Ansible escaping a string issue on mac vs ubuntu? - macos

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 }}"

Related

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 - only last with_items being updated in file

Using blockinfile: which is using with_items from an exernal file. When I run the playbook I can see all itmes being processed but the resulting end file only has the last item updated.
Apologies, bit of a noob to this, so might be missing something obvious.
Tried various permutations
I have an external yaml config file with following contents - which is included as include_vars:
yaml props file:
ds_props:
- prop: dataSource.initialSize=8
- prop: dataSource.maxActive=50
- prop: dataSource.maxIdle=20
- prop: dataSource.minIdle=5
- prop: dataSource.maxWait=1000
Ansible tasks:
- name: update DS settings
blockinfile:
path: /app.properties
insertafter: "##### Data Source Properties"
block: |
"{{ item.prop }}"
with_items: "{{ ds_props }}"
Expected:
##### Data Source Properties #####
# BEGIN ANSIBLE MANAGED BLOCK
dataSource.initialSize=8
dataSource.maxActive=50
dataSource.maxIdle=20
dataSource.minIdle=5
dataSource.maxWait=1000
# END ANSIBLE MANAGED BLOCK
Actual:
##### Data Source Properties #####
# BEGIN ANSIBLE MANAGED BLOCK
dataSource.maxWait=1000
# END ANSIBLE MANAGED BLOCK
blockinfile uses a marker to keep track of the blocks it manages in a file. By default, this marker is ANSIBLE MANAGED BLOCK.
What happens in your case since you use the default marker is that a block is created after the line "##### Data Source Properties" for the first item then edited for the next items.
One solution would be to change the marker for each item. An other is to use lineinfile as reported by #Larsk
I would prefer in this case creating the full block at once:
- name: update DS settings
blockinfile:
path: /app.properties
insertafter: "##### Data Source Properties"
marker: "Custom ds props - ansible managed"
block: "{{ ds_props | json_query('[].prop') | join('\n') }}"
If your intent is to do more complicated stuff with your config file, follow #Larsk advice and use a template.
blockinfile is behaving exactly as designed: it adds a block of text to a target file, and will remove the matching block before adding a modified version. So for every iteration of your loop, blockinfile is removing the block added by the previous iteration and adding a new one.
Given that you're adding single lines to the file, rather than a block, you're probably better off using the lineinfile module, as in:
---
- hosts: localhost
gather_facts: false
vars:
ds_props:
- prop: dataSource.initialSize=8
- prop: dataSource.maxActive=50
- prop: dataSource.maxIdle=20
- prop: dataSource.minIdle=5
- prop: dataSource.maxWait=1000
tasks:
- name: update DS settings using lineinfile
lineinfile:
path: /app.properties-line
line: "{{ item.prop }}"
insertafter: "##### Data Source Properties"
with_items: "{{ ds_props }}"
While this works, it's still problematic: if you change the value of one of your properties, you'll end up with multiple entries in the file. E.g, if we were to change dataSource.maxWait from 1000 to 2000, we would end up with:
dataSource.maxWait=1000
dataSource.maxWait=2000
We can protect against that using the regexp option to the lineinfile module, like this:
- name: update DS settings using lineinfile
lineinfile:
path: /app.properties-line
line: "{{ item.prop }}"
insertafter: "##### Data Source Properties"
regexp: "{{ item.prop.split('=')[0] }}"
with_items: "{{ ds_props }}"
This will cause the module to remove any existing lines for the particular property before adding the new one.
Incidentally, you might want to consider slightly restructuring your data, using a dictionary rather than a list of "key=value" strings, like this:
---
- hosts: localhost
gather_facts: false
vars:
ds_props:
dataSource.initialSize: 8
dataSource.maxActive: 50
dataSource.maxIdle: 20
dataSource.minIdle: 5
dataSource.maxWait: 1000
tasks:
- name: update DS settings using lineinfile
lineinfile:
path: /app.properties-line
line: "{{ item.key }}={{ item.value }}"
insertafter: "##### Data Source Properties"
regexp: "{{ item.key }}"
with_items: "{{ ds_props|dict2items }}"
And lastly, rather than using lineinfile or blockinfile, you might want to consider using ansible's template module to create your /app.properties file rather than trying to edit it.

Ansible find replace is not working for 2 lines

- name: Cassandra cassandra.yaml
lineinfile:
dest: "{{ home}}/conf/cassandra.yaml"
state: present
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
# backup: yes
with_items:
- { regexp: "data_file_directories:", line: "data_file_directories: \n - {{ data_directory }}" }
in the first file first run it looks good but in the second run it keeps adding new line. what needs to be done in order to the second run also looks good.
data_file_directories:
- /mount1/data
second run
data_file_directories:
- /mount1/data
- /mount1/data
- /mount1/data
I want some thing like
data_file_directories:
- /mount1/data
lineinfile ― as its name suggest ― is a module to ensure a certain line is in the target file; not lines.
To deal with multiple lines either:
use regexp module with matchgroup and backreference ― the exact implementation is dependent on other constructs in the target file,
use blockinfile module ― the exact implementation is dependent on other constructs in the target file,
or (preferably) use template module.

Ansible Lineinfile insert after syntax issues

Having some issues with my code and can't figure out the syntax error.
I'm trying to take output from a firewall and put it into an html file but i keep getting stuck. The command in its own separate file outputs a couple of lines of text. Note destination changed to protect it.
- hosts: firewall
gather_facts: no
tasks:
- name: Hardware Info
raw: show asset all
register: output
- local_action: lineinfile dest=dest destination regexp="{{item}}" insertafter="test" line={{item}}
with_items: output.stdout_lines
Error:
local_action: lineinfile dest=dest insertafter="test"
line='{{item}}'
^ 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 }}"
Change this line:
- local_action: lineinfile dest=dest destination regexp="{{item}}" insertafter="test" line={{item}}
To this:
- local_action: lineinfile dest=dest destination regexp="{{item}}" insertafter="test" line="{{item}}"
The extra quotes should help.
Note lineinfile is terrible from a configuration management point of view, I predict you'll pull your hair out in the future.

Why is conditional not working?

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.

Resources