问题
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
回答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"]
回答2:
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.
来源:https://stackoverflow.com/questions/59773518/key-value-pair-mapping-in-ansible-to-pass-run-the-role-with-the-appropriate-valu