How can i fix this playbook - automation

how can i use service_name in the condition, i tryed with set_fact but it doesn't work.
- name: "create systemd service"
template:
src: "service.j2"
dest: "/etc/systemd/system/{{ systemd_service[item].service_name | default(item) }}.service"
set_fact: service_name= "{{ systemd_service[item].service_name }}"
with_items: "{{ systemd_service | list }}"
when:
- service_name == "oracle"

set_fact is the name of a module; it's not an argument to the template module. Fortunately, you don't need it; you can just write:
- name: "create systemd service"
template:
src: "service.j2"
dest: "/etc/systemd/system/{{ systemd_service[item].service_name | default(item) }}.service"
with_items: "{{ systemd_service | list }}"
when:
- systemd_service[item].service_name == "oracle"
- env_vars.stdout.find('ORACLE=True') != -1

Related

Retrieve variable values from var file in ansible playbook

Need some help to retrieve child values from var file.
Below is my var file
api_user: root
api_password: !vault |
$ANSIBLE_VAULT;1.2;AES256;isi33835326238346338613761366531376662613865376263656262
6138
Huston:
onefs_host: 10.88.55.00
Phoenix:
onefs_host: 10.76.52.01
Below is my playbook
---
- name: isi_increase
hosts: localhost
connection: local
vars_files:
- isilonvars.yml
tasks:
- name: Print
debug:
msg:
- "{{ Huston.onefs_host }}"
- "{{ api_user }}"
- "{{ api_password }}"
This code works perfectly
TASK [Print] ********************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"10.88.55.00",
"root",
"Sh00tm3!"
]
}
But as per my requirement i have to retrieve onefs_host IP as per location in my playbook. I am using extra vars here -e "location=Huston"
- name: Print
debug:
msg:
# - "{{ wcc.onefs_host }}"
- "{{ {{location}}.onefs_host }}"
- "{{ api_user }}"
- "{{ api_password }}"
I am getting the below error.
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: expected token ':', got '}'. String: {{ {{isilon_location}}.onefs_host }}"}
Can you try this way
- name: Print
debug:
msg:
- "{{ vars[location]['onefs_host'] }}"
- "{{ api_user }}"
- "{{ api_password }}"

Ansible use variables in tags option

my ansible tasks/main.yml looks like this atm:
---
- name: Create Directories
file:
path: "{{ item.path }}"
recurse: yes
owner: "{{ item.owner | default(\"nobody\") }}"
group: "{{ item.group | default(\"nogroup\") }}"
state: directory
with_items:
- "{{ app_dirs }}"
- name: Move Templates
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner | default(\"nobody\") }}"
group: "{{ item.group | default(\"nogroup\") }}"
with_items: "{{ app_templates }}"
- name: Move Dependencies
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ item.owner | default(\"nobody\") }}"
group: "{{ item.group | default(\"nogroup\") }}"
with_items: "{{ app_dependencies }}"
I have to move a couple of dependencies and templates to the remote machine. Now I need to add some conditionals or tags so we can decide if we want to copy all depedencies or just a few of them. I tried it like this:
- name: Create Directories
file:
path: "{{ item.path }}"
recurse: yes
owner: "{{ item.owner | default(\"nobody\") }}"
group: "{{ item.group | default(\"nogroup\") }}"
state: directory
tags: "{{ item.tag }}"
with_items:
- "{{ app_dirs }}"
But Ansible throws this error: ERROR! 'item' is undefined. Probably the tags option has to be inside the "file" block so with_items knows where to item.tag from. But the tags option has to be intended like that. Is there a way to use variables for the tags options? I actually liked the structure of this tasks/main.yml, it was easier to handle all variables in one place. My other idea was to create blocks with when conditions like this:
tasks:
- name: Install app1
block:
- name: Create Directory
file:
....
- name: Move Templates
template:
....
- name: Move Dependencies
copy:
....
tags:
- app1
- name: Install app2
block: .....
With this approach I can't store all variables as a dictonary like before. If there is no other way I'll use the block approach but I hope that someone has a better idea. Thanks in advance!

Iterating over variables in Ansible

I'm trying to use the same set of variables for the various modules in my play (with some slight variations as you will see).
It seemed logical to include them as 'vars' at the top of my play, but i then have trouble referring to them later on. So far i've done this :
- name: destruction instance sur GCP
hosts: localhost
gather_facts: no
vars:
gcp_project: ansible-test-248409
gcp_cred_kind: serviceaccount
gcp_cred_file: /google/service-accounts/ansible-test-248409-fbadc808948d.json
zone: europe-west1-b
region: europe-west1
machine_type: n1-standard-1
machines:
- webserver-1
- webserver-2
- webserver-3
- devops-1
- devops-2
tasks:
- name: destruction des machines
gcp_compute_instance:
name: "{{ machines }}"
state: absent
zone: "{{ zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
- name: destruction des disques
gcp_compute_disk:
name: "{{ machines }}-disk"
state: absent
zone: "{{ zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
Which gives me this error message
[WARNING]: The value ['webserver-1', 'webserver-2', 'webserver-3', 'devops-1', 'devops-2'] (type list) in a string field was
converted to u"['webserver-1', 'webserver-2', 'webserver-3', 'devops-1', 'devops-2']" (type string). If this does not look like what
you expect, quote the entire value to ensure it does not change.
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Invalid JSON response with error: <HTML>\n<HEAD>\n<TITLE>Bad Request</TITLE
>\n</HEAD>\n<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\">\n<H1>Bad Request</H1>\n<H2>Error 400</H2>\n</BODY>\n</HTML>\n"}
Using 'lookup' or 'query' doesn't work either. Can anyone see what i'm missing ?
you use with_items: option.
tasks:
- name: destruction des machines
gcp_compute_instance:
name: "{{ item }}"
state: absent
zone: "{{ zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
scopes:
- https://www.googleapis.com/auth/compute
with_items: "{{ machines }}"

Deploy TCK Kapacitor conf

I need to deploy TICK.
How do you use variables in kapacitor.conf?
EX: username = "{{ admin }}"
I have a kapacitor.conf with variables to replace, and I have a file default.yml with variables.
Kapacitor.conf
username = "{{ admin }}"
password = "{{ admin_password }}"
default.yml
---
admin: admin
admin_password: admin
An option would be to use lineinfile. Given the variables
> cat default.yml
username: admin
password: admin_password
the playbook below
- hosts: localhost
vars_files:
- default.yml
tasks:
- lineinfile:
path: Kapacitor.conf
regexp: "^{{ item.key }}:"
line: "{{ item.key }}:{{ item.value }}"
create: yes
loop:
- {key: 'admin', value: "{{ username }}"}
- {key: 'admin_password', value: "{{ password }}"}
gives:
> cat Kapacitor.conf
admin:admin
admin_password:admin_password
next (for some first) option would be template.

In an Ansible playbook, what is a better way to iterate over a list of objects and call a different role depending on that object's data?

I am using Ansible to read in a YAML file containing a list of dictionaries. I then need to iterate through this list and call a different role depending on data within each list object. I have a solution that is working, but it seems so kludgy to me, that I wanted to find out if there was a better way.
I have defined a YAML file structure to provide the input to my playbook and I read that file into a variable with the include_vars module. I then use with_items to loop through the array one time for each role that I need to support (currently 6, but it may increase) and use a when clause to only include_role when the data in the object is correct for that role.
Code
Sample Input file:
---
objects:
- type: type1
name: obj_type1
- type: type2
name: obj_type2
- type: type3
name: obj_type3
Sample Playbook:
---
- hosts: cf-host
gather_facts: False
vars:
objects_file: ''
tasks:
- name: Read objects_file
include_vars:
file: "{{ objects_file }}"
- name: Handle type1
include_role:
name: type1_role
vars:
- type1_role_name: "{{ item.name }}"
with_items: "{{ objects }}"
when: item.type == "type1"
- name: Handle type2
include_role:
name: type2_role
vars:
- type2_role_name: "{{ item.name }}"
with_items: "{{ objects }}"
when: item.type == "type2"
- name: Handle type3
include_role:
name: type3_role
vars:
- type3_role_name: "{{ item.name }}"
with_items: "{{ objects }}"
when: item.type == "type3"
Sample Role:
---
- name: Print name
debug:
msg: "Type 1 - Name is {{ type1_role_name }}"
The other roles are the same, but have msg set to "Type X - Name is {{ typeX_role_name }}" instead.
This leads to a skipped task for every item in the list when it does not match the type corresponding to the role. It also means that I have to loop through the same list multiple times (as many as types that I need to support). As mentioned, I already need to support 6 different types and that number may grow.
This solution seems like it would scale very poorly and would have terrible performance as the list and supported types become larger and larger. Is there a better way to do what I need to do?
Better Solution
Using this answer: https://stackoverflow.com/a/53859851/9744341 as a base, I was able to come up with this as a better solution that I am happy with. Here it is in case anyone else has the same needs:
Sample Playbook:
---
- hosts: cf-host
gather_facts: False
vars:
objects_file: ''
role_name_lookup:
type1:
role_name: type1_role
tasks_from: type1_tasks
type2:
role_name: type2_role
tasks_from: type2_tasks
type3:
role_name: type3_role
tasks_from: main
tasks:
- name: Read objects_file
include_vars:
file: "{{ objects_file }}"
- name: Call roles to create infra
include_role:
name: "{{ role_name_lookup[item.type].role_name }}"
tasks_from: "{{ role_name_lookup[item.type].tasks_from }}"
vars:
inputs: "{{ item }}"
with_items: "{{ objects }}"
Sample Role:
---
- name: Print name
debug:
msg: "Type 1 - Name is {{ inputs.name }}"
The other roles are the same, but have msg set to Type X - Name is {{ inputs.name }} instead.
Would this code fit your purpose?
- name: Include roles
include_role:
name: "{{ item.type }}_role"
with_items: "{{ objects }}"
- name: Print name
debug:
msg: "{{ item.type }} - Name is {{ role_name }}"