Ansible Playbook : variables - ansible

I am having an issue with my playbook when I run this playbook as follows
ansible-playbook –i inventory junos_config_new.yml –check –vvv
name: Juniper SRX configuration compliance checks
hosts: juniper
gather_facts: false
tasks:
set_fact:
config_directory: '{{ "/home/myfolder/ansible_junos/files/" }}'
- name: Syslog server check
junipernetworks.junos.junos_config:
src:'{{ config_directory }}/syslog_config.txt'
src_format: set
comment: Ensure that appropriate Syslog server configured
register: junos_output
diff: true
- debug:
msg: Syslog server check - This check has failed with the following output({{ junos_output.diff.prepared }})
when: junos_output.changed
- debug:
msg: Syslog server check - This check has failed with the following output({{ junos_output.diff.prepared }})
when: junos_output.changed
- name: Admin credentials check
junipernetworks.junos.junos_config:
src: '{{ config_directory }}/admin_user.txt'
comment: Ensure that Admin user have been created
diff: true
register: junos_output1
- debug:
var: junos_output1 ***************************************failed section
- debug:
msg: Admin credentials check - This check has passed with the following output({{ junos_output1.diff.prepared }})
when: not junos_output1.changed
- debug:
msg: Admin credentials check - This check has failed with the following output({{ junos_output1.diff.prepared }})
when: junos_output1.changed
- name: NTP Server check
junipernetworks.junos.junos_config:
src: '{{ config_directory }}/NTP_server.txt'
comment: Ensure that correct NTP servers has been configured
diff: true
- debug:
var: junos_output2
- debug:
msg: NTP Server check - This check has passed with the following output({{ junos_output2.diff.prepared }})
when: not junos_output.changed
- debug:
msg: NTP Server check - This check has failed with the following output({{ junos_output2.diff.prepared }})
when: junos_output.changed
- name: Idle timeout check
junipernetworks.junos.junos_config:
src: '{{ config_directory }}/idle_timeout.txt'
comment: Ensure that idle timeout has been configured
diff: true
- debug:
var: junos_output3
- debug:
msg: Idle timeout check - This check has passed with the following output({{ junos_output3.diff.prepared }})
when: not junos_output.changed
- debug:
msg: Idle timeout check - This check has failed with the following output({{ junos_output3.diff.prepared }})
when: junos_output.changed
The error appears to be in '/home/gefelas/ansible_junos/junos_config_new.yml': line 30, column 5, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
register: junos_output1
- debug:
^ here
Please let me know what I can change ..

The main cause for the error seems to be that you are using diff for the junos_config module. According to the documentation, this module does not support diff: https://docs.ansible.com/ansible/latest/modules/junos_config_module.html
So you'll need to remove the diff: true from your junos_config tasks.
On another note, you also seem to have multiple issues with indentation, for example this is not the correct indentation:
- name: Admin credentials check
junipernetworks.junos.junos_config:
src: '{{ config_directory }}/admin_user.txt'
comment: Ensure that Admin user have been created
register: junos_output1
Make sure you properly indent the task name and additional task parameters like so for all of your tasks:
- name: Admin credentials check
junipernetworks.junos.junos_config:
src: '{{ config_directory }}/admin_user.txt'
comment: Ensure that Admin user have been created
register: junos_output1
So I would recommend going over your file and checking the indentation for all tasks (note that this might also be due to StackOverflow formatting).

Related

Error handling for updating IOS via Ansible

