1

I am new to ansible. I have a small scenario. So I pass the name of the branch using ansible when I run it. In my play book I have:

# Deploy docker container
- include_role:
    name: devops/deployment.docker
  vars:
    docker_name: "docker name is based on the branch id develop dev if UAT test if master then it should be prod"
  when: build_type in "develop master UAT"

and in devops/deployment.docker I have a role which deploy a docker image.

- name: push docker container
  docker_image:
    name: "{{ docker.registery }}/docker_name"
    source: build
    build: 
      nocache: true
      path: "{{ travis.base_build_path }}"
    tag: "{{ ucd.component_version }}"
    push: yes

So I send build_type as develop,UAT or master when I run the ansible this role will be called. Now there is an issue:

I need to build my image based on the branch so the code needs to be intelligent and when I send develop it should go search for the key assigned to develop and get the related docker name and build it. something similar to this:

{
 develop: {
  dockerName:dev
 },
 master: {
  dockerName: prod
  },
 UAT: {
   dockerName: test
 }
}

If anyone help me how to do it in ansible I really appreciate it

Learner
  • 1,686
  • 4
  • 19
  • 38

2 Answers2

1

Here is something that works, but there are several ways this could be achieved.

Assuming you are passing variables from the command line while running ansible-playbook.

This would be your command, which you might be knowing already.

ansible-playbook mydocker-playbook.yml --extra-vars "build_type=develop"

Following is an example how you could achieve this.

mydocker-playbook.yaml

---
- name: Docker deployment
  hosts: devops
  become: yes
  roles:
    - devops-role

And your task could be something like this

- name: push docker container
  docker_image:
    name: "{{ docker.registery }}/{{item.name}}"
    source: build
    build: 
      nocache: true
      path: "{{ travis.base_build_path }}"
    tag: "{{ ucd.component_version }}"
    push: yes
  when: build_type == item.type
  with_items:
    - { name: "dev", type: "develop" }
    - { name: "master", type: "prod" }
    - { name: "UAT", type: "test" }

The task iterates over the given list. But executes only when the build_type is one of the values of type. And assigns your docker name with {{item.name}} i.e. either dev, or master, or UAT.

Again, there are several ways we can do this, this is just one of them.

Hope this is helpful.

BinaryMonster
  • 1,118
  • 7
  • 10
1

TLDR;

- name: push docker container
  vars:
    docker_name: "{{ vars[build_type].dockerName }}"
  docker_image:
    name: "{{ docker.registery }}/{{ docker_name }}"
    source: build
    build: 
      nocache: true
      path: "{{ travis.base_build_path }}"
    tag: "{{ ucd.component_version }}"
    push: yes

Vars notation

Ansible has 2 notations to access dict items:

  • The dot notation: {{ my_var.my_key.my_subkey }}
  • The bracket notation: {{ my_var['my_key']['my_subkey'] }}

You can mix those two notations as you wish

  • {{ my_var.my_key['my_subkey'] }}
  • {{ my_var['my_key'].my_subkey }}

Note that lists can be accessed the same way using their index:

  • {{ my_list.0 }}
  • {{ my_list[0] }}

Vars "access point"

Each of your environment definition is a first level var. You can normally call those vars in a template expression directly, e.g. {{ master.dockerName }}. But those vars are also available through the first level vars dict so the following is exactly equivalent {{ vars.master.dockerName }}.

Finally...

Knowing the above and that you are sending the name of the relevant key in the build_type variable, you can get the expected value with: {{ vars[build_type].dockerName }}


Unrelated to your current question

Concerning your include_role condition:

when: build_type in "develop master UAT"

Note that this will work for the value "develop" as you expect, but will also match for "AT", "mast", "devel" or even "op mas". That might break the rest of your operations in case of a typo.

To make sure you match the exact word, put your matches in a list and the comparison will move from "is it a substring of" to "is it an element of"

when: build_type in ["develop", "master", "UAT"]
Zeitounator
  • 38,476
  • 7
  • 53
  • 66
  • Thanks a lot. Does this work with any version of ansible? – Learner Jan 17 '20 at 03:57
  • I am going to try it but first I wanted to double check with you. I will let you know how it gores :) – Learner Jan 17 '20 at 13:23
  • You're on SO my friend. People here expect you to try first then ask a question if your are having a problem ;) – Zeitounator Jan 17 '20 at 13:26
  • Another question: how do you define nested variable as my example in ansible my_var you defined? – Learner Jan 17 '20 at 13:38
  • Is this example good to follow? https://docs.ansible.com/ansible/latest/plugins/lookup/subelements.html – Learner Jan 17 '20 at 13:43
  • Here is my list: { develop: { dockerName:dev }, master: { dockerName: prod }, UAT: { dockerName: test } } – Learner Jan 17 '20 at 13:44
  • This is not a list. It is a dictionary, the same that you already posted in your question. And I took for granted it was declared as top level vars. If this is not the case, please review [How to ask](https://stackoverflow.com/help/how-to-ask), [Creating an MCVE](https://stackoverflow.com/help/minimal-reproducible-example), then edit your question with the relevant details. Regarding creating nested var, you can have a look at [learn yml in y minutes](https://learnxinyminutes.com/docs/yaml/) – Zeitounator Jan 17 '20 at 14:25
  • Actually worked like a charm and I should say you are the best and awesome :D Your answer was one of the most clear and easy to understand one based on my experience in stackoverflow – Learner Jan 17 '20 at 15:26
  • Also I have another question if you can kindly take a look https://stackoverflow.com/questions/59794199/import-an-inventory-fole-to-another-in-ansible – Learner Jan 17 '20 at 20:07