ansible problem with single quote, double quote in uri body - ansible

I have a problem with the correct syntax to address an API with absolutely don't understands any json arguments.
In the body must be exactly one value in this form '["XXXX"]' so that it works.
- uri:
url: "{{ AssociatePolicies_url }}"
method: POST
return_content: yes
validate_certs: no
body_format: form-urlencoded
body:
apiKey: "{{ apiKey }}"
ASSIGNED_POLICIES: '["XXXX"]'
RESOURCEID: "{{ resourceId }}"
RUNCOMPCHECK_STATUS: true
headers:
Content-Type: "application/x-www-form-urlencoded;charset=UTF-8"
but when I pass the value now as variable i don't get it in the correct form
---
- name: Post to API
hosts: KingKong
connection: local
gather_facts: no
vars:
policygroup:
- XXXX
# - YYYY
# - ZZZZ
tasks:
- uri:
url: "{{ AssociatePolicies_url }}"
method: POST
return_content: yes
validate_certs: no
body_format: form-urlencoded
body:
apiKey: "{{ apiKey }}"
ASSIGNED_POLICIES: "'["{{ item }}"]'"
RESOURCEID: "{{ resourceId }}"
RUNCOMPCHECK_STATUS: true
headers:
Content-Type: "application/x-www-form-urlencoded;charset=UTF-8"
with_items: "{{ policygroup }}"
Is the response: Error while parsing ASSIGNED_POLICIES json data
After various approaches I don't get any closer to the result:
ASSIGNED_POLICIES: "\'[{{ item }}]\'" is the format '[XXXX]
ASSIGNED_POLICIES: \'["{{ item }}"]\' is the format \\'[\"XXXX\"]\\'
ASSIGNED_POLICIES: "\'[\"{{ item }}\"]\'" is the format '[\"XXXX\"]'
ASSIGNED_POLICIES: "\'["{{ item }}"]\'" playbook error
ASSIGNED_POLICIES: "\'[{{ \" }}{{ item }}{{\"}}]\'" is the format '[ }}{{ item }}{{]'"}]
where I get almost closer to the format is:
ASSIGNED_POLICIES: "\'['{{ item }}']\'" is the format "'['XXXX']'"
but with single quote in front anb ack of XXXX but there must be double quote.
Maybe one of you has a creative idea

I have corrected my source code above and post below what I get back as a response.
What i see in see response:
"content": "{\"error\":{\"message\":\"Error while parsing ASSIGNED_POLICIES json data.\",\"errorcode\":\"JSON_PARSE_ERROR\"}}\n"
and the wrong format:
"ASSIGNED_POLICIES": "'[XXXX]'"
It is missing double quote in front and behind XXXX.
this must be the correct post
"ASSIGNED_POLICIES": "'["XXXX"]'"
.
{
"changed": false,
"_ansible_verbose_always": true,
"result_4": {
"msg": "All items completed",
"changed": false,
"results": [
{
"content_length": "104",
"status": 200,
"cookies": {
"opmcsrfcookie": "192d408c-be9b-42f7-985b-56360c06fdd7"
},
"set_cookie": "opmcsrfcookie=192d408c-be9b-42f7-985b-56360c06fdd7;path=/;Secure;priority=high",
"vary": "Accept-Encoding",
"elapsed": 0,
"msg": "OK (104 bytes)",
"content_type": "application/json;charset=UTF-8",
"date": "Wed, 16 Mar 2021 16:22:55 GMT",
"x_frame_options": "deny",
"ansible_loop_var": "item",
"x_xss_protection": "1",
"url": "https://https://AssociatePolicies_url",
"changed": false,
"x_content_type_options": "nosniff",
"connection": "close",
"content": "{\"error\":{\"message\":\"Error while parsing ASSIGNED_POLICIES json data.\",\"errorcode\":\"JSON_PARSE_ERROR\"}}\n",
"failed": false,
"json": {
"error": {
"errorcode": "JSON_PARSE_ERROR",
"message": "Error while parsing ASSIGNED_POLICIES json data."
}
},
"item": 301,
"invocation": {
"module_args": {
"directory_mode": null,
"force": false,
"remote_src": null,
"status_code": [
200
],
"follow": false,
"owner": null,
"body_format": "form-urlencoded",
"client_key": null,
"group": null,
"use_proxy": true,
"unix_socket": null,
"unsafe_writes": null,
"setype": null,
"content": null,
"serole": null,
"follow_redirects": "safe",
"return_content": true,
"client_cert": null,
"body": {
"RUNCOMPCHECK_STATUS": true,
"RESOURCEID": "abcde",
"apiKey": "just_a_Key",
"ASSIGNED_POLICIES": "'[XXXX]'"
},
"url_username": null,
"src": null,
"dest": null,
"selevel": null,
"force_basic_auth": false,
"removes": null,
"http_agent": "ansible-httpget",
"regexp": null,
"url_password": null,
"url": "https://AssociatePolicies_url",
"validate_certs": false,
"seuser": null,
"method": "POST",
"creates": null,
"headers": {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
"delimiter": null,
"mode": null,
"timeout": 30,
"attributes": null,
"backup": null
}
},
"redirected": false,
"cookies_string": "opmcsrfcookie=192d408c-be9b-42f7-985b-56360c06fdd7"
}
]
},
"_ansible_no_log": false
}

Related

how to filter e filter string from list in ansible

this is the list which i have filtered from a nested json using the below json_query
Please see the content of tmpdata
{
"content_length": "4883",
"status": 200,
"cookies": {},
"changed": false,
"strict_transport_security": "max-age=15768000",
"x_api_total_time": "0.234s",
"_ansible_item_result": true,
"_ansible_no_log": false,
"json": {
"job_tags": "",
"type": "job",
"scm_revision": "",
"status": "successful",
"credential": null,
"force_handlers": false,
"job_slice_number": 0,
"ask_credential_on_launch": false,
"started": "2021-02-24T06:48:29.884643Z",
"ask_job_type_on_launch": false,
"start_at_task": "",
"event_processing_finished": true,
"elapsed": 27.82,
"finished": "2021-02-24T06:48:57.704791Z",
"ask_variables_on_launch": true,
"ask_limit_on_launch": false,
"job_slice_count": 1,
"ask_skip_tags_on_launch": false,
"extra_vars": "{\"domain\": \"abc-cn-1\", \"mgmt_password\": \"admin123\", \"mgmt_server\": \"192.168.20.30\", \"fingerprint\": \"9125544D272B5AD28F3E9AB7BC8AA3F276E45064\", \"fwcmd\": \"fw sam -v -J src 192.68.10.10\", \"targets\": [\"abc-cn-c1\"]}",
"use_fact_cache": false,
"name": "test-Checkpoint",
"created": "2021-02-24T06:48:29.003796Z",
"url": "/api/v2/jobs/1198/",
"vault_credential": null,
"verbosity": 4,
"job_args": "[\"ansible-playbook\", \"-u\", \"root\", \"-vvvv\", \"-i\", \"/tmp/awx_1198_e4iie_fm/tmpz4bfietf\", \"-e\", \"#/tmp/awx_1198_e4iie_fm/env/extravars\", \"chkpoint.yml\"]",
"modified": "2021-02-24T06:48:29.720325Z",
"unified_job_template": 7,
"project": 6,
"limit": "",
"timeout": 0,
"host_status_counts": {
"ok": 1
},
"result_traceback": "",
"launch_type": "manual"
},
"server": "nginx/1.12.2",
"connection": "close",
"_ansible_parsed": true,
"allow": "GET, DELETE, HEAD, OPTIONS",
"redirected": false,
"cookies_string": "",
"_ansible_ignore_errors": null
}
i am using the below json_query to filter the output from the tempdata
- name: "search for traget fw"
set_fact:
job_status2: "{{ tmpdata | json_query('[json.status, json.extra_vars]') }}"
please see the output from the above facts, you can see dict inside the list and i want to filter only expected output mentioned below
current output:
ok: [localhost] => {
"msg": [
"successful",
"{\"domain\": \"abc-cn-1\", \"mgmt_password\": \"admxxxxxin123\", \"mgmt_server\": \"192.168.10.20\", \"fingerprint\": \"9125544D272B5AD28F3E9AB7BC8AA3F276E45064\", \"fwcmd\": \"fw sam -v -J src 192.68.10.10\", \"targets\": [\"abc-cn-c1\"]}"
]
}
expected output:
["successful", targets": ["abc-cn-c1"]]
please help me id if this is possible
There are (at least) two answers to your question if you want to continue to use json_query, and one that sidesteps that mess entirely. We'll start with the latter because it's less typing for me :-)
- set_fact:
job_status2: '{{ [ tmpdata.json.status, (tmpdata.json.extra_vars|from_json).targets] }}'
the second is a slight variation on that, in that someone needs to resolve that embedded JSON to a dict and (AFAIK) JMESPath has no such ability
- set_fact:
job_status2: "{{ newdata | json_query('[json.status, json.extra_vars.targets]') }}"
vars:
newdata: >-
{{ tmpdata
| combine({"json":{"extra_vars", tmpdata.json.extra_vars|from_json}}, recursive=True)
}}
I mention that one mostly for the case where you are doing other things with json_query and thus it would be advantageous to know how to coerce the structure to be friendlier for JMESPath
and finally, you can cheat and use the JMESPath literal notation to embed the already JSON-ified string right into the query
- set_fact:
job_status2: "{{ newdata | json_query('[json.status, `' + newdata.json.extra_vars + '`.targets]') }}"

Ansible Parse for value from REST API Response Header

I must be missing something obvious. I need to extract the value from one key in the response header of a GET API call.
I am trying to get the value of client_version but cant seem to pull that data out.
Anisble version: 2.4.2.0
playbook:
- name: Get test client version
uri:
url: "{{ current_client_version_url }}"
method: GET
header:
Content-Type: "application/json"
register: resp
- debug: msg={{ resp }}
Output:
{
"msg": {
"content_length": "180",
"status": 200,
"cookies": {},
"x_ratelimit_reset": "1",
"json": {
"defaultContainerAlias": "_default",
"exchangeContainerAlias": null,
"hasContainersEnabled": true,
"hasExchangeEnabled": false,
"hasTargetedOffers": false,
"autoDeleteItemReferences": false
},
"url": "https://some.url.goes.here.com/v1/subdir/metadata",
"changed": false,
"vary": "Accept-Encoding, User-Agent",
"x_envoy_upstream_service_time": "3",
"failed": false,
"connection": "close",
"content_type": "application/json;charset=utf-8",
"client_version": "1a2b3c4d5f",
"date": "Tue, 04 Aug 2020 22:34:34 GMT",
"redirected": false,
"x_ratelimit_remaining": "197",
"msg": "OK (180 bytes)"
},
"changed": false,
"_ansible_verbose_always": true,
"_ansible_no_log": false
}
I assumed it would be a regular Ansible output and have tried:
resp.msg.client_version
resp.msg['client_version']
resp.msg[client_version]
When I reference resp.msg in the debug statement, I just get:
"msg": "OK (180 bytes)"
which makes no sense to me...
Help is appreciated.
figured it out solution is resp.client_version. it made sense funny enough once I pasted here. there is another key msg.

CentOS/Ansible - How to fix an error "_ssl.c:602: The handshake operation timed out"

I am running an API login task for network device and sometimes I get this error: "_ssl.c:602: The handshake operation timed out". Sometimes it runs and sometimes it gives a handshake error. I recently added RADIUS authentication to network device when using SSH, but API still using local credentials. But would that cause the problem?
Module I am using is the basic URI module and the task looks following:
- name: Login to switch using API
uri:
url: "https://{{ ansible_host }}/rest/v4/login-sessions"
method: POST
headers:
Accept: "application/json"
Content-Type: "application/json"
body: {"userName": "{{ ansible_user }}", "password": "{{ ansible_password }}"}
body_format: json
validate_certs: no
status_code: 201
register: switch_session
Error I am getting looks following:
fatal: [test_switch]: FAILED! => {
"changed": false,
"content": "",
"elapsed": 30,
"invocation": {
"module_args": {
"attributes": null,
"backup": null,
"body": {
"password": "<PASSWORD>",
"userName": "<USERNAME>"
},
"body_format": "json",
"client_cert": null,
"client_key": null,
"content": null,
"creates": null,
"delimiter": null,
"dest": null,
"directory_mode": null,
"follow": false,
"follow_redirects": "safe",
"force": false,
"force_basic_auth": false,
"group": null,
"headers": {
"Accept": "application/json",
"Content-Type": "application/json"
},
"http_agent": "ansible-httpget",
"method": "POST",
"mode": null,
"owner": null,
"regexp": null,
"remote_src": null,
"removes": null,
"return_content": false,
"selevel": null,
"serole": null,
"setype": null,
"seuser": null,
"src": null,
"status_code": [
"201"
],
"timeout": 30,
"unix_socket": null,
"unsafe_writes": null,
"url": "https://<IP_ADDR>/rest/v4/login-sessions",
"url_password": null,
"url_username": null,
"use_proxy": true,
"validate_certs": false
}
},
"msg": "Status code was -1 and not [201]: Request failed: <urlopen error ('_ssl.c:602: The handshake operation timed out',)>",
"redirected": false,
"status": -1,
"url": "https://<IP_ADDR>/rest/v4/login-sessions"

send multiline form with ansible uri module

I'm trying to upload a multi-line file to a appdynamics controller, using the ansible uri module. Any advice?
As you'll notice in the snippets, I'm brand new to Ansible...
It works fine with shell: curl, but I can't seem to get the output correct for a more structured play.
Works
- name: import health rule xml via curl
shell: "curl -i -X POST {{ APPD_HEALTH_RULE_URL }}/{{ APPD_APPLICATIAON_ID }}?overwrite={{ OVERWRITE_EXISTING_RULE }} -H {{ APPD_AUTH_TOKEN }} -F file=#{{ WORKSPACE }}/infrastructure_health_rule_template.xml"
register: health_rule
Doesn't work
- name: import health rule to application
uri:
url: "{{ APPD_HEALTH_RULE_URL }}/{{ APPD_APPLICATIAON_ID }}?overwrite={{ OVERWRITE_EXISTING_RULE }}"
method: POST
headers:
Authorization : "{{ APPD_TOKEN }}"
Content-Type : "multipart/form-data"
return_content : yes
follow_redirects : all
body_format : raw
body : msg="{{lookup('file', '{{ WORKSPACE }}/infrastructure_health_rule_template.xml') }}"
status_code:
- 100
- 200
- 201
- 202
- 300
- 301
- 302
- 307
register: health_rule
Expected outcome - I'm able to successfully import the health rule to AppD
Actual - I get a 200 response, and nothing happens.
Response:
ok: [localhost] => {
"age": "0",
"changed": false,
"connection": "close",
"content": "the request was rejected because no multipart boundary was found \n",
"cookies": {
"JSESSIONID": "NUMBERS & STUFF"
},
"cookies_string": "JSESSIONID=NUMBERS & STUFF",
"date": "Wed, 25 Sep 2019 20:25:07 GMT",
"elapsed": 0,
"invocation": {
"module_args": {
"attributes": null,
"backup": null,
"body": "<health-rules controller-version=\"VERSION HERE\">\n <health-rule>\n <name>Disk_Space_too_low</name>\n <type>INFRASTRUCTURE</type>\n <description/>\n <enabled>True</enabled>\n <is-default>false</is-default>\n <always-enabled>true</always-enabled>\n <duration-min>35</duration-min>\n <wait-time-min>35</wait-time-min>\n <affected-entities-match-criteria>\n <affected-infra-match-criteria>\n <type>NODES</type>\n <node-match-criteria>\n <type>CUSTOM</type>\n <match-type>STARTSWITH</match-type>\n <match-pattern>i-</match-pattern>\n <inverse>True</inverse>\n <node-meta-info-match-criteria/>\n <vm-sys-properties/>\n <env-properties/>\n </node-match-criteria>\n </affected-infra-match-criteria>\n </affected-entities-match-criteria>\n <critical-execution-criteria>\n <entity-aggregation-scope>\n <type>ANY</type>\n <value>0</value>\n </entity-aggregation-scope>\n <policy-condition>\n <type>leaf</type>\n <display-name>Hardware Resources|Volumes|Used %</display-name>\n <condition-value-type>ABSOLUTE</condition-value-type>\n <condition-value>90.0</condition-value>\n <operator>GREATER_THAN</operator>\n <condition-expression/>\n <use-active-baseline>False</use-active-baseline>\n <trigger-on-no-data>False</trigger-on-no-data>\n <metric-expression>\n <type>leaf</type>\n <function-type>VALUE</function-type>\n <value>0</value>\n <is-literal-expression>False</is-literal-expression>\n <display-name></display-name>\n <metric-definition>\n <type>LOGICAL_METRIC</type>\n <logical-metric-name>Hardware Resources|Volumes|Used (%)</logical-metric-name>\n </metric-definition>\n </metric-expression>\n </policy-condition>\n </critical-execution-criteria>\n <warning-execution-criteria>\n <entity-aggregation-scope>\n <type>ANY</type>\n <value>0</value>\n </entity-aggregation-scope>\n <policy-condition>\n <type>leaf</type>\n <display-name>Hardware Resources|Volumes|Used %</display-name>\n <condition-value-type>ABSOLUTE</condition-value-type>\n <condition-value>80.0</condition-value>\n <operator>GREATER_THAN</operator>\n <condition-expression/>\n <use-active-baseline>False</use-active-baseline>\n <trigger-on-no-data>False</trigger-on-no-data>\n <metric-expression>\n <type>leaf</type>\n <function-type>VALUE</function-type>\n <value>0</value>\n <is-literal-expression>False</is-literal-expression>\n <display-name></display-name>\n <metric-definition>\n <type>LOGICAL_METRIC</type>\n <logical-metric-name>Hardware Resources|Volumes|Used (%)</logical-metric-name>\n </metric-definition>\n </metric-expression>\n </policy-condition>\n </warning-execution-criteria>\n</health-rule>\n</health-rules>",
"body_format": "raw",
"client_cert": null,
"client_key": null,
"content": null,
"creates": null,
"delimiter": null,
"dest": null,
"directory_mode": null,
"follow": false,
"follow_redirects": "all",
"force": false,
"force_basic_auth": false,
"group": null,
"headers": {
"Authorization": "Bearer REALLY LONG STRING OF CHARACTERS",
"Content-Type": "multipart/form-data"
},
"http_agent": "ansible-httpget",
"method": "POST",
"mode": null,
"owner": null,
"regexp": null,
"remote_src": null,
"removes": null,
"return_content": true,
"selevel": null,
"serole": null,
"setype": null,
"seuser": null,
"src": null,
"status_code": [
100,
200,
201,
202,
300,
301,
302,
307
],
"timeout": 30,
"unix_socket": null,
"unsafe_writes": null,
"url": "####### URL #######",
"url_password": null,
"url_username": null,
"use_proxy": true,
"validate_certs": true
}
},
"msg": "OK (unknown bytes)",
"redirected": false,
"server": "AppDynamics",
"set_cookie": "JSESSIONID=NUMBERS & STUFF; Path=/controller; HttpOnly;Secure",
"status": 200,
"transfer_encoding": "chunked",
"url": "####### URL #######,
"via": "1.1 varnish",
"x_content_type_options": "Nosniff",
"x_frame_options": "SAMEORIGIN",
"x_varnish": "1299636501",
"x_xss_protection": "1; mode=block"
}
META: ran handlers
META: ran handlers
PLAY RECAP ***************************************************************************************************************
localhost : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Not sure if it is still needed. With ansible v2.10 this is possible. What you need is this:
- name: import health rule to application
uri:
url: "{{ APPD_HEALTH_RULE_URL }}/{{ APPD_APPLICATIAON_ID }}?overwrite={{ OVERWRITE_EXISTING_RULE }}"
method: POST
headers:
Authorization : "{{ APPD_TOKEN }}"
Content-Type : "multipart/form-data"
return_content : yes
follow_redirects : all
body_format : form-multipart
body :
file : "{{lookup('file', '{{ WORKSPACE }}/infrastructure_health_rule_template.xml') }}"
filename : infrastructure_health_rule_template.xml
mime_type : application/xml
status_code:
- 100
- 200
- 201
- 202
- 300
- 301
- 302
- 307
register: health_rule
Notice the body_format: form-multipart and the body structure. Check documentation examples. More specific the example: Upload a file via multipart/form-multipart

Ansible Symbolic Link Task Role Failure

I am new to ansible and executing the following ansible task:
- name: Create symbolic links
file:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ jboss_usr }}"
group: "{{ jboss_grp }}"
state: link
with_items:
- { src: "/apps/etc/jboss", dest: "/etc/jboss" }
- { src: "/apps/var/log/jboss", dest: "/var/log/jboss" }
And I got the following error:
2018-12-21 21:27:23,469 p=15185 u=ex_sam | failed: [hostname.x] (item={u'dest': u'/etc/jboss', u'src': u'/apps/etc/jboss'}) => {
"changed": false,
"invocation": {
"module_args": {
"attributes": null,
"backup": null,
"content": null,
"delimiter": null,
"dest": "/etc/jboss",
"diff_peek": null,
"directory_mode": null,
"follow": true,
"force": true,
"group": "jboss",
"mode": null,
"original_basename": null,
"owner": "jboss",
"path": "/etc/jboss",
"recurse": false,
"regexp": null,
"remote_src": null,
"selevel": null,
"serole": null,
"setype": null,
"seuser": null,
"src": "/apps/etc/jboss",
"state": "link",
"unsafe_writes": null,
"validate": null
}
},
"item": {
"dest": "/etc/jboss-as",
"src": "/apps/etc/jboss"
},
"msg": "Error while linking: [Errno 13] Permission denied",
"path": "/etc/jboss-as",
"state": "absent"
}
I am trying to find out why the symbolic link creation failed.
I read the following:
https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#id6
I says the "changed" attribute is a boolean indicating if the task had to make changes.
But, there are lots of null parameters in the invocation:module_args elements of the json
Does that mean the values are really “null” or they are being set to a default value?
I have looked into the ansible documentation and I am not sure if the invocation:module_args null values are representative of the outcome of the trying to create the symbolic link i.e. are the null input or output of executing the tasks.
I think some of the nulls are defaults, but will appreciate some helpful comments on the possible relation between the json returned in my ansible error log and the actual "Error while linking: [Errno 13] Permission denied".
Thanks all for you anticipated help.
I think, is the permissions on /etc. So probably you need to add the option:
become: true
To your task.

Resources