beginner to using Ansible. More of a network engineer, less of a scripter / programmer, but trying to learn a new skill.
Attempting to write a playbook to automate updating of our fleet of Cisco switch stacks but I think I am both lost in syntax and if this is the 'right' way to go about what I am doing.
---
- name: Update Cisco switch stack
hosts: Cisco2960
vars:
upgrade_ios_version: "15.2(7)E5"
tasks:
name: Check current IOS version / Determine if update is needed...
ios_facts:
debug:
msg:
- "Current image is {{ ansible_net_version }}"
- "Current compliant image is {{ upgrade_ios_version }}"
name: Fail if versions match.
ansible.builtin.fail: msg="IOS versions match. Stopping update."
when: "{{ ansible_net_version }} = {{ upgrade_ios_version }}"
At first I thought each variable needed its own quotation, but that appears to be incorrect syntax as well, as below.
when: "{{ ansible_net_version }}" = "{{ upgrade_ios_version }}"
Couple questions:
Is there an easier way with a plain-English way of describing the type of error handling I am looking for? Ansible documentation is great on options, but light on practical applications / examples.
Why am I receiving this specific syntax error in this case?
You can use the playbook below.
Ansible Playbook to upgrade Cisco IOS
- name: Upgrade CISCO IOS
hosts: SWITCHES
vars:
upgrade_ios_version: 15.2(7)E5
tasks:
- name: CHECK CURRENT VERSION
ios_facts:
- debug:
msg:
- "Current version is {{ ansible_net_version }}"
- "Current compliant image is {{ upgrade_ios_version }}"
- debug:
msg:
- "Image is not compliant and will be upgraded"
when: ansible_net_version != upgrade_ios_version
Create backup folder for today
- hosts: localhost
tasks:
- name: Get ansible date/time facts
setup:
filter: "ansible_date_time"
gather_subset: "!all"
- name: Store DTG as fact
set_fact:
DTG: "{{ ansible_date_time.date }}"
- name: Create Directory {{hostvars.localhost.DTG}}
file:
path: ~/network-programmability/backups/{{hostvars.localhost.DTG}}
state: directory
run_once: true
Backup Running Config
- hosts: SWITCHES
tasks:
- name: Backup Running Config
ios_command:
commands: show run
register: config
- name: Save output to ~/network-programmability/backups/
copy:
content: "{{config.stdout[0]}}"
dest: "~/network-programmability/backups/{{hostvars.localhost.DTG}}/{{ inventory_hostname }}-{{hostvars.localhost.DTG}}-config.txt"
SAVE the Running Config
- name: Save running config
ios_config:
save_when: always
Copy software to target device
- name: Copy Image // This could take up to 4 minutes
net_put:
src: "~/network-programmability/images/c2960l-universalk9-mz.152-7.E5.bin"
dest: "flash:/c2960l-universalk9-mz.152-7.E5.bin"
vars:
ansible_command_timeout: 600
Change the Boot Variable to the new image
- name: Change Boot Variable to new image
ios_config:
commands:
- "boot system flash:c2960l-universalk9-mz.152-7.E5.bin"
save_when: always
Reload the device
- name: Reload the Device
cli_command:
command: reload
prompt:
- confirm
answer:
- 'y'
Wait for Reachability to the device
- name: Wait for device to come back online
wait_for:
host: "{{ inventory_hostname }}"
port: 22
delay: 90
delegate_to: localhost
Check current image
- name: Check Image Version
ios_facts:
- debug:
msg:
- "Current version is {{ ansible_net_version }}"
- name: ASSERT THAT THE IOS VERSION IS CORRECT
vars:
upgrade_ios_version: 15.2(7)E5
assert:
that:
- upgrade_ios_version == ansible_net_version
- debug:
msg:
- "Software Upgrade has been completed"

Ansible 2.4 Skip option

