Ansible pre-check before run playbook - ansible

Is it possible to add a condition before to run a playbook which check if there is a title, a description, the environment and the versions on the playbook ?
For example my test.yml playbook:
---
#Apache servers
#Linux
#Ubuntu
#version 2.1.1
#Testing for secure the webserver
task:
xxxxxx
xxxxxx
And I would like to check if all the comment before are present before to run this task !
I tried to test this solution :
name: run Apachetest playbook
include: test.yml
when: "{{ lookup('file', 'test.yml').split('\n')[1] == '#Apache servers' }}"
But still not working...
BS

Comments are, well, comments. They do not impact the execution and are just ignored. So there is no way, and actually no real reason, to check if comments are present or not. You would need to implement that yourself.
To check playbooks, roles, etc. there is ansible-lint which will verify the syntax and some best practices (e.g. if you use a command or shell for something there is a module for) but this does not verify comments (again, checking for comments does not make sense from a execution perspective, as they are ignored).
You want some information to be present in your playbook, that is what I understand. If I was you, I would either create a git hook, that verifies if the information is present before letting you push that code to your repository or establish a proper review-process, where the reviewer only accepts a merge/pull request, if the information is present.
Otherwise, here is the code, that will do what you are trying to do:
---
#Apache server
- hosts: all
tasks:
- name: set fact
set_fact:
pb: "{{ lookup('file', 'test.yml').split('\n')[1] }}"
- name: check if we found it
debug:
msg: 'found'
when: "'#Apache server' in pb"

You could use the apache role for apache installed like that
---
- hosts: apache
sudo: yes
tasks:
- name: install apache2
apt: name=apache2 update_cache=yes state=latest
have a look here how-to-install-apache-on-ansible

Related

ansible: customize which password manager to use

New to Ansible here. I've been adapting an Ansible playbook to automate the setup of a Raspberry Pi to use Pi-hole as described on this blog and as per this repo.
One change I've made is to use Bitwarden instead of 1Password as the secrets manager (see details below).
But after having done it, and thinking of offering a PR to the repo in question, I realized that my use of Bitwarden is just as hard-coded as the use of 1Password in the original (hardly an improvement).
Is there a way to make the choice of secret manager configurable in an Ansible playbook or setup? Or "call a different function" based on the value of a variable?
A desirable setup would be something along the lines of:
vars:
secret_manager: bitwarden
# one of {'1password', 'bitwarden', 'lastpass', 'ansible-vault',
# 'aws-secrets', 'azure-key-vault', ...}
tasks:
- name: ...
...
value: "{{ lookup(secret_manager, item_name, field=field_name) }}"
Details
Here is an example of using bitwarden instead of 1password in a playbook.yml:
New:
roles:
- role: ansible-modules-bitwarden
tasks:
- name: "test: get 'username' from the secrets manager"
debug:
- msg: "{{ lookup('bitwarden', 'pi-hole', field='username') }}"
(and note: if the field is a custom one, one must add custom_field=true whereas with
community.general.onepassword this is not needed).
Instead of:
tasks:
- name: "test: get 'username' from the secrets manager"
debug:
- msg: "{{ lookup('community.general.onepassword', 'pi-hole', field='username') }}"
Side note and for sake of completeness, in order to make this work I needed to install Bitwarden CLI as well as (one of) the ansible-modules-bitwarden, and then of course log in and get a session token:
export BW_SESSION="$(bw unlock --raw)"
This all works fine, but I am not quite happy: now the use of Bitwarden is hard-coded instead of "1Password". I would like to make this more generic and customizable. What if someone would like to use LastPass or AWS Secrets Manager instead?
Things I've tried
using if-else:
- hosts: all
vars:
use_bitwarden: true
secret_item: pi-hole
roles:
- role: ansible-modules-bitwarden
when: use_bitwarden
tasks:
- name: get username from the secrets manager
debug:
msg: "{{ lookup('bitwarden', secret_item, field='username') if use_bitwarden \
else lookup('community.general.onepassword', secret_item, field='username') }}"
but this bloats the playbook, makes it less readable and less DRY. Also, it isn't very extensible to the many other secrets managers out there.
define which manager to use in a variable:
- hosts: all
vars:
secret_manager: bitwarden
# secret_manager: community.general.onepassword
secret_item: pi-hole
roles:
- role: ansible-modules-bitwarden
when: secret_manager == 'bitwarden'
tasks:
- name: get username from the secrets manager
debug:
msg: "{{ lookup(secret_manager, secret_item, field='username') }}"
but this doesn't work as custom fields are to be queried with custom_field=true with the Bitwarden plugin, but not with 1Password.
Other ideas (not tried)
define a new generic plugin that uses other existing ones, based on a config variable.
use a task to get all the needed variables from whatever password manager at once and insert them, encrypted, into Ansible's vault. That way the task that does that can be isolated and have conditional execution with when: secret_manager == 'that'. But it makes maintenance of the playbook more difficult.
Maybe there is a much simpler and concise way of accomplishing this?

How to make Ansible display the host name before asking for the sudo password?

I have an Ansible playbook to update my Debian based servers. For simplicity and security reasons, I don't want to use a vault for the passwords and I also don't want to store them in a publically accessible config file. So I ask for the password for every client with
become: yes
become_method: sudo
Now, when the playbook runs, it seems the first thing Ansible does is ask for the sudo password, but I don't know for which server (the passwords are different). Is there a way to get Ansible to print the current host name before it asks for the password?
The update playbook is similar to this:
---
- hosts:
all
gather_facts: no
vars:
verbose: false
log_dir: "log/dist-upgrade/{{ inventory_hostname }}"
pre_tasks:
- block:
- setup:
rescue:
- name: "Install required python-minimal package"
raw: "apt-get update && apt-get install -y --force-yes python-apt python-minimal"
- setup:
tasks:
- name: Update packages
apt:
update_cache: yes
upgrade: dist
autoremove: yes
register: output
- name: Check changes
set_fact:
updated: true
when: not output.stdout | search("0 upgraded, 0 newly installed")
- name: Display changes
debug:
msg: "{{ output.stdout_lines }}"
when: verbose or updated is defined
- block:
- name: "Create log directory"
file:
path: "{{ log_dir }}"
state: directory
changed_when: false
- name: "Write changes to logfile"
copy:
content: "{{ output.stdout }}"
dest: "{{ log_dir }}/dist-upgrade_{{ ansible_date_time.iso8601 }}.log"
changed_when: false
when: updated is defined
connection: local
(source: http://www.panticz.de/Debian-Ubuntu-mass-dist-upgrade-with-Ansible)
Your above become configuration does not make ansible ask you for a become password: it just advises it to use become with the sudo method (which will work without any password if your have the correct keys configured for example).
If you are asked for a become password, it's because (it's a guess but I'm rather confident...) you used the --ask-become-pass option when running ansible-playbook.
In this case, you are prompted only once at the beginning of the playbook operations and this default become password will be used on all servers you connect to except if you defined an other one in your inventory for a specific host/group.
If you have different become passwords depending on your machines, you don't really have an other option: you need to declare those passwords in your inventory (and it is strongly advised to use ansible-vault encryption) or use some other mechanisms to get them out of an external application (hashicorp vault, dynamic inventory, cyberark...)

Is there a better way to conditionally add a user to a group with Ansible?

I have a playbook that provisions a host for use with Rails/rvm/passenger. I'd like to add use the same playbook to setup both test and production.
In testing, the user to add to the rvm group is jenkins. The one in production is passenger. My playbook excerpt below does this based on the inventory_hostname parameter.
It seems like adding a new user:/when: block in the playbook for every testing or production host is the wrong way to go here. Should I be using an Ansible role for this?
Thanks
---
- hosts: all
become: true
...
tasks:
- name: add jenkins user to rvm group when on testing
user: name={{ item }}
shell=/bin/bash
groups=rvm
append=yes
with_items:
- jenkins
when: "'bob.mydomain' in inventory_hostname"
- name: add passenger user to rvm group when on rails production
user: name={{ item }}
shell=/bin/bash
groups=rvm
append=yes
with_items:
- passenger
when: "'alice.mydomain' in inventory_hostname"
Create an inventory file called inventories/testing
[web]
alice.mydomain
[testing:children]
web
This will control what hosts are targeted when you run your playbook against your testing environment.
Create another file called group_vars/testing
rvm_user: jenkins
This file will keep all variables required for running a playbook against the testing environment. Your production file should have the same variables, but with different values.
Finally in your playbook:
---
- hosts: all
become: true
...
tasks:
- name: add user to rvm group
user:
name: "{{ rvm_user }}"
shell: "/bin/bash"
groups: rvm
append: yes
Now, when you want to run your playbook, you execute it like so:
ansible-playbook -i inventories/testing site.yml
Ansible will do the right thing, and look for a testing file in group_vars and read variables from there. It will ignore variables in a file or folder not named after your environment with the exception of a file called all which is intended to be for common variables across playbooks.
Good luck - Ansible is an amazing tool :)

Ansible - Unable to run certain JUNOS modules

I'm trying to run the Ansible modules junos_cli and junos_rollback and I get the following error:
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
The error appears to have been in '/home/quake/network-ansible/roles/junos-rollback/tasks/main.yml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
---
- name: I've made a huge mistake
^ here
This is the role in question:
---
- name: I've made a huge mistake
junos_rollback:
host={{ inventory_hostname }}
user=ansible
comment={{ comment }}
confirm={{ confirm }}
rollback={{ rollback }}
logfile={{ playbook_dir }}/library/logs/rollback.log
diffs_file={{ playbook_dir }}/configs/{{ inventory_hostname }}
Here is the Juniper page:
http://junos-ansible-modules.readthedocs.io/en/1.3.1/junos_rollback.html
Their example's syntax is a little odd. host uses a colon while the rest uses = signs. I've tried mixing both and only using one or the other. I keep getting errors.
I also confirmed that my junos-eznc version is higher than 1.2.2 (I have 2.0.1)
I've been able to use junos_cli before, I don't know if a version mismatch happened. On the official Ansible documentation, there is no mention of junos_cli or junos_rollback. Perhaps they're not supported anymore?
http://docs.ansible.com/ansible/list_of_network_modules.html#junos
Thanks,
junos_cli & junos_rollback are part of Galaxy and not core modules. You can find them at
https://galaxy.ansible.com/Juniper/junos/
Is the content posted here has whole content of your playbook? if yes, You need to define other items too in your playbook such as roles, connection, local. For example
refer https://github.com/Juniper/ansible-junos-stdlib#example-playbook
```
---
- name: rollback example
hosts: all
roles:
- Juniper.junos
connection: local
gather_facts: no
tasks:
- name: I've made a huge mistake
junos_rollback:
host = {{inventory_hostname}}
----
----
```
Where have you saved the content of juniper.junos modules?. Can you post the content of your playbook and the output of the tree command to see your file structure? That could help.
I had a similar problem where Ansible was not finding my modules and what I did was to copy the juniper.junos folder to my roles folder and then added a tasks folder within it to execute the main.yaml from there.
Something like this:
/Users/macuared/Ansible_projects/roles/Juniper.junos/tasks
---
- name: "TEST 1 - Gather Facts"
junos_get_facts:
host: "{{ inventory_hostname}}"
user: "uuuuu"
passwd: "yyyyyy"
savedir: "/Users/macuared/Ansible_projects/Ouput/Facts"
ignore_errors: True
register: junos
- name: Checking Device Version
debug: msg="{{ junos.facts.serialnumber }}"
Additionally, I would add "" to the string values in your YAML. Something like this:
---
- name: I've made a huge mistake
junos_rollback:
host="{{ inventory_hostname }}"
user=ansible
comment="{{ comment }}"
confirm={{ confirm }}
rollback={{ rollback }}
logfile="{{ playbook_dir }}/library/logs/rollback.log"
diffs_file="{{ playbook_dir }}/configs/{{ inventory_hostname }}"
Regarding this "I've tried mixing both and only using one or the other. I keep getting errors."
I've used just colon and mine works fine even when in the documentation suggests = signs. See junos_get_facts

Usage of variable and role in openstack-ansible

I am a newbie to Ansible and I started to study deploying Openstack with Ansible recently.
Here is the git of openstack-ansible:
https://github.com/openstack/openstack-ansible
From the tutorial:
https://docs.openstack.org/project-deploy-guide/openstack-ansible/newton/run-playbooks.html
there is one command running playbook:
openstack-ansible setup-hosts.yml
I read this playbook, it includes another playbook at line 16:
include: openstack-hosts-setup.yml
Then I read the included openstack-hosts-setup.yml and following is the snippet from it:
- name: Basic host setup
hosts: "{{ openstack_host_group|default('hosts') }}"
gather_facts: "{{ gather_facts | default(True) }}"
max_fail_percentage: 20
user: root
pre_tasks:
- name: Check for a supported Operating System
assert:
that:
- (ansible_distribution == 'Ubuntu' and ansible_distribution_release == 'xenial') or
(ansible_os_family == 'RedHat' and ansible_distribution_major_version == '7')
msg: "The only supported platforms for this release are Ubuntu 16.04 LTS (Xenial) and CentOS 7 (WIP)"
roles:
- role: "openstack_hosts"
tags:
- openstack-hosts
I was confused about roles here
roles:
- role: "openstack_hosts"
As far as I know, there should be directory structure when using roles like:
roles/
openstack_hosts/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
However, I can't find this structure in this openstack-ansible project.
So I have no idea where is the role(openstack_hosts) in this playbook.
When running this playbook , an error occurred just expected:
ERROR! the role 'openstack_hosts' was not found in /opt/openstack-ansible/playbooks/roles:/root/ansible/roles:/opt/openstack-ansible/playbooks
Also, I was wondering where the variablescome from:
hosts: "{{ openstack_host_group|default('hosts') }}"
I thought the variable will be found from the directory vars or defaults
under roles directory.
Since there is no such directory, I have no idea where this variable comes from.
Could any tell me where should I find the variable openstack_host_group
and explain how the role is used here?
Or did I miss something or I was wrong with some concepts about Ansible?
Thanks!!
By the way, this is the first time I ask question.
If the question is not clear enough or something not proper, please let me know :). Thanks again.
I guess you didn't complete bootstrap-ansible.sh from this guide. So you don't have required roles installed.
As for openstack_host_group, it seems that it is optional variable, so you can override default host pattern (which is hosts) if you want with extra variable (like -e openstack_host_group=my_other_group).

Resources