Replace text using saltstack - jinja2

I will need your assistance on the following:
I would like to replace an IP address within a file, regex is matching, but the output is totally wrong.
test.sls
wsc_start_server:
file.managed:
- name: /tmp/modify.txt
- source: salt://modify.txt
{% set ip = grains['fqdn_ip4'] %}
wsc_jbos_replace_hostname:
file.replace:
- name: /tmp/modify.txt
- pattern: '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
- repl: {{ ip }}
- backup: '.bak'
- show_changes: True
modify.txt
address=y.y.y.y
address.private=y.y.y.y
salt 'workstation' state.apply test.sls
output:
address=['x.x.x.x']
address.private=['x.x.x.x']
When I am running the state why I am getting the ip address in ['x.x.x.x'] format instead of address=x.x.x.x ????
Note: y.y.y.y & x.x.x.x are IP Addresses

The issue is that the fqdn represent a list.
to fix the issue I change the following:
{% set ip = grains['fqdn_ip4'] %}
wsc_jbos_replace_hostname:
file.replace:
- name: /tmp/modify.txt
- pattern: '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
- repl: {{ ip }}
- backup: '.bak'
- show_changes: True
to the correct one:
{% set ip = grains['fqdn_ip4'][0] %}
wsc_jbos_replace_hostname:
file.replace:
- name: /tmp/modify.txt
- pattern: '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
- repl: {{ ip }}
- backup: '.bak'
- show_changes: True
it worked. :) :)

Related

How to get the return code in saltstack state

Do you know how I can parse the data from stdout and searching within it?
check_satellite_registration:
cmd.run:
- name: subscription-manager list
For example, see the return data below. How can I evaluate the Status in stdout?
retcode:
0
stderr:
stdout:
Status: Subscribed
If the above status is "Subscribed" then continue the execution of the states, otherwise redo the installation:
deploy the http.conf file:
file.managed:
- name: /etc/http/conf/http.conf
- source: salt://apache/http.conf
There are a couple of options. They all involve not using a state for the check, because it doesn't do anything stateful.
deploy the http.conf file:
file.managed:
- name: /etc/http/conf/http.conf
- source: salt://apache/http.conf
- onlyif:
- subscription-manager list | grep 'Status: Subscribed'
do something else:
cmd.run:
- unless:
- subscription-manager list | grep 'Status: Subscribed'
{% set status = salt["cmd.run"]("subscription-manager list") %}
{% if "Status: Subscribed" in status %}
deploy the http.conf file:
file.managed:
- name: /etc/http/conf/http.conf
- source: salt://apache/http.conf
{% else %}
do something else:
cmd.run: []
{% endif %}
Though if your "something else" action is supposed to result in the status becoming subscribed, then you should do it like this instead:
register satellite:
cmd.run:
- name: my-register-command
- unless:
- subscription-manager list | grep 'Status: Subscribed'
deploy the http.conf file:
file.managed:
- name: /etc/http/conf/http.conf
- source: salt://apache/http.conf
- require:
- register satellite

Ansible save output from multiple hosts

I'm facing the issue with ansible playbook, I want to collect the info about all servers to a single file. Simly speaking I need gather info from all servers specified under hosts file.
Here is my .yml file:
---
- hosts: idrac
connection: local
name: Get system inventory
gather_facts: False
collections:
- dellemc.openmanage
tasks:
- name: Get system inventory
dellemc_get_system_inventory:
idrac_ip: "{{ idrac_ip }}"
idrac_user: "root"
idrac_password: "root"
register: result
- name: Copy results locally to output file
copy:
content: "{{ result }}"
dest: "./output/system_inventory_output.json"
delegate_to: localhost
But the problem is that I check output file, it contains json data only from one server.
I've been browsing the Net but till now did not find any working solution for that...
Any idea how to achieve that?
Thanks!
Create the output file in a second play, and iterate over all the hosts using a template. Something like this:
---
- hosts: idrac
connection: local
name: Get system inventory
gather_facts: False
collections:
- dellemc.openmanage
tasks:
- name: Get system inventory
dellemc_get_system_inventory:
idrac_ip: "{{ idrac_ip }}"
idrac_user: "root"
idrac_password: "root"
register: system_inventory
- hosts: localhost
gather_facts: false
tasks:
- name: Write results to local output file
copy:
dest: "./output/system_inventory_output.json"
content: |
{% for host in groups.idrac %}
=== {{ host }} ==
{{hostvars[host].system_inventory}}
{% endfor %}
You might elect to use the template module rather than embedding the template in the content argument of the copy module, as I have done here.

Extracting values from YAML into Jinja template for Ansible playbook

I have a YAML file with content as like below:
cat ../../ansible/playbooks/vars/patching-config.yml
---
patching_tag_name: "Patching"
my_windows_patching:
- {
OS: "WINDOWS",
tag_value: "myProdA",
frequency: "Month", #patching frequency. OneTime|Day|Hour|Week|Month|Minute
interval: 1, #interval of the schedule.
rebootSetting: "never", #ifRequired|never|always
PatchGroup: testA,
startDate: "2020-01-16T23:59:59Z",
expiryDate: "2020-02-16T23:59:59Z",
duration: "PT2H0M",
timeZone: "Australia/Sydney",
updateClassifications: "Critical,Important,Moderate"
}
I want to extract the values of updateClassifications from above YML file in Jinja Template file MaintenanceWindow.yml.j2
Resources:
WindowsNonProdBaseline:
Type: AWS::SSM::PatchBaseline
Properties:
Name: Windows-Non-Prod-Baseline
Description: Baseline containing all updates approved for Windows instances
OperatingSystem: {{ item.OS }}
PatchGroups:
- {{ item.PatchGroup }}
ApprovalRules:
PatchRules:
- PatchFilterGroup:
PatchFilters:
- Values:
# - Critical
# - Important
# - Moderate
{% for item in item.updateClassifications %}
- {{ item }}
{% endfor %}
I'm trying with the code described above, below one more time snippet:
{% for item in item.updateClassifications %}
- {{ item }}
{% endfor %}
I'm calling patching-config.yml in my tasks/main.yml as below
- include_vars: "{{playbook_dir}}/vars/patching-config.yml"
ignore_errors: yes
- name: create a cloudformation stack
cloudformation:
stack_name: "New-Ansible-cloudformation"
state: "present"
disable_rollback: true
template_body: "{{ lookup('template', '../../cloudformation/patching/MaintenanceWindow.yml.j2') }}"
with_items: "{{ telstra_windows_patching }}"
Finally, invoking role as below
cat ansible/playbooks/patching.yml
---
- hosts: localhost
roles:
- patching-cf-ssm
Unfortunately, it is not working.
Any lead shall be greatly appreciated.
Couple of things:
Your task is using telstra_windows_patching in with_items where as your variable file has variable name as my_windows_patching.
Assuming you are using the same name say my_windows_patching in your task and var file, if you are trying to save json object in yaml variable my_windows_patching you don't need - before curly braces. You can define something like this
my_windows_patching:
{
OS: "WINDOWS",
tag_value: "myProdA",
frequency: "Month", #patching frequency. OneTime|Day|Hour|Week|Month|Minute
interval: 1, #interval of the schedule.
rebootSetting: "never", #ifRequired|never|always
PatchGroup: testA,
startDate: "2020-01-16T23:59:59Z",
expiryDate: "2020-02-16T23:59:59Z",
duration: "PT2H0M",
timeZone: "Australia/Sydney",
updateClassifications: "Critical,Important,Moderate"
}
If you want to use elements inside my_windows_patching object with dot notation directly you could change the variable from object to a list something like,
my_windows_patching:
- OS: "WINDOWS"
tag_value: "myProdA"

Rendering SLS: mapping values are not allowed here

I try to place / remove a drop in config file based on a PILLAR variable.
This was put in highstate/init.sls on my salt master.
I cannot see any syntax error or spacing issues here.
What am i doing wrong here?
Here my SLS file
(% if pillar['highstateenabled'] == 'true' %)
enable_highstate:
file.managed:
- name: /etc/salt/minion.d/highstate.conf
- source: salt://common/salt-minion/files/minion.d/highstate.conf
- template: jinja
(% else %)
disable_highstate:
file.absent:
- name: /etc/salt/minion.d/highstate.conf
(% endif %)
And the output during salt-call:
---
local:
Data failed to compile:
----------
Rendering SLS 'LAB:common.salt-minion' failed: mapping values are not allowed here; line 4
---
(% if pillar['highstateenabled'] == 'true' %)
enable_highstate: <======================
file.managed:
- name: /etc/salt/minion.d/highstate.conf
- source: salt://common/salt-minion/files/minion.d/highstate.conf
- template: jinja
[...]
---
finally i found the solution myself:
The code above is using the wrong brackets.
Instead using "()" it should be curly brackets "{}" and the code is beeing parsed correctly.
The SLS Rendering error does not point to a syntax error here...
{% if pillar['highstate'] == 'enabled' %}
output:
cmd.run:
- name: 'echo "highstate_enabled" '
enable_highstate:
file.managed:
- name: /etc/salt/minion.d/highstate.conf
- source: salt://common/salt-minion/files/minion.d/highstate.conf
- template: jinja
{% else %}
disable_highstate:
file.absent:
- name: /etc/salt/minion.d/highstate.conf
{% endif %}
"seems sometimes you don't see the forest because of too many tree's"

Salt: Can I use an argument from the command line as a jinja variable?

Given a file called package-list, I want to do something like:
salt state.sls install-packages list_to_install=package-list
...and then in the sls:
packages:
pkg.installed:
- names:
{% include list_to_install %}
You can do this using Pillar:
packages:
pkg:
- installed
- pkgs: {{ salt['pillar.get']('packages') }}
Then pass the pillar argument containing valid YAML:
salt '*' state.sls package-list pillar='{packages: [foo, bar, baz]}'