I'm trying to install a website with ansible 2.4.0.0. When I do:
./architecture/scripts/provision.sh lxc
I get this result:
/usr/local/lib/python2.7/dist-packages/cryptography/__init__.py:39: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
CryptographyDeprecationWarning,
/usr/local/lib/python2.7/dist-packages/cryptography/__init__.py:39: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
CryptographyDeprecationWarning,
[WARNING]: - ansible-genericservice was NOT installed successfully: - command git clone git#git.smile.fr:ansible/ansible-genericservice.git ansible-genericservice failed in directory /tmp/tmpmZfdUa (rc=128)
ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.
/usr/local/lib/python2.7/dist-packages/cryptography/__init__.py:39: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
CryptographyDeprecationWarning,
[DEPRECATION WARNING]: The use of 'include' for tasks has been deprecated. Use 'import_tasks' for static inclusions or 'include_tasks' for dynamic inclusions. This feature will be removed in a future release.
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: include is kept for backwards compatibility but usage is discouraged. The module documentation details page may explain more about this rationale.. This feature will be removed in a
future release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
PLAY [dbservers,cacheservers,searchservers,webservers] ************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
Warning: the ECDSA host key for 'webstore.lxc' differs from the key for the IP address '10.124.193.20'
Offending key for IP in /home/jredor/.ssh/known_hosts:19
Matching host key in /home/jredor/.ssh/known_hosts:21
Are you sure you want to continue connecting (yes/no)? yes
ok: [lxc-server]
TASK [include_vars] ***********************************************************************************************************************************************************************************************
fatal: [lxc-server]: FAILED! => {"failed": true, "msg": "No file was found when using with_first_found. Use the 'skip: true' option to allow this task to be skipped if no files are found"}
to retry, use: --limit #/home/jredor/projets/webstore/architecture/provisioning/provision.retry
PLAY RECAP ********************************************************************************************************************************************************************************************************
lxc-server : ok=1 changed=0 unreachable=0 failed=1
I can't find how to pass the skip option to true. My ansible file look like that:
cd "$( dirname "${BASH_SOURCE[0]}" )"
cd ..
source scripts/_environment-with-lxc.sh
source scripts/_ansible.sh
ansible-galaxy install -r provisioning/requirements.yml -p provisioning/roles -n -f
ansible-playbook --ssh-extra-args="${ANSIBLE_SSH_ARGS}" provisioning/provision.yml -i provisioning/inventory/$inventory
exit $?
It's the first time that I use ansible so I'm lost.
Thanks
Edit:
So here is the code in provision.yml
---
# load variables for each servers
- hosts:
- dbservers
- cacheservers
- searchservers
- webservers
vars:
ansible_user: "root"
tasks:
- include: includes/include-vars.yml
# Prepare the delivery authorized keys
- hosts:
- dbservers
- cacheservers
- searchservers
- webservers
connection: local
vars:
ansible_user: "root"
tmp_delivery_users:
- name: "{{ magento_project_user }}"
group: "{{ magento_webserver_group }}"
authorized_keys: "{{ delivery_authorized_keys }}"
tasks:
- name: "Prepare the list of the authorized keys for delivery - Extra Keys"
set_fact: delivery_authorized_keys="{{ delivery_authorized_extra_keys }}"
- name: "Prepare the delivery_users object"
set_fact: delivery_users="{{ tmp_delivery_users }}"
# add hosts alias on Servers
- hosts:
- dbservers
- cacheservers
- searchservers
- webservers
vars:
ansible_user: "root"
tasks:
- include: includes/init-hosts.yml
with_items: "{{ specific_hosts|default([]) }}"
# add magento hosts alias on WebServers
- hosts:
- webservers
vars:
ansible_user: "root"
tasks:
- include: includes/init-hosts.yml
with_items: "{{ magento_server_alias|default([]) }}"
# Generic behaviors on all servers
- hosts:
- dbservers
- cacheservers
- searchservers
- webservers
vars:
ansible_user: "root"
roles:
- role: ansible-basicserver
# Generic usage of the ansible roles - DB Server
- hosts: dbservers
vars:
ansible_user: "root"
roles:
- role: ansible-mysql-server
# Generic usage of the ansible roles - Cache Server
- hosts: cacheservers
vars:
ansible_user: "root"
roles:
- {
role: ansible-redis,
redis_instance_name: "magento_cache",
redis_setting_port: "{{ magento_cache_port }}",
redis_setting_save: "{{ redis_setting_save_cache }}"
}
- {
role: ansible-redis,
redis_instance_name: "magento_session",
redis_setting_port: "{{ magento_cache_session_port }}",
redis_setting_save: "{{ redis_setting_save_session }}"
}
# Generic usage of the ansible roles - Search Server
- hosts: searchservers
vars:
ansible_user: "root"
roles:
- role: ansible-elasticsearch
# Prepare php parameters
- hosts: webservers
vars:
ansible_user: "root"
tasks:
- include: includes/prepare-php-parameters.yml
# Generic usage of the ansible roles - Webserver Server
- hosts: webservers
vars:
ansible_user: "root"
roles:
- role: ansible-php
- role: ansible-apache
- role: ansible-varnish
- role: ansible-nginx
# Specific usage of the ansible roles - Webserver Server - Dev Tools
- hosts: webservers
vars:
ansible_user: "root"
roles:
- { role: ansible-npm, when: magento_install_maildev or magento_install_grunt }
- { role: ansible-maildev, when: magento_install_maildev }
tasks:
- name: "Install NPM package: grunt-cli"
npm: name="grunt-cli" global=yes
when: magento_install_grunt
- name: "Add delivery user in groups"
user:
name: "{{ magento_project_user }}"
groups: "{{ magento_delivery_groups }}"
- name: "Create {{ magento_source_path }} folder"
file:
path: "{{ magento_source_path }}"
state: directory
owner: "{{ magento_project_user }}"
group: "{{ magento_project_group }}"
mode: "u=rwX,g=rX,o=rX"
# Specific task for Magento 2
- name: "Check if Magento app/etc/env.php exists"
stat:
path: "{{ magento_source_path }}/app/etc/env.php"
register: magento_app_etc_env
- name: "Update app/etc/env.php configuration file"
template:
src: "templates/magento/env.php.j2"
dest: "{{ magento_source_path }}/app/etc/env.php"
owner: "{{ magento_project_user }}"
group: "{{ magento_webserver_group }}"
mode: "u=rw,g=rw,o=r"
vars:
magento_cache_database: "{{ magento_cache_database_for_run }}"
when: magento_app_etc_env.stat.exists
# Update permissions
- include: includes/permissions-tasks-full.yml
It was coded by a fellow coworker and I'm just trying to use it to deplay the website on my computer. So I guess I have to put here the "skip:true" but I really don't know where, sorry. Thanks for your help!
You can specify the skip option as the argument in the failing lookup, https://docs.ansible.com/ansible/latest/plugins/lookup/first_found.html#parameter-skip

