ansible updating a YAML file using set_fact/update_fact - ansible

My ansible project consists of 6 roles (app, db, init, ror, tick, web). Each role represents the installation of one component of the system. Each device keeps track of which roles have been installed using the file "/etc/ansible/ansible-install-state.yml". It's initial contents are:
# ansible-install-state.yml
#
#
# This file is maintained by Ansible
# Please leave it alone, or accept the consequences!
#
roles:
app:
installed: false
db:
installed: false
init:
installed: false
ror:
installed: false
tick:
installed: false
web:
installed: false
At the completion of the 'init' role, I want to process the file to update the installed state to 'true'. I do that with the following call. (For testing, I'm also setting 'ror: true' and adding a new role 'new: unknown'
- name: System Init | Process ansible_install_state
ansible.builtin.include_tasks: process_ansible_install_state.yml
with_items:
- role: { key: init, value: true }
- role: { key: ror, value: true }
- role: { key: new, value: unknown}
Updating existing roles went fairly smoothly, but adding a new role did not. I finally got it to work by first adding the role itself, essentially 'new: {}', then modifying it again to add the 'installed: unknown' part. Although this does work, I can't help but believe there's a better way - a way to do it all at once. Following is the process_enable_install_state.yml file.
---
# process_ansible_install_state.yml
#
#------------------------- Process Ansible Install State File
#
- name: display variable
debug:
var: item
# See https://stackoverflow.com/questions/32994002/is-there-a-yaml-editing-module-for-ansible
- name: Ansible Install State | Read ansible-install-state.yml
ansible.builtin.slurp:
path: "/etc/ansible/ansible-install-state.yml"
register: install_state
- name: Ansible Install State | Decode and save yaml as fact
ansible.builtin.set_fact:
my_roles: "{{ install_state['content'] | b64decode | from_yaml }}"
register: its_a_fact
- name: Ansible Install State | Save the new ROLE block
block:
- name: Ansible Install State | Save the new role
ansible.utils.update_fact:
updates:
- path: my_roles.roles.{{ item.role.key }}
value: {}
register: updated
# Update_fact does not update 'in place', so we need to save it as a fact
- name: Ansible Install State | Update the saved 'fact'
ansible.builtin.set_fact:
my_roles: "{{ updated.my_roles}}"
when: my_roles.roles[item.role.key] is undefined
- name: debug
debug:
var: updated
- name: Ansible Install State | Update the role's installed state
ansible.utils.update_fact:
updates:
- path: my_roles.roles.{{ item.role.key }}.installed
value: "{{item.role.value}}"
register: updated
- name: debug
debug:
var: updated
# Update_fact does not update 'in place', so we need to save it as a fact
- name: Ansible Install State | Save modified as 'fact'
ansible.builtin.set_fact:
my_roles: "{{ updated.my_roles}}"
- name: Ansible Install State | Write Yaml File
ansible.builtin.copy:
content: '{{ my_roles | to_nice_yaml }}'
dest: "/etc/ansible/ansible-install-state.yml"
- name: Ansible Install State | Insert Header Comments
ansible.builtin.blockinfile:
path: "/etc/ansible/ansible-install-state.yml"
insertbefore: BOF
marker: "#{mark}"
marker_begin: "-------------------------------------------"
marker_end: "-------------------------------------------"
block: |
# ansible-install-state.yml
#
#
# This file is maintained by Ansible
# Please leave it alone, or accept the consequences!
#
#
This successfully produced...
# ansible-install-state.yml
#
#
# This file is maintained by Ansible
# Please leave it alone, or accept the consequences!
#
#
#-------------------------------------------
roles:
app:
installed: false
db:
installed: false
init:
installed: true
new:
installed: unknown
ror:
installed: true
tick:
installed: false
web:
installed: false
deploy#rpi-tick2:/etc/ansible $

Related

Can I import parameters set in azure-pipeline.yml into playbook.yml

I have two yaml files. One is azure-pipeline.yml
name: test-resources
trigger: none
resources:
repositories:
- repository: pipeline
type: git
name: test-templates
parameters:
- name: whetherYesOrNo
type: string
default: Yes
values:
- Yes
- No
extends:
template: pipelines/ansible-playbook-deploy.yml#pipeline
parameters:
folderName: test-3scale
As for this file, when I run the pipeline, I could choose Yes or No as options before running it.
The other one is the playbook.yml for Ansible
- hosts: localhost
connection: local
become: true
vars_files:
- test_service.yml
- "vars/test.yml"
collections:
- test_collection
tasks:
- name: Find out playbooks pwd
shell: pwd
register: playbook_path_output
no_log: false
- debug: var=playbook_path_output.stdout
- name: echo something
shell: echo 'test this out'
register: playbook_ls_content_output
no_log: false
- debug: var=playbook_ls_content_output.stdout
I wish to add a condition in the playbook.yml task, so that
When I choose "Yes" when running the pipeline, task named "echo something" will run, but if I choose "No", this task will be skipped. I am really new in yaml syntax and logic. Could someone help? Many thanks!
These runs successfully on my side(I can judge the condition with no problem, at compile time it will be expanded.):
azure-pipeline.yml
trigger: none
parameters:
- name: whetherYesOrNo
type: string
default: Yes
values:
- Yes
- No
extends:
template: pipelines/ansible-playbook-deploy.yml
parameters:
whetherYesOrNo: ${{parameters.whetherYesOrNo}}
ansible-playbook-deploy.yml
parameters:
- name: whetherYesOrNo
type: string
default: No
steps:
- ${{ if eq(parameters.whetherYesOrNo, 'Yes') }}:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
Write-Host "Hello World"
Repository structure on my side:
If Yes:
If No:

run yz tasks only if x task condition is met in ansible

Team,
I have 10 tasks and I want to run 2-10 only if condition in task1 is met.
- name: 1Check if the node needs to be processed
stat: /tmp/fscache-cleaned-up1.log
register: dc_status
- name: 2Check if the node needs to be processed
stat: /tmp/fscache-cleaned-up2.log
register: dc_status
failed_when: dc_status.stat.exists
..
..
..
You have to use "path" in your stat module call and "block" for combining dependant tasks, like this:
- name: Check if the node needs to be processed
stat:
path: /tmp/fscache-cleaned-up1.log
register: dc_status
- name: Run this only when the log file exists
block:
- name: Install something
yum:
name:
- somepackage
state: present
- name: Apply a config template
template:
src: templates/src.j2
dest: /etc/foo.conf
- name: Start a service and enable it
service:
name: bar
state: started
enabled: True
when:
- dc_status.stat.exists
- dc_status.stat.is_file
Additional information: ansible stat module, block usage

Ansible Idempotence for elasticsearch.yml

New ansible user (v2.3) and pulled playbook for github but not understanding idempotence. Once elasticsearch is installed and started with playbook, I now want to be able to just modify or add an es_config parm and then rerun playbook expecting an updated elasticsearch.yml config file and elasticsearch restarted. That include_roles elasticsearch however is skipped on rerun and not sure what to modify to change that.
ansible-playbook --ask-become-pass -vv elk.yml
elk.yml
---
#
# Playbook to install the ELK stack
#
- hosts: servers
strategy: debug
remote_user: ansible
become: yes
become_user: root
tasks:
- debug: msg="elk main"
- include_role:
name: java
name: elasticsearch
name: kibana
name: nginx
name: logstash
vars:
es_instance_name: "node1"
es_config: {
discovery.zen.ping.unicast.hosts: "logstash-2, logstash-3",
network.host: _eno1_,
cluster.name: logstash,
node.name: "{{ ansible_hostname }}",
http.port: 9200,
transport.tcp.port: 9300,
node.data: true,
node.master: true,
bootstrap.memory_lock: true,
index.number_of_shards: 3,
index.number_of_replicas: 1
}
es_major_version: "6.x"
es_version: "6.2.1"
es_heap_size: "26g"
es_cluster_name: "logstash"
roles/elasticsearch/tasks/main.yml
---
- name: os-specific vars
include_vars: "{{ansible_os_family}}.yml"
tags:
- always
- debug: msg="es parms"
- name: check-set-parameters
# include: elasticsearch-parameters.yml
include_tasks: elasticsearch-parameters.yml
tags:
- always
#- include: java.yml
# when: es_java_install
# tags:
# - java
#- include: elasticsearch.yml
- include_tasks: elasticsearch.yml
roles/elasticsearch/tasks/elasticsearch.yml
---
- name: Include optional user and group creation.
when: (es_user_id is defined) and (es_group_id is defined)
include_tasks: elasticsearch-optional-user.yml
- name: Include specific Elasticsearch
include_tasks: elasticsearch-Debian.yml
when: ansible_os_family == 'Debian'
roles/elasticsearch/tasks/elasticsearch-Debian.yml
---
- set_fact: force_install=no
- set_fact: force_install=yes
when: es_allow_downgrades
- name: Debian - Install apt-transport-https to support https APT downloads
become: yes
apt: name=apt-transport-https state=present
when: es_use_repository
- name: Debian - Add Elasticsearch repository key
become: yes
apt_key: url="{{ es_apt_key }}" state=present
when: es_use_repository and es_apt_key
- name: Debian - Add elasticsearch repository
become: yes
apt_repository: repo={{ item.repo }} state={{ item.state}}
with_items:
- { repo: "{{ es_apt_url_old }}", state: "absent" }
- { repo: "{{ es_apt_url }}", state: "present" }
when: es_use_repository
- name: Debian - Include versionlock
include: elasticsearch-Debian-version-lock.yml
when: es_version_lock
- name: Debian - Ensure elasticsearch is installed
become: yes
apt: name=elasticsearch{% if es_version is defined and es_version != ""
%}={{$
when: es_use_repository
register: debian_elasticsearch_install_from_repo
notify: restart elasticsearch
- name: Debian - Download elasticsearch from url
get_url: url={% if es_custom_package_url is defined %}{{
es_custom_package_ur$
when: not es_use_repository
- name: Debian - Ensure elasticsearch is installed from downloaded package
become: yes
apt: deb=/tmp/elasticsearch-{{ es_version }}.deb
when: not es_use_repository
register: elasticsearch_install_from_package
notify: restart elasticsearch
roles/elasticsearch/tasks/elasticsearch-parameters.yml
# Check for mandatory parameters
- fail: msg="es_instance_name must be specified and cannot be blank"
when: es_instance_name is not defined or es_instance_name == ''
- fail: msg="es_proxy_port must be specified and cannot be blank when
es_proxy_$
when: (es_proxy_port is not defined or es_proxy_port == '') and
(es_proxy_hos$
- debug: msg="WARNING - It is recommended you specify the parameter
'http.port'"
when: es_config['http.port'] is not defined
- debug: msg="WARNING - It is recommended you specify the parameter
'transport.$
when: es_config['transport.tcp.port'] is not defined
- debug: msg="WARNING - It is recommended you specify the parameter
'discovery.$
when: es_config['discovery.zen.ping.unicast.hosts'] is not defined
#If the user attempts to lock memory they must specify a heap size
- fail: msg="If locking memory with bootstrap.memory_lock a heap size must
be s$
when: es_config['bootstrap.memory_lock'] is defined and
es_config['bootstrap.$
#Check if working with security we have an es_api_basic_auth_username and
es_ap$
- fail: msg="Enabling security requires an es_api_basic_auth_username and
es_ap$
when: es_enable_xpack and ("security" in es_xpack_features) and
es_api_basic_$
- set_fact: file_reserved_users={{ es_users.file.keys() | intersect
(reserved_x$
when: es_users is defined and es_users.file is defined and
(es_users.file.key$
- fail:
msg: "ERROR: INVALID CONFIG - YOU CANNOT CHANGE RESERVED USERS THROUGH THE$
when: file_reserved_users | default([]) | length > 0
- set_fact: instance_default_file={{default_file |
dirname}}/{{es_instance_name$
- set_fact: instance_init_script={{init_script | dirname
}}/{{es_instance_name}$
- set_fact: conf_dir={{ es_conf_dir }}/{{es_instance_name}}
- set_fact: m_lock_enabled={{ es_config['bootstrap.memory_lock'] is defined
and$
#TODO - if transport.host is not local maybe error on boostrap checks
#Use systemd for the following distributions:
#Ubuntu 15 and up
#Debian 8 and up
#Centos 7 and up
#Relies on elasticsearch distribution installing a serviced script to
determine$
- set_fact: use_system_d={{(ansible_distribution == 'Debian' and
ansible_distri$
- set_fact: instance_sysd_script={{sysd_script | dirname
}}/{{es_instance_name}$
when: use_system_d
#For directories we also use the {{inventory_hostname}}-{{ es_instance_name
}} $
- set_fact: instance_suffix={{inventory_hostname}}-{{ es_instance_name }}
- set_fact: pid_dir={{ es_pid_dir }}/{{instance_suffix}}
- set_fact: log_dir={{ es_log_dir }}/{{instance_suffix}}
- set_fact: data_dirs={{ es_data_dirs | append_to_list('/'+instance_suffix)
}}
formatting issue with include_role. Fixed problem with one role per include as follows:
- include_role:
name: java
- include_role:
name: elasticsearch
and so forth.

Registering multiple variables in a loop

I have a variable yaml file:
---
apps:
- client
- node
- gateway
- ic
- consul
and this task:
- name: register if apps exists
stat: path="/etc/init.d/{{ item }}"
with_items: apps
register: "{{ item.stat.exists }}exists"
I need to end up with a variable for each app with a value of true or false whether the file exists or not:
clientexists = true
nodeexists = true
gatewayexists = false
icexists = true
consulexists = false
For some reason, the item and exists concat is not working.
How can I achieve that??
Try this hope this will help you out. While looping in Stats.yml then msg field will contain your desired output.
Variables.yml Here we are defining variables
---
apps:
- client
- node
- gateway
- ic
- consul
Stats.yml
---
- hosts: localhost
name: Gathering facts
vars_files:
- /path/to/variables.yml
tasks:
- name: "Here we are printing variables"
debug:
msg: "{{apps}}"
- name: "Here we are gathering stats and registering it"
stat:
path: "/etc/init.d/{{item}}"
register: folder_stats
with_items:
- "{{apps}}"
- name: "Looping over registered variables, Its msg field will contain desired output"
debug:
msg: "{{item.invocation.module_args.path}}: {{item.stat.exists}}"
with_items:
- "{{folder_stats.results}}"
...
folder_stats will contain whole result, for individually referring to single - single result You can use it like this in you playbook.
folder_stats.results[0].stat.exists
folder_stats.results[1].stat.exists
folder_stats.results[2].stat.exists
folder_stats.results[3].stat.exists

Ansible : Trouble accessing Register VAlue

I am writing an ansible playbook that will :
log into a windows box
check if the version of the application i am deploying exists already
downloads the application from git
extracts the app's zip file
moves it to the correct directory
I am having a bunch of trouble on a section of the code where i need to find the extracted directory. I am extracting a GIT zip, and of course, through Github the zip file contains the git hash directory. What I do is i look for this directory through a simple find-like command in windows. The problem is that during debug, i can see the results in stdout_lines ... but in practice, it doesn't seem to work.
Here is the code:
---
# Register our work path to do work in
- name: Registering {{apm_work_path}} as our working path
tags: install
win_stat: path={{apm_work_path}}
register: my_apmworkpath
# First check to see if an agent is already installed in our
# destination. We want to make sure we dont install multiple
# agents
- name: Checking if {{apm_root_path}} path exists on our remote server
tags: install
win_stat: path={{apm_root_path}}
register: my_apmrootpath
# Check if the apm agent is installed in the root path
- name: Checking if {{apm_root_path}}\\{{apm_install_path}} path exists
tags: install
win_stat: path={{apm_root_path}}/{{apm_install_path}}
register: my_apminstallpath
# Check if the apm version is installed in the root path
- name: Checking if {{apm_version}} path exists
tags: install
win_stat: path={{apm_root_path}}\\{{apm_install_path}}\\{{apm_version}}
register: my_apmversionpath
# We also want to make sure that we keep track of the path
# that we want our agent to be placed
- name: An agent already exists on server
tags: install
debug: msg="APM {{apm_version}} is already installed under {{apm_install_path}}"
when: my_apminstallpath.stat.exists == true
# Create our work directory
- name: Creating Work directory
tags: install
win_file: path={{apm_work_path}} state=directory mode=0755
when: my_apmworkpath.stat.exists == false
# Create our application directory
- name: Creating APM Agent directory
tags: install
win_file: path={{apm_root_path}}\\{{apm_install_path}} state=directory mode=0755
when: my_apminstallpath.stat.exists == false
# Create our versioning directory
- name: Create APM version directory
tags: install
win_file: path={{apm_root_path}}\\{{apm_install_path}}\\{{apm_version}} state=directory mode=0775
when: my_apmversionpath.stat.exists == false
# Export our agent from our version control repo (GIT)
- name: Exporting Agent from GIT
tags: install
win_get_url:
url: http://git.sys.a.com/APM/apm-agent-{{apm_version}}-base-win/repository/archive.zip?ref=master
dest: "{{apm_work_path}}\\agent.zip"
when: my_apmversionpath.stat.exists == false
# Make sure we succesfully got our agent downloaded
- name: Checking our agent download
tags: install
win_stat: path={{apm_work_path}}\\agent.zip
register: my_agentarchive
# Create the base-nix directory
- name: Creating base-nix directory
tags: install
win_file: path={{apm_root_path}}\\{{apm_install_path}}\\{{apm_version}}\\base-win state=directory mode=0755
when:
- my_apmversionpath.stat.exists == false
- my_agentarchive.stat.exists == true
# Extract our GIT tarball to our new directory
- name: Extracting Agent
tags: install
win_unzip:
src: "{{apm_work_path}}\\agent.zip"
dest: "{{apm_work_path}}"
rm: True
when:
- my_apmversionpath.stat.exists == false
- my_agentarchive.stat.exists == true
###############################################################
##### THIS SECTION ############################################
# Get the extract directory
- name: Locate the Extracted Directory
tags: install
win_shell: for /d %d in (*apm-agent*) do echo %d
args:
executable: cmd
chdir: "{{apm_work_path}}"
register: extout
###### UNABLE TO SEE RESULTS HERE ############
- debug: msg={{ item }}
with_items: extout.stdout_lines
# Copy data from our work directory to the base-win directory
- name: Migrate Agent Files
tags: install
win_copy:
src: "{{apm_work_path}}\\{{ item }}\\"
dest: "{{apm_root_path}}\\{{apm_install_path}}\\{{apm_version}}\\base-win"
with_items:
extout.stdout_lines
ignore_errors: no
when:
- my_apmversionpath.stat.exists == false
- my_agentarchive.stat.exists == true
# Now create a symbolic link for the agent path
- name: Creating Symlink
tags: install
win_file: src={{apm_root_path}}\\{{apm_install_path}}\\{{apm_version}}\\base-win dest={{apm_root_path}}\\{{apm_install_path}}\\base-win state=link
when:
- my_apmversionpath.stat.exists == false
- my_agentarchive.stat.exists == true
# And cleanup after ourselves
#- name: Removing downloaded files
# tags: install
# win_file: path={{apm_work_path}} state=absent
# when:
# - my_apmversionpath.stat.exists == false
# - my_agentarchive.stat.exists == true
Relevant Section
###############################################################
##### THIS SECTION ############################################
# Get the extract directory
- name: Locate the Extracted Directory
tags: install
win_shell: for /d %d in (*apm-agent*) do echo %d
args:
executable: cmd
chdir: "{{apm_work_path}}"
register: extout
###### UNABLE TO SEE RESULTS HERE ############
- debug: msg={{ item }}
with_items: extout.stdout_lines
I can see the values of my register
changed: [ciwsdbxd8559.silver.com] => {
"changed": true,
"cmd": "for /d %d in (*apm-agent*) do echo %d",
"delta": "0:00:00.062173",
"end": "2016-11-06 07:56:51.816995",
"invocation": {
"module_name": "win_shell"
},
"rc": 0,
"start": "2016-11-06 07:56:51.754822",
"stderr": "",
"stdout": "\r\nE:\\SA\\tmp\\apm>echo apm-agent-10.3.0.15-base-win-master-541edbf478cc5e960c33e90b394a9b9cd822def3 \r\napm-agent-10.3.0.15-base-win-master-541edbf478cc5e960c33e90b394a9b9cd822def3\r\n",
"stdout_lines": [
"",
"E:\\SA\\tmp\\apm>echo apm-agent-10.3.0.15-base-win-master-541edbf478cc5e960c33e90b394a9b9cd822def3 ",
"apm-agent-10.3.0.15-base-win-master-541edbf478cc5e960c33e90b394a9b9cd822def3"
],
"warnings": []
}
However the following debug command gives me the following:
TASK [../roles/apm_windows : debug] ********************************************
task path: /home/SILVER/c53259/ansible/apm_deployment/roles/apm_windows/tasks/agent.yml:95
ok: [ciwsdbxd8559.silver.com] => (item=extout.stdout) => {
"invocation": {
"module_args": {
"msg": "extout.stdout"
},
"module_name": "debug"
},
"item": "extout.stdout",
"msg": "extout.stdout"
}
Any thoughts on what is going on?
Using Ansible 2.2
Python 2.7
Are you sure this works without an error? Because mesg is not a valid option in debug. Did you mean msg?
- debug: mesg={{ item }}
Anyway, the problem is you are using a wrong parameter. Use var instead since you are printing the value of a variable.
- debug: var={{ item }}
with_items: extout.stdout_lines

Resources