Why is conditional not working? - ansible

I am trying to write a simple conditional in Ansible and I am getting an error
- name: Add user key to AWS
ec2_key:
name: "{{ ansible_user_id }}_key"
key_material: "{{ item }}"
region: "{{ region }}"
with_file: ~/.ssh/id_rsa.pub
when: "development" == prefix
Error
ERROR! Syntax Error while loading YAML.
The error appears to have been in '/Users/ryanme/sites/devops/aws-infrastructure/roles/ec2/tasks/main.yml': line 7, column 23, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
with_file: ~/.ssh/id_rsa.pub
when: "development" == prefix
^ here
This one looks easy to fix. It seems that there is a value started
with a quote, and the YAML parser is expecting to see the line ended
with the same kind of quote. For instance:
when: "ok" in result.stdout
Could be written as:
when: '"ok" in result.stdout'
Or equivalently:
when: "'ok' in result.stdout"
I have tried a couple of variations. This should be pretty straight forward, but I am obviously missing something. Any pointers would be appreciated.

To resolve the problem I updated the script to
- name: Add user key to AWS
ec2_key:
name: "{{ ansible_user_id }}_key"
key_material: "{{ item }}"
region: "{{ region }}"
with_file: "~/.ssh/id_rsa.pub"
when: prefix == "development"
I needed to put with_file in double quotes as well since it starts with a special character.

Related

Ansible - Problem with using Hostvars to use variables across different hosts. Error: Undefined Variable

The problem I'm having is fairly simple. I have a Windows Server host I'm connecting to, to make a new AD User based off some data. It's static for now, but will be dynamic in the future. It takes some variables plus randomization for uniqueness and puts them in some variables.
The next play needs to use those same variables for deploying a Windows 10 virtual machine. I used the "{{ hostvars['host']['variablename'] }}" to take them over to the next play. But no matter what I try, I always get the Undefined Variable error.
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: \"hostvars['windowsDA']\" is undefined\n\nThe error appears to be in '/etc/ansibleplaybooks/Orchestration/onboarduser': line 67, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: giveinfo\n ^ here\n"}
I've tried gather_facts. I've tried putting the original vars in vars: ... than putting them under set_fact, I've tried multiple types of syntax. Yet it doesn't want to work. Here is a shortened version of my playbook. The rest Isn't needed to know. If the debug msg works, then it should work everywhere.
- name: Make AD User
hosts: windowsDA
tasks:
- name: Set variables as fact
set_fact:
var_random_string: "{{ lookup('community.general.random_string', length=3, special=false, base64=false) }}"
var_name: Pieter
var_lastname: Post
var_department: IT
var_underscore: _
- name: Create User
community.windows.win_domain_user:
enabled: yes
name: "{{var_name+var_lastname+var_underscore+var_random_string}}"
firstname: "{{ var_name }}"
surname: "{{ var_lastname }}"
company: Poliforma
password: P#ssw0rd
password_expired: yes
path: OU={{var_department}},DC=poliforma,DC=com
state: present
description: Werknemer van {{var_department}}Afdeling
upn: "{{var_name+var_lastname+var_underscore+var_random_string}}#poliforma.com"
user_cannot_change_password: no
attributes:
department: "{{var_department}}Afdeling"
- name: Clone the template and customize
hosts: localhost
vars:
test: "{{ hostvars['windowsDA']['var_name'] }}"
#hostvar_fact_var_name: #"{{hostvars['localhost']['fact_var_name']}}"
#hostvar_fact_var_lastname: #"{{hostvars['localhost']['fact_var_lastname']}}"
#hostvar_fact_var_underscore: #"{{hostvars['localhost']['fact_var_underscore']}}"
#hostvar_fact_var_random_string: #"{{hostvars['localhost']['fact_var_random_string']}}"
tasks:
- name: giveinfo
debug: msg="{{test}}"
Can someone help me?
I believe it would work if you set your inventory as the following.
[your_group_name]
windowsDA ansible_host=188.88.88.88 etc.

Ansible known_hosts module with a loop

I am trying to run a task executing the known_hosts module with a list of key entries. The problem is that I keep getting the following error, even though the variable has data when using debug.
The task includes an option with an undefined variable. The error was: 'item' is undefined
I have the following task which registers a variable of the ssh-keyscan output
- name: keyscan platform hosts
shell: "ssh-keyscan ssh.{{ item }}"
register: "platform_ssh_host_keys"
loop:
- "one.example.com"
- "two.example.com"
When I run the following debug, I get the stdout which contains the key
- name: debug
debug:
var: item.stdout
with_items: "{{platform_ssh_host_keys.results}}"
But as soon as I run it with known_hosts it says item is undefined.
- name: configure known_hosts
known_hosts:
path: "~/.ssh/known_hosts"
name: "ssh.{{ item.item }}"
key: "{{ item.stdout }}"
state: present
loop: "{{ platform_ssh_host_keys.results }}"
I don't get how item can be defined in debug but not known_hosts task.
🤦‍♂️ Well, after I posted this I immediately realized the problem was due to the fact I had loop as a property for known_hosts and not the tasks. So the problem was indentation.
This fixed it all.
- name: configure known_hosts
known_hosts:
path: "~/.ssh/known_hosts"
name: "ssh.{{ item.item }}"
key: "{{ item.stdout }}"
state: present
loop: "{{platform_ssh_host_keys.results}}"

Error in launching ansible playbook with roles

trying to do playbook:
- hosts: win
gather_facts: no
roles:
- update_win
update_win mail.yml:
- name: Create Auto_deploy_temp folder on remoter host
win_file:
path: {{ disk }}\Auto_deploy_temp
state: directory
and vars in group vars file win.yml:
disk: 'c:'
but getting out:
ERROR! Syntax Error while loading YAML.
did not find expected key
The error appears to be in '/etc/ansible/roles/update_win/tasks/main.yml': line 3, column 19, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
win_file:
path: {{ disk }}\Auto_deploy_temp
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
can u help me with this issue?
P.S.: earlier i've launched some similar code, but there were no vars in the start of path expression, only in the end
Please provide path: "{{ disk }}\Auto_deploy_temp"
Update
Create a new var as path_dir: \Auto_deploy_temp, and use
path: "{{disk}}{{path_dir}}"
or
path: "{{ disk }}\\Auto_deploy_temp"
Escape '\'
win_file:
path: {{ disk }}\\Auto_deploy_temp

Ansible escaping a string issue on mac vs ubuntu?

With the following code:
- name: Add the gii config for main.php on staging
blockinfile:
dest: "{{ www_path }}/protected/config/main.php"
marker: "//Gii"
insertafter: "\'modules\'=>array\\("
block: "{{ gii_content }}"
I'm getting a syntax error on OSX:
ERROR! Syntax Error while loading YAML.
The offending line appears to be:
marker: "//Gii"
insertafter: "\'modules\'=>array\\("
^ here
Yet on ubuntu, no such issue and the playbook runs seamlessly. Any ideas?
If you run this through a YAML parser it will tell you it discovered an unknown escape character, so OS X is right there. What is the purpose of \'? If the idea was to match that string and the backslash appears in the file like this, you should put two backslashes there:
- name: Add the gii config for main.php on staging
blockinfile:
dest: "{{ www_path }}/protected/config/main.php"
marker: "//Gii"
insertafter: "\\'modules\\'=>array\\("
block: "{{ gii_content }}"
If there are two backslashes right after array you would need to have 4 of them there, just for escaping. Though since insertafter takes a regular expression and ( has a special meaning in regular expressions, it might be necessary to actually put 6 of them there.
- name: Add the gii config for main.php on staging
blockinfile:
dest: "{{ www_path }}/protected/config/main.php"
marker: "//Gii"
insertafter: "\\'modules\\'=>array\\\\\\("
block: "{{ gii_content }}"

ansible: using with_items with notify handler

I want to pass a variable to a notification handler, but can't find anywhere be it here on SO, the docs or the issues in the github repo, how to do it. What I'm doing is deploying multiple webapps, and when the code for one of those webapps is changed, it should restart the service for that webapp.
From this SO question, I got this to work, somewhat:
- hosts: localhost
tasks:
- name: "task 1"
shell: "echo {{ item }}"
register: "task_1_output"
with_items: [a,b]
- name: "task 2"
debug:
msg: "{{ item.item }}"
when: item.changed
with_items: task_1_output.results
(Put it in test.yml and run it with ansible-playbook test.yml -c local.)
But this registers the result of the first task and conditionally loops over that in the second task. My problem is that it gets messy when you have two or more tasks that need to notify the second task! For example, restart the web service if either the code was updated or the configuration was changed.
AFAICT, there's no way to pass a variable to a handler. That would cleanly fix it for me. I found some issues on github where other people run into the same problem, and some syntaxes are proposed, but none of them actually work.
Including a sub-playbook won't work either, because using with_items together with include was deprecated.
In my playbooks, I have a site.yml that lists the roles of a group, then in the group_vars for that group I define the list of webapps (including the versions) that should be installed. This seems correct to me, because this way I can use the same playbook for staging and production. But maybe the only solution is to define the role multiple times, and duplicate the list of roles for staging and production.
So what is the wisdom here?
Variables in Ansible are global so there is no reason to pass a variable to handler. If you are trying to make a handler parameterized in a way that you are trying to use a variable in the name of a handler you won't be able to do that in Ansible.
What you can do is create a handler that loops over a list of services easily enough, here is a working example that can be tested locally:
- hosts: localhost
tasks:
- file: >
path=/tmp/{{ item }}
state=directory
register: files_created
with_items:
- one
- two
notify: some_handler
handlers:
- name: "some_handler"
shell: "echo {{ item }} has changed!"
when: item.changed
with_items: files_created.results
I finally solved it by splitting the apps out over multiple instances of the same role. This way, the handler in the role can refer to variables that are defined as role variable.
In site.yml:
- hosts: localhost
roles:
- role: something
name: a
- role: something
name: b
In roles/something/tasks/main.yml:
- name: do something
shell: "echo {{ name }}"
notify: something happened
- name: do something else
shell: "echo {{ name }}"
notify: something happened
In roles/something/handlers/main.yml:
- name: something happened
debug:
msg: "{{ name }}"
Seems a lot less hackish than the first solution!
To update jarv's answer above, Ansible 2.5 replaces with_items with loop. When getting results, item by itself will not work. You will need to explicitly get the name, e.g., item.name.
- hosts: localhost
tasks:
- file: >
path=/tmp/{{ item }}
state=directory
register: files_created
loop:
- one
- two
notify: some_handler
handlers:
- name: "some_handler"
shell: "echo {{ item.name }} has changed!"
when: item.changed
loop: files_created.results
I got mine to work like this - I had to add some curly brackets
tasks:
- name: Aktivieren von Security-, Backport- und Non-Security-Upgrades
lineinfile:
path: /etc/apt/apt.conf.d/50unattended-upgrades
regexp: '^[^"//"]*"\${distro_id}:\${distro_codename}-{{ item }}";'
line: ' "${distro_id}:${distro_codename}-{{ item }}";'
insertafter: "Unattended-Upgrade::Allowed-Origins {"
state: present
register: aenderung
loop:
- updates
- security
- backports
notify: Auskommentierte Zeilen entfernen
handlers:
- name: Auskommentierte Zeilen entfernen
lineinfile:
path: /etc/apt/apt.conf.d/50unattended-upgrades
regexp: '^\/\/.*{{ item.item }}";.*'
state: absent
when: item.changed
loop: "{{ aenderung.results }}"

Resources