Ansible playbook “path specified in src not found”

I am runnning into this message when I do this :
ansible-playbook -i inventory junos_config_new.yml --check -vvv
ansible-playbook 2.9.9 config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules',
'/usr/share/ansible/plugins/modules'] ansible python module location =
/root/.local/lib/python3.6/site-packages/ansible executable location =
/usr/bin/ansible-playbook python version = 3.6.8 (default, Nov 21
2019, 19:31:34) [GCC 8.3.1 20190507 (Red Hat 8.3.1-4)] Using
/etc/ansible/ansible.cfg as config file host_list declined parsing
/home/gefela/ansible_junos/inventory as it did not pass its
verify_file() method script declined parsing
/home/gefela/ansible_junos/inventory as it did not pass its
verify_file() method auto declined parsing
/home/gefela/ansible_junos/inventory as it did not pass its
verify_file() method Parsed /home/gefela/ansible_junos/inventory
inventory source with ini plugin
PLAYBOOK: junos_config_new.yml ***************************************************************************************************************************** 1 plays in junos_config_new.yml
This is the playbook that I have ...
name: Juniper SRX configuration compliance checks
hosts: juniper
gather_facts: false
connection: local
tasks:
- name: Syslog server checks
junos_config:
src: ~/ansible_junos/files/syslog_config.txt
comment: Ensure that appropriate Syslog server configured
register: junos_output
- debug:
var: junos_output
- name: success
debug:
msg: Syslog server check - This check has passed with the following output({{ junos_output }})
when: not junos_output.changed
- name: failed
debug:
msg: Syslog server check - This check has failed with the following output({{ junos_output }})
when: junos_output.changed
- name: Admin credentials check
junos_config:
src: ~/ansible_junos/files/admin_user.txt
comment: Ensure that Admin user havee been created
register: junos_output
- debug:
var: junos_output
- name: success
debug:
msg: Admin credentials check - This check has passed with the following output({{ junos_output }})
when: not junos_output.changed
- name: failed
debug:
msg: Admin credentials check - This check has failed with the following output({{ junos_output }})
when: junos_output.changed
The directory ~/ansible_junos/files/syslog_config.txt is in the right place
Should ~/ansible_junos/files/ be the right place to place all the configuration to be compared against the firewall ?
Please let me know ..
It's because ~ is a bash feature, and not an actual path component; your shell expands ~ to mean the home directory for the current user (or for the user named directly after the ~), however, ansible modules would have to go out of their way to use expanduser to behave like that.
You can try sending the filename through the | expanduser filter, or you may have to use gather_facts: true in order to have access to ansible_env.HOME
- set_fact:
config_directory: '{{ "~/ansible_junos/files" | expanduser }}'
- name: Syslog server checks
junos_config:
src: '{{ config_directory }}/syslog_config.txt'
comment: Ensure that appropriate Syslog server configured
register: junos_output
src jues need "admin_user.txt"
- name: Admin credentials check
junos_config:
src: "admin_user.txt"
comment: Ensure that Admin user havee been created
register: junos_output
add you can add admin_user.txt in files/admin_user.txt
I had to change the inventory file ( ansible_user and ansible_password ) and change this
set_fact:
config_directory: '{{ "~/ansible_junos/files" | expanduser }}'
name: Syslog server checks
junos_config:
src: '{{ config_directory }}/syslog_config.txt'
comment: Ensure that appropriate Syslog server configured
register: junos_output
to
set_fact:
config_directory: '{{ "/home/myfolder/ansible_junos/files" }}'
name: Syslog server checks
junos_config:
src: '{{ config_directory }}/syslog_config.txt'
comment: Ensure that appropriate Syslog server configured
register: junos_output

