Conditional when win_service exists? - windows

I'm creating playbook to install fluentbit on windows hosts. Everything is working properly but i'm getting error when creating service, it doesn’t fail the install as then everything is already in place but I would like to figure out how I could leverage conditionals. Could you help me with this? :)
My adhoc test-play where I've tried to parse results from ansible.windows.win_service_info module is as follows:
---
- name: Check Windows service status
hosts: win
gather_facts: True
tasks:
- name: Check if a service is installed
win_service:
name: fluent-bit
register: service_info
- debug: msg="{{service_info}}"
- name: Get info for a single service
ansible.windows.win_service_info:
name: fluent-bit
register: service_info
- debug: msg="{{ service_info }}"
- name: Get info for a fluent-bit service
ansible.windows.win_service_info:
name: logging
register: service_exists
- debug: msg="{{ service_exists }}"
- name: Send message if service exists
debug:
msg: "Service is installed"
when: service_exists.state is not defined or service_exists.name is not defined
- name: Send message if service exists
debug:
msg: "Service is NOT installed"
when: service_exists.state is not running
I just don’t get it how I could parse output so that I could skip task when fluent-bit -service exists = True like here:
TASK [debug] *****************************************************************************************
ok: [win-server-1] => {
"msg": {
"can_pause_and_continue": false,
"changed": false,
"depended_by": [],
"dependencies": [],
"description": "",
"desktop_interact": false,
"display_name": "fluent-bit",
**"exists": true,**
"failed": false,
"name": "fluent-bit",
"path": "C:\\fluent-bit\\bin\\fluent-bit.exe -c C:\\fluent-bit\\conf\\fluent-bit.conf",
"start_mode": "manual",
"state": "stopped",
"username": "LocalSystem"
}
}
Cheers :)

So, got it working as I wanted with service_info.exists != True, now it will skip the task if service is already present.

Related

Ansible register variable from facts output

I'm using Ansible playbook to get information about the server's hardware internals through iDrac controller. It is performed by 3rd party module, which uses API to connect to the device.
I get server's internals info (controllers, disks, CPU information, etc.) by running the task. And I would like to register some variables from such output (the output is just shortened by dots).
I kept the main structure of output, to make it clear:
ok: [rac1] => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"invocation": {
"module_args": {
"ca_path": null,
"idrac_ip": "192.168.168.100",
"idrac_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"idrac_port": 443,
...
}
},
"msg": "Successfully fetched the system inventory details.",
"system_info": {
"BIOS": [
{
"BIOSReleaseDate": "09/14/2022",
"FQDD": "BIOS.Setup.1-1",
…
}
],
"CPU": [
{
"CPUFamily": "Intel(R) Xeon(TM)",
"Characteristics": "64-bit capable",
"CurrentClockSpeed": "2.1 GHz",
…
},
{
"CPUFamily": "Intel(R) Xeon(TM)",
"Characteristics": "64-bit capable",
…
}
],
"Controller": [
{
"Bus": "67",
"CacheSize": "8192.0 MB",
"DeviceDescription": "RAID Controller in SL 3",
"FQDD": "RAID.SL.3-1",
"Key": "RAID.SL.3-1",
…
},
I need to get only couple values from output (PCI slot num where RAID controller is located):
"DeviceDescription": "RAID Controller in SL 3",
"Key": "RAID.SL.3-1"
But I have no clue, which example from documentation can I use to register value to variable.
Considering this is a third party module. The task execution is very slow, so it is not so easy for me to play with it as much as possible.
Could somebody suggest me please, which direction should I dig? I'm not a big expert in Ansible yet.
My role's tasks are following below.
I tried to get nested values using debug task(just to figure out key which I need to register), like this, but no luck:
### Get inventory key:value pairs and trying to save certain value to variable ###:
- name: Get Inventory
dellemc.openmanage.idrac_system_info:
idrac_ip: "{{ idrac_ip }}"
idrac_user: "{{ idrac_user }}"
idrac_password: "{{ idrac_password }}"
validate_certs: False
register: ansible_facts[system_info][Controller][FQDD].result
### Trying to show my saved variable in this task ###
- name: print registered value
debug:
var: RAID slot is at "{{ result }}"
verbosity: 4
I get this message after launching playbook:
"msg": "Unsupported parameters for (dellemc.openmanage.idrac_system_info) module: register. Supported parameters include: idrac_ip, timeout, idrac_user, ca_path, idrac_port, validate_certs, idrac_password (idrac_pwd)."
Since you are providing already valid output, how do have generated that? How was it "printed"?
A minimal example playbook
---
- hosts: rac1
become: false
gather_facts: false
vars:
result:
system_info: {
"BIOS": [
{
"BIOSReleaseDate": "09/14/2022",
"FQDD": "BIOS.Setup.1-1"
}
],
"CPU": [
{
"CPUFamily": "Intel(R) Xeon(TM)",
"Characteristics": "64-bit capable",
"CurrentClockSpeed": "2.1 GHz"
},
{
"CPUFamily": "Intel(R) Xeon(TM)",
"Characteristics": "64-bit capable"
}
],
"Controller": [
{
"Bus": "67",
"CacheSize": "8192.0 MB",
"DeviceDescription": "RAID Controller in SL 3",
"FQDD": "RAID.SL.3-1",
"Key": "RAID.SL.3-1"
}
]
}
tasks:
- name: Show Facts
debug:
msg: "{{ result.system_info.Controller }}"
will result already into the expected output of
TASK [Show Facts] *****************************
ok: [rac1] =>
msg:
- Bus: '67'
CacheSize: 8192.0 MB
DeviceDescription: RAID Controller in SL 3
FQDD: RAID.SL.3-1
Key: RAID.SL.3-1
Regarding
which example from documentation can I use to register value to variable.
you may read about Registering variables. For registering results, even for 3rd-party or Custom Modules the structure will be
- name: Task
module_name:
module_parameter: values
register: variable_name
That's why you get an syntax error
Unsupported parameters for (dellemc.openmanage.idrac_system_info) module: register.
about the incorrect indention. Therefore try first
- name: Get Inventory
dellemc.openmanage.idrac_system_info:
idrac_ip: "{{ idrac_ip }}"
idrac_user: "{{ idrac_user }}"
idrac_password: "{{ idrac_password }}"
validate_certs: False
register: inventory
- name: Show Inventory
debug:
msg: "{{ inventory }}"
to get familiar with the result set and data structure.
Further documentation which might help are Return Values and idrac_system_info module – Get the PowerEdge Server System Inventory.

Unable to gather datastore facts with vmware_datastore_info module

I'm trying to collect the VMware datastore info from the ansible module community.vmware.vmware_datastore_info with the below task and debug the same:
- name: Gather info from datacenter about specific datastore
community.vmware.vmware_datastore_info:
hostname: '{{ vcenter_hostname }}'
username: '{{ username }}'
password: '{{ password }}'
datacenter_name: '{{ datacenter_name }}'
name: ENV04
validate_certs: False
delegate_to: localhost
register: info
- debug:
msg: "{{ info }}"
The debug task is returning the below output:
TASK [Gather info from datacenter about specific datastore] ************************************************************************************************************
ok: [172.17.92.2 -> localhost]
TASK [debug] ***********************************************************************************************************************************************************
ok: [172.17.92.2] => {
"msg": {
"changed": false,
"datastores": [],
"failed": false
}
}
Rather than the one mentioned in the ansible-doc for this module:
RETURN VALUES:
- datastores
metadata about the available datastores
returned: always
sample:
- accessible: true
capacity: 5497558138880
datastore_cluster: datacluster0
freeSpace: 4279000641536
maintenanceMode: normal
multipleHostAccess: true
name: datastore3
nfs_path: /vol/datastore3
nfs_server: nfs_server1
provisioned: 1708109410304
type: NFS
uncommitted: 489551912960
url: ds:///vmfs/volumes/420b3e73-67070776/
Can anyone suggest what was the issue, as I was getting the expected output before and now it is not coming.

ansible rabbitmq purge queue

I have ansible playbook where I want purge all queues in rabbitmq
- name: Get queues
uri:
url: http://localhost:15672/api/queues
method: GET
return_content: yes
status_code: 200,404
body_format: json
register: result
- name: Just the Names
debug: msg="{{ result.json | json_query(jmesquery)}}"
vars:
jmesquery: "[*].name"
register: queue_name
Return list queues
TASK [demo : Just the Names] ***
ok: [test] => {
"msg": [
"test1",
"test2"
]
}
How to do a loop for queues
- name: delete queues
uri:
url: http://localhost:15672/api/queues/aaa/{{ queue_name }}/contents"
method: DELETE
You could try:
- name: delete queues
uri:
url: "http://localhost:15672/api/queues/aaa/{{ item }}/contents"
method: DELETE
loop: "{{ result.json | json_query(jmesquery)}}"
vars:
jmesquery: "[*].name"

Using url module with jinja2 templates

I know how to process jinja2 templates files and let them create files. I also know how to POST to webservices using the url module.
For now I use some code like this, which successfully posts hardcoded JSON to my remote service:
tasks:
- name: GSA app definition
uri:
url: "http://localhost:8764/api/apps?relatedObjects=false"
method: POST
force_basic_auth: yes
user: "{{ admin_name }}"
password: "{{ admin_pass }}"
body_format: json
body: "{\"name\":\"My new app\", \"description\":\"A really great new app\" }"
follow_redirects: all
status_code: 200
timeout: 15
register: app_gsa_cfg
But the JSON is static, how can I process a jinja2 template and POST its content ? I would prefer not having to create temporary files on disk and POST them, what I am looking for is a direct connection or perhaps an approach that puts the template processing result into a string.
For starters a jinja2 template could look like this, later I will add variables too:
{#
This file creates the basic GSA app in Fusion. See https://doc.lucidworks.com/fusion-server/4.2/reference-guides/api/apps-api.html#create-a-new-app for details
#}
{
"name": "GSA",
"description": "Contains all configuration specific to the migrated GSA legacy searches"
}
(I know that this has little advantage over a static json included into the playbook. But is is easier to edit and offers me the opportunity to have (jinja style) comments in Json, which is normally not possible)
In my case, what I do is the following:
I have an API, so I do the following:
- name: Change API Status
uri:
url: "{{ enpoint }}/v1/requests/{{ whatever }}"
method: PATCH
user: "{{ tokenid }}"
password: x
headers:
X-4me-Account: "myaccount"
body: '{ "status":"{{ reqstatus }}" }'
body_format: json
status_code:
- 201
- 200
force_basic_auth: true
validate_certs: false
return_content: true
Then your reqstatus var will change.
Even you can add your whole text as yaml, import into a variable and convert with filters {{ some_variable | to_json }}
Note: Have a look to the formatting without escaping quotes. That will help.
It makes no sense creating a file with jinja2 if you are not going to copy it remotely. Ansible supports jinja natively but its strength is the possibility to have plugins for better maintainability. There is no difference between template (or win_template) modules unless (as said) you copy the file somewhere. Look this example:
---
- name: Adhoc Jinja
hosts: localhost
connection: local
gather_facts: false
vars:
mytemplate:
- name: "GSA"
description: "Contains all configuration specific to the migrated GSA legacy searches"
- name: "Another Name"
description: "Contains Another Var"
tasks:
- name: Read Vars Loop
debug:
msg: "{{ item | to_json }}"
with_items: "{{ mytemplate }}"
- name: Include Vars
include_vars: adhocjinja2.yml
- name: Read Vars Loop
debug:
msg: "{{ item | to_json }}"
with_items: "{{ mytemplate }}"
And adhocjinja2.yml:
mytemplate:
- name: "GSA2"
description: "Contains all configuration specific to the migrated GSA legacy searches"
- name: "Another Name 2"
description: "Contains Another Var"
The output is:
TASK [Read Vars Loop] **************************************************************************************
ok: [localhost] => (item={'name': 'GSA', 'description': 'Contains all configuration specific to the migrated GSA legacy searches'}) => {
"msg": "{\"name\": \"GSA\", \"description\": \"Contains all configuration specific to the migrated GSA legacy searches\"}"
}
ok: [localhost] => (item={'name': 'Another Name', 'description': 'Contains Another Var'}) => {
"msg": "{\"name\": \"Another Name\", \"description\": \"Contains Another Var\"}"
}
TASK [Include Vars] ****************************************************************************************
ok: [localhost]
TASK [Read Vars Loop] **************************************************************************************
ok: [localhost] => (item={'name': 'GSA2', 'description': 'Contains all configuration specific to the migrated GSA legacy searches'}) => {
"msg": "{\"name\": \"GSA2\", \"description\": \"Contains all configuration specific to the migrated GSA legacy searches\"}"
}
ok: [localhost] => (item={'name': 'Another Name 2', 'description': 'Contains Another Var'}) => {
"msg": "{\"name\": \"Another Name 2\", \"description\": \"Contains Another Var\"}"
}
You can manage your variables as you want and create your json on the fly as Ansible has jinja and json it its heart.

Why is this basic ansible playbook throwing an error?

I am trying to understand how ansible playbooks are structured and I am failing at a basic example:
---
- hosts: all
tasks:
# update dependencies
- name: install apt dependencies
apt: name={{ item }}
with_items:
- python3-arrow
- python3-netifaces
- python3-requests
- python3-docopt
- name: install pip3 dependencies
pip: name=scapy-python3 executable=pip3
# install service
- name: copy source file
copy: src=honeysyn.py dst=/opt/sentinel-honeysyn/honeysyn.py
- name: copy service file
copy: src=honeysyn.service dst=/etc/systemd/system/honeysyn.service mode=0644
- name: install service, restart and enable
systemd:
name: honeysyn
daemon_reload: yes
enabled: yes
started: yes
The error is:
The offending line appears to be:
copy: src=honeysyn.service dst=/etc/systemd/system/honeysyn.service mode=0644
- name: install service, restart and enable
^ here
I checked the consistency of the YAML file and the JSON output makes sense:
[
{
"tasks": [
{
"name": "install apt dependencies",
"apt": "name={{ item }}",
"with_items": [
"python3-arrow",
"python3-netifaces",
"python3-requests",
"python3-docopt"
]
},
{
"pip": "name=scapy-python3 executable=pip3",
"name": "install pip3 dependencies"
},
{
"copy": "src=honeysyn.py dst=/opt/sentinel-honeysyn/honeysyn.py",
"name": "copy source file"
},
{
"copy": "src=honeysyn.service dst=/etc/systemd/system/honeysyn.service mode=0644",
"name": "copy service file"
},
{
"systemd": {
"started": true,
"enabled": true,
"name": "honeysyn",
"daemon_reload": true
},
"name": "install service, restart and enable"
}
],
"hosts": "all"
}
]
I found out that the errors are often very much off the real bug (I had the same case as above, but it was an extra space after a = in a completely different place) - thus the whole playbook.
What is wrong with this playbook?
The systemd module that you are attempting to use is present in Ansible 2.2 (which is not released as far as I know) and hence will not work with any of the currently available Ansible versions.
https://docs.ansible.com/ansible/systemd_module.html
As #Amit pointed out, it's not released yet.
Ansible seems to have a very zealous documentation release schedule, which sometimes outstrips the release of the actual supporting code :-)
Maybe try the service module instead for now, something like this should work:
- name: install service, enable and start
service:
name: honeysyn
enabled: yes
state: started

Resources