Ansible lineinfile not performing idempotency [closed] - ansible

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I have an ansible task that writes 2 lines into journald.conf, however it doesn't perform idempotency when running again.
I have seen the following questions that didn't work for me:
Ansible lineinfile duplicates line
Idempotency in ansible playbook
https://github.com/ansible/ansible/issues/4531
My regex seems to be okay, you can see below my task:
- name: set cpu affinity settings in systemd
lineinfile:
dest: /etc/systemd/journald.conf
line: "{{ item.key }}={{ item.value }}"
regexp: "^#?{{ item.value }}"
state: present
with_dict:
RateLimitIntervalSec: 0
RateLimitBurst: 0
tags: journald
notify: restart journald
The expected behavior should be: keep the commented line and add new ones at the end of the file with the items in the list, unless the uncommented lines already exists.
My file journald.conf file is like this:
[Journal]
#Storage=auto
#Compress=yes
#Seal=yes
#SplitMode=uid
#SyncIntervalSec=5m
#RateLimitIntervalSec=30s
#RateLimitBurst=1000
#SystemMaxUse=
#SystemKeepFree=
#SystemMaxFileSize=
#SystemMaxFiles=100
#RuntimeMaxUse=
#RuntimeKeepFree=
#RuntimeMaxFileSize=
#RuntimeMaxFiles=100
#MaxRetentionSec=
#MaxFileSec=1month
#ForwardToSyslog=yes
#ForwardToKMsg=no
#ForwardToConsole=no
#ForwardToWall=yes
#TTYPath=/dev/console
#MaxLevelStore=debug
#MaxLevelSyslog=debug
#MaxLevelKMsg=notice
#MaxLevelConsole=info
#MaxLevelWall=emerg
#LineMax=48K
RateLimitIntervalSec=0
RateLimitBurst=0
RateLimitIntervalSec=0
RateLimitBurst=0
RateLimitIntervalSec=0
RateLimitBurst=0
RateLimitIntervalSec=0
RateLimitBurst=0
I tried to use the parameter backrefs: yes as suggested in above mentioned articles, but it performs idempotency every time, even when there is no any uncommented line.
Do you guys have any suggestions?
I'm using ansible 2.9.0

I'd suggest an alternative approach - use the ini_file module, as settings in journald.conf are INI style key=value (with a section as well). This will simplify the task required and be idempotent as well.
Example:
- name: set cpu affinity settings in systemd
ini_file:
path: /etc/systemd/journald.conf
section: Journal
option: "{{ item.key }}"
value: "{{ item.value }}"
no_extra_spaces: yes
with_dict:
RateLimitIntervalSec: 0
RateLimitBurst: 0
Note: If you want a reference of settings prior to change, add backup: yes to the task.

Related

Ansible logical AND with conditions not working [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 months ago.
Improve this question
I try to run task depending on two conditions using logical "and". For the first condition I created the following task:
- name: Check if configuration already exists, then skip next task
stat:
path: "{{openldap_config}}/cn=config"
register: is_configured
Then I crated the following task, which is working fine:
- name: add new basic-configuration
shell: /opt/symas/sbin/slapadd -n 0 -F {{openldap_config}} -l /home/{{ansible_user}}/config.ldif
args:
executable: /bin/bash
when: not is_configured.stat.exists
If a configuration file exists the task will be skipped. Then I have a few task where I use "group_names" like this on:
- name: generating deltasyncrepl LDIF for main DB
template:
src: main_db_repl.j2
dest: /home/{{ansible_user}}/main-db-repl.ldif
owner: "{{ansible_user}}"
group: "{{ansible_group}}"
mode: '660'
when: "'ldap_provider' in group_names"
That's also working. BUT now I would like to have a logical "and" for both conditions:
- name: add replication of cn=config to all provider
shell: /opt/symas/bin/ldapmodify -Y EXTERNAL -H ldapi:/// -f /home/{{ansible_user}}/repl_config.ldif
args:
executable: /bin/bash
when: not is_configured.stat.exists
and "'ldap_provider' in group_names"
This is not working. I tried different quoting but I could not find a a working solution. I try it with brackets too, also not working. Some how it must be possible to have a logical AND with a int- and a string- variable.
Thanks for any help
While you can manually stat the file and that works just fine, this is actually exactly the case that the creates parameter to the shell and command modules is designed to handle. You should also migrate to the cmd parameter (supported since Ansible 2.0) instead of using args, so that people reading your code don't have to understand that rarely-used syntax:
- name: Basic configuration for OpenLDAP
shell:
cmd: /opt/symas/sbin/slapadd -n 0 -F {{ openldap_config }} -l /home/{{ ansible_user }}/config.ldif
executable: /bin/bash
creates: "{{ openldap_config }}/cn=config"
register: openldap_config_result
While you didn't include your other attempts at solving this problem, generally the best way to apply multiple conditions to a task is to use a list, which will implicitly apply and between each condition in the list:
- name: Add replication of cn=config to all providers
shell:
cmd: /opt/symas/bin/ldapmodify -Y EXTERNAL -H ldapi:/// -f /home/{{ ansible_user }}/repl_config.ldif
executable: /bin/bash
when:
- openldap_config_result is changed
- "'ldap_provider' in group_names"
You can also do it as a single string, though you have to make sure your quoting is correct (which it isn't in your question):
when: openldap_config_result is changed
and 'ldap_provider' in group_names

Substraction within an Ansible space calculation [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 months ago.
Improve this question
I try to subtract 2 variables in Ansible, but what I get is zero in the result.
- name: ansible calculate space
hosts: pghosts
gather_facts: false
tasks:
- name: Check /srv freespace
shell: df /srv --output\=avail | tail -1
register: srv_freespace
- name: Check postgres data dir size
shell: du -ks /srv/postgresql/data |awk '{ print $1 }'
register: postgres_data
- debug:
msg: "substraction {{ srv_freespace|int - postgres_data|int }}"
- copy: content="{{ srv_freespace|int - postgres_data|int }}" dest=/tmp/results.txt
Try changing the last line to:
- copy: content="{{ srv_freespace.stdout|int - postgres_data.stdout|int }}" dest=/tmp/results.txt
Explanation: the registered variable is not a string, its a dict. The dict includes several keys like the command name, command start and end time, exit code and other good stuff. The actual value i.e. what is printed to standard output is under the stdout key.

how to escape single quotes in ansible variables registered during execution. I cannot use "\" since the variable is unknown until its registered [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
When a registered variable has a single quote in it, for example
if value of var.stdout is IxMy5NPG'dCbrHD (note the single quote in string)
When I use this variable in an upcoming task,
lineinfile:
path: /path/to/file.j2
regexp: "X1234"
line: {{ var.stdout }}
mode: 0755
state: present
I get the follwing error
ERROR! failed at splitting arguments, either an unbalanced
jinja2 block or quotes
This only occurs if there is a single quote in the string, which may or may not have a single quote. Hence I cannot expect this already and handle it. I tried a regex_replace filter on the variable like {{ var.stdout | regex_replace("'", "\'") }} I get "Unexpected failure during module execution."
The expression {{ var.stdout }} must be quoted
lineinfile:
path: file.j2
regexp: X1234
line: {{ var.stdout }} # <-- WRONG
For example, given the file
shell> cat file.j2
X1234
The task below
lineinfile:
path: file.j2
regexp: X1234
line: "{{ var.stdout }}" # <-- CORRECT
works as expected
shell> cat file.j2
IxMy5NPG'dCbrHD
If you want to replace the quote for example with the underscore "_"
- set_fact:
var_stdout: "{{ var.stdout|regex_replace(_regex, _replace) }}"
vars:
_regex: "'"
_replace: "_"
gives
var_stdout: IxMy5NPG_dCbrHD
To avoid escaping put _regex/_replace into the task's vars.
If you want to escape the quote
_replace: "\\'"
gives
var_stdout: IxMy5NPG\'dCbrHD

Execute on host conditionally, Ansible [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm attempting to create a conditional in my playbook that switches based on an ENV defined in a Dockerfile. The playbook is copied in by the Dockerfile, and Ansible runs it against localhost to do some configuration. However, these playbooks are also used to configure an ordinary server.
Here's my question: Is is possible to use a conditional when defining hosts?
- hosts: actual_server
roles:
- some_roles
when:
- DOCKER_CONTAINER is not defined
- hosts: docker_container
roles:
- almost_same_roles
when:
- DOCKER_CONTAINER is true
I've hunted through the Ansible docs, and found several examples where multiple hosts are targeted in a single playbook, but I an unsure if my syntax for the conditional is wrong, or if what I want to accomplish simply cannot be done. Am I limited to defining conditionals only on a role-by-role basis?
I'd be glad to edit this question, to make it more clear, since it has been closed for being "unclear"... but I'm not sure how much MORE clear I could be, than stating exactly what I'm asking in the above. Glad for more specific feedback if anyone is willing to give it.
It honestly feels like this behavior should be pushed lower into the tasks as opposed to the role level. Roles describe how to accomplish a specific state through a list of tasks, and the tasks themselves perform the steps in order to accomplish that specific state.
With that said, it makes sense to have the logic in the task to determine whether or not it will execute. This means that your role some_roles would look like this (warning: untested).
# In tasks/playbook.yml
- hosts: actual_server
roles:
- some_roles
vars:
environment_type: Server
- hosts: docker_container
roles:
- some_roles
vars:
environment_type: Docker
# In vars/main.yml file
environment_type: Server
# In tasks/main.yml
- name: Download a tarball
get_url:
url: "https://example.com/some_package.tar.gz"
dest: /tmp
mode: 0750
when: environment_type == 'Docker'
If you want to run one ansible script for the different environment.
Here is your answer, you can go with inventory file for each environment generated by docker(if needed).
ansible-playbook playbook.yml -i development.ini
ansible-playbook playbook.yml -i testing.ini
ansible-playbook playbook.yml -i staging.ini
development.ini
[actual_server]
192.168.0.100 # some IP address
[docker_container]
127.0.0.1
testing.ini
[actual_server]
192.168.0.101 # some IP address
[docker_container]
127.0.0.1
https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
https://symfonycasts.com/screencast/ansible/hosts-inventory
Not the ideal answer, but you can use a when condition on each role:
- hosts: actual_server
roles:
- role: role1
when: DOCKER_CONTAINER is not defined
- role: role2
when: DOCKER_CONTAINER is not defined
...
- hosts: docker_container
roles:
- role: role3
when: DOCKER_CONTAINER is true
- role: role4
when: DOCKER_CONTAINER is true
...

Syntax error on the last line in the ansible playbook [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
All,
My playbook is almost ready. Only the last line with alias is giving me issues. I tried to look at what I am doing wrong in the yaml syntax checker but still not able to find it. Any clue what I am doing wrong? I tried escaping the forward slash but still no luck :(
I am bad at finding the syntax errors in general. So appreciate any clues you folks can provide in finding the problem.
tasks:
- name: Create a KMS key for using the aws cli
command: 'aws kms create-key --profile="{{ aws_profile }}" --region="{{ aws_region }}"'
register: newkeydetails
- name: Display the values for the variable output
set_fact: newkeydetails="{{ newkeydetails.stdout | from_json }}"
- name: Display the value of keyid
debug:
msg: "{{ newkeydetails.KeyMetadata.KeyId }}"
- name: Create a alias name for KMS key using the aws cli
command: 'aws kms create-alias --alias-name 'alias/anothernewkeydetailskey' --target-key-id '"{{ newkeydetails.KeyMetadata.KeyId }}"' --profile="{{ aws_profile }}" --region="{{ aws_region }}"'
The reason for the issue here was due to the usage of single quotes in the last line, as they were not escaped, resulting in parsing errors.
The working solution involves removing unnecessary quotes, resulting in the following:
'aws kms create-alias --alias-name "alias/anothernewkeydetailskey" --target-key-id "{{ newkeydetails.KeyMetadata.KeyId }}" --profile="{{ aws_profile }}" --region="{{ aws_region }}"

Resources