Read a file locally and use the vars remote in Ansible

I read a YAML file locally with the following playbook:
- name: Ensure the deploy_manifest var is defined and read deploy manifest
hosts: localhost
connection: local
gather_facts: False
tasks:
- assert:
that: deploy_manifest is defined
msg: |
Error: Must provide providers config path. Fix: Add '-e deploy_manifest=/path/to/manifest' to the ansible-playbook command
- name: Read deploy manifest
include_vars:
file: "{{ deploy_manifest }}"
name: manifest
register: manifest
- debug:
msg: "[{{ manifest.key }}]: {{ manifest.value }}"
with_dict: "{{ manifest.ansible_facts }}"
and then in the same playbook YAML file I run:
- name: Deploy Backend services
hosts: backend
remote_user: ubuntu
gather_facts: False
vars:
env: "{{ env }}"
services: "{{ manifest.ansible_facts }}"
tasks:
- include_role:
name: services_backend
when: backend | default(true) | bool
However it doesn't work because debug fails. It says that manifest is empty.
Which is the best way to read a YAML file or generally a configuration in a playbook and then have the variables passed in another playbook?
Your debug module doesn't say "that manifest is empty", it says the key manifest.key does not exist because it does not.
You registered a fact named manifest with:
register: manifest
You try to refer to a key of the above manifest named key and another key (!) named value:
msg: "[{{ manifest.key }}]: {{ manifest.value }}"
Please read Looping over Hashes chapter and acknowledge that (without using loop control) you refer to the iterated variable using item.
Please note that with name: manifest and register: manifest you read your vars file into manifest.ansible_facts.manifest.

Trying to include a list of tasks from an playbook in Ansible

My folder structure:
First I'll give you this so you can see how this is laid out and reference it when reading below:
/environments
/development
hosts // Inventory file
/group_vars
proxies.yml
/custom_tasks
firewall_rules.yml // File I'm trying to bring in
playbook.yml // Root playbook, just brings in the plays
rev-proxy.yml // Reverse-proxy playbook, included by playbook.yml
playbook.yml:
---
- include: webserver.yml
- include: rev-proxy.yml
proxies.yml just contains firewall_custom_include_file: custom_tasks/firewall_rules.yml
firewall_rules.yml:
tasks:
- name: "Allowing traffic from webservers on 80"
ufw: src=10.10.10.3, port=80, direction=in, rule=allow
- name: "Allowing traffic all on 443"
ufw: port=443, rule=allow
and finally rev-proxy.yml play:
---
- hosts: proxies
become: yes
roles:
- { role: firewall }
- { role: geerlingguy.nginx }
pre_tasks:
# jessie-backports for nginx-extras 1.10
- name: "Adding jessie-backports repo"
copy: content="deb http://ftp.debian.org/debian jessie-backports main" dest="/etc/apt/sources.list.d/jessie-backports.list"
- name: Updating apt-cache.
apt: update_cache="yes"
- name: "Installing htop"
apt:
name: htop
state: present
- name: "Coopying SSL certificates"
copy: src=/vagrant/ansible/files/ssl/ dest=/etc/ssl/certs force=no
tasks:
- name: "Including custom firewall rules."
include: "{{ inventory_dir }}/{{ firewall_custom_include_file }}.yml"
when: firewall_custom_include_file is defined
vars_files:
- ./vars/nginx/common.yml
- ./vars/nginx/proxy.yml
What I'm trying to do:
Using Ansible 2.2.1.0
I'm trying to include a list of tasks that will be run if a variable firewall_custom_include_file is set. The list is included relative to the inventory directory by doing "{{ inventory_dir }}/{{ firewall_custom_include_file }}.yml" - in this case that works out to /vagrant/ansible/environments/development/custom_tasks/firewall_rules.yml
Essentially the idea here is that I need to have different firewall rules be executed based on what environment I'm in, and what hosts are being provisioned.
To give a simple example: I might want to whitelist a database server IP on the production webserver, but not on the reverse proxy, and also not on my development box.
The problem:
Whenever I include firewall_rules.yml like above, it tells me:
TASK [Including custom firewall rules.] ****************************************
fatal: [proxy-1]: FAILED! => {"failed": true, "reason": "included task files must contain a list of tasks"}
I'm not sure what it's expecting, I tried taking out the tasks: at the beginning of the file, making it:
- name: "Allowing traffic from webservers on 80"
ufw: src=10.10.10.3, port=80, direction=in, rule=allow
- name: "Allowing traffic all on 443"
ufw: port=443, rule=allow
But then it gives me the error:
root#ansible-control:/vagrant/ansible# ansible-playbook -i environments/development playbook.yml
ERROR! Attempted to execute "/vagrant/ansible/environments/development/custom_tasks/firewall_rules.yml" as inventory script: problem running /vagrant/ansible/environments/development/custom_tasks/firewall_rules.yml --list ([Errno 8] Exec format error)
Attempted to read "/vagrant/ansible/environments/development/custom_tasks/firewall_rules.yml" as YAML: 'AnsibleSequence' object has no attribute 'keys'
Attempted to read "/vagrant/ansible/environments/development/custom_tasks/firewall_rules.yml" as ini file: /vagrant/ansible/environments/development/custom_tasks/firewall_rules.yml:2: Expected key=value host variable assignment, got: name:
At this point I'm not really sure what it's looking for in the included file, and I can't seem to really find clear documentation on this, or other people having this issue.
Try to execute with -i environments/development/hosts instead of directory.
But I bet that storing tasks file inside inventory is far from best practices.
You may want to define list of custom rules as inventory variable, e.g.:
custom_rules:
- src: 10.10.10.3
port: 80
direction: in
rule: allow
- port: 443
rule: allow
And instead of include task, make something like this:
- ufw:
port: "{{ item.port | default(omit) }}"
rule: "{{ item.rule | default(omit) }}"
direction: "{{ item.direction | default(omit) }}"
src: "{{ item.src | default(omit) }}"
with_items: "{{ custom_rules }}"

Resources