问题
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