I have this variable here, set in a .yaml variables file
patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar'
I want my patch_plan_week_and_day
variable to be set dynamically, based on role
and environment
which are 2 other variables set elsewhere (doesn't matter now) outside this variables file.
For instance, I will explain 3 cases:
- If
role = 'master'
andenvironment = 'srvb'
thenpatch_plan_week_and_day = 'Week1_Monday'
and thus the end result ofpatch_plan = 'foo-Week1_Monday-bar'
. - If
role != 'master'
andenvironment = 'srvb'
thenpatch_plan_week_and_day = 'Week1_Tuesday'
and thus the end result ofpatch_plan = 'foo-Week1_Tuesday-bar'
- If
role = 'slave'
andenvironment = 'pro'
thenpatch_plan_week_and_day = 'Week3_Wednesday'
and hus the end result ofpatch_plan = 'foo-Week3_Wednesday-bar'
This is the idea of the code:
patch_plan: 'foo-{{ patch_plan_week_and_day }}-bar'
# Patch Plans
## I want something like this:
# case 1
patch_plan_week_and_day: Week1_Monday
when: role == 'master' and environment == 'srvb'
# case 2
patch_plan_week_and_day: Week1_Tuesday
when: role != 'master' and environment == 'srvb'
# case 3
patch_plan_week_and_day: Week3_Wednesday
when: role == 'slave' and environment == 'pro'
I have 14 cases in total.
CodePudding user response:
Put the logic into a dictionary. For example,
patch_plan_week_and_day_dict:
srvb:
master: Week1_Monday
default: Week1_Tuesday
pro:
slave: Week3_Wednesday
default: WeekX_Wednesday
Create the project for testing
shell> tree .
.
├── ansible.cfg
├── hosts
├── pb.yml
└── roles
├── master
│ ├── defaults
│ │ └── main.yml
│ └── tasks
│ └── main.yml
├── non_master
│ ├── defaults
│ │ └── main.yml
│ └── tasks
│ └── main.yml
└── slave
├── defaults
│ └── main.yml
└── tasks
└── main.yml
10 directories, 9 files
shell> cat ansible.cfg
[defaults]
gathering = explicit
inventory = $PWD/hosts
roles_path = $PWD/roles
retry_files_enabled = false
stdout_callback = yaml
shell> cat hosts
localhost
shell> cat pb.yml
- hosts: localhost
vars:
patch_plan_week_and_day_dict:
srvb:
master: Week1_Monday
default: Week1_Tuesday
pro:
slave: Week3_Wednesday
default: WeekX_Wednesday
roles:
- "{{ my_role }}"
The code of all roles is identical
shell> cat roles/master/defaults/main.yml
patch_plan_role: "{{ (my_role in patch_plan_week_and_day_dict[env].keys()|list)|
ternary(my_role, 'default') }}"
patch_plan_week_and_day: "{{ patch_plan_week_and_day_dict[env][patch_plan_role] }}"
shell> cat roles/master/tasks/main.yml
- debug:
var: patch_plan_week_and_day
Example 1.
shell> ansible-playbook pb.yml -e env=srvb -e my_role=master
...
patch_plan_week_and_day: Week1_Monday
Example 2.
shell> ansible-playbook pb.yml -e env=srvb -e my_role=non_master
...
patch_plan_week_and_day: Week1_Tuesday
Example 3.
shell> ansible-playbook pb.yml -e env=pro -e my_role=slave
...
patch_plan_week_and_day: Week3_Wednesday
CodePudding user response:
A lot of considerations here ...
It seems you try to use Ansible as a programming language which it isn't. You've started to implement something without any description about your use case and what is actually the problem. The given example looks like an anti-pattern.
... set dynamically, based on role and environmentv ...
It is in fact "static" and based on the properties of the systems. You only try to generate the values at runtime. Timeslots when patches can or should be applied (Patch Window) are facts about the system and usually configured within the Configuration Management Database (CMDB). So this kind of information should be already there, either in a database or within the Ansible inventory or as a Custom fact on the system itself.
... which are 2 other variables set elsewhere (doesn't matter now) outside this variables file. ...
Probably it does matter and maybe you could configure the Patch Cycle or Patch Window there.
By pursuing your approach further you'll mix up Playbook Logic with Infrastructure Description or Configuration Properties leading fast into less readable and probably future unmaintainable code. You'll deny yourself the opportunity to maintain the system configuration within a Version Control System (VCS), CMDB or the inventory.
Therefore avoid CASE, SWITCH and IF THEN ELSE ELSEIF structures and describe the desired state of your systems instead.
Some Further Readings
In addition to the sources already given.