What is the purpose of ">" in "shell: >" within an Ansible task? - ansible

What function does the ">" character serve, in a simple Ansible task that executes a shell command? For the life of me I can't find documentation or mention of this! Here is the template for the task:
- name: <task_name>
shell: >
<command>
Thank you.

The > is a mark for yaml. It means that the following lines will be compressed into a single string with leading indentation compressed to a single space. There are some technical details regarding leading indentation that will modify how the final string is generated, but to the yaml parser the following are equivalent:
- name: task_name
shell: >
this is some
arbitrary string which may
be a shell command
- name: task2_name
shell: this is some arbitrary string which may be a shell command

Related

Ansible 2.9 - Escape a single "\" backslash being passed into win_command from variable

vars:
- windowsLogonAccount: NT AUTHORITY\SYSTEM
tasks:
- name: Install Agent via CMD
win_command: "config.cmd --windowsLogonAccount '{{ windowsLogonAccount }}'"
args:
chdir: "c:/agent"
I'm attempting to get just a single backslash to pass via Ansible to Windows. I've tried double backslashes "\\" and I've tried {{ var | safe }}, but without luck. I'm hoping somebody in the community can point me in the right direction. I can't believe it is as complicated as some of the other examples I've seen using replace and regex...
Everything I try I keep getting a double backslash:
2021-10-19T04:45:52.8643709Z TASK [Get Variable Output to Screen] *******************************************
2021-10-19T04:45:52.9042957Z "msg": "My Variable Test Area 'NT AUTHORITY\\SYSTEM'"
I came here having not the exact same problem, but a similar one (passing an escaped backslash (\\) to the command), and my solution might also help here. When inserting variables into the command for command or win_command, it is always good to pipe the variable to the quote filter to preserve the content of the variable as is. In your case:
win_command: "config.cmd --windowsLogonAccount {{ windowsLogonAccount | quote }}"
----Resolved----
So this is a unique thing with Ansible Outputs to Terminal. They write output in valid JSON and thus "auto" escape special characters like backslashes in the output. But the actual value passed during run-time does not contain both back slashes. I'm posting this in case any other Ansible noobs run into this surprise.
Example output to screen:
2021-10-19T04:46:11.6003956Z: [COMPUTERNAME]: CHANGED! => {"changed": true, "cmd": "config.cmd --unattended --windowsLogonAccount 'NT AUTHORITY\SYSTEM'
Actual output to host:
config.cmd --unattended --windowsLogonAccount 'NT AUTHORITY\SYSTEM'

Expand complex ansible variable

I have distinct ansible variables which are combined in a single command. More precisely, the system defines a variable with default value:
# This exists in an ansible variable definition file
instrumentor = ''
At some the python script that "creates" the ansible commands specifies the extra arguments to override the default values. I'm jumping through some hoops (using \" and \') because the desired value contain spaces:
# This is a line from python script
instrumentation_specs =
'-e \'instrumentor=\"/software/cuda-memcheck --tool racecheck --log-file /tmp/memlog\"\''
On the ansible side then the command is structured as
;; This exists in a jinja template (.j2 extension)
;; command is what the start.yml script will be running
command="{{ instrumentor }}" my_program
Unfortunately I cannot get this to work. The command is reported to expand to something that contains extra ' and ":
start.yml (...) -e 'instrumentor="/software/cuda-memcheck --tool racecheck --log-file /tmp/memlog"' (...)
The weird thing is that
if I create another variable before command that only contains instrumentor, it is reported to have the exact value that I need
instr_tmp = "{{ instrumentor }}"
command = "{{ instr_tmp }}" my_program
i.e. the extra ' and " don't appear in instr_tmp but do appear in command
If I ommit the \" and \' on the python side (when creating the string that is used to provide the extra arguments) everything that's after a space gets omitted.
Anyone knows how to specify such a variable override, i.e. how the string should look like when I specify a variable that contains multiple space separated strings (instrumentor), but that variable is supposed to be plugged into another ansible variable (command).

How to use escape characters in Ansible shell/grep command

I need to extract a hostname from a URL in a file on my remote host to then use that value in another task.
I have the following task in my playbook:
- name: Extract server name
shell: "grep ^serverURL=https:\/\/(.*)\/XMLRPC <filename>"
register: <variable>
But when I try and run it I get the following error (cut down to relevant bits):
Found unknown escape character. The offending line appears to be:
- name: Extract server name
shell: "grep ^serverURL=https:\/\/(.*)\/XMLRPC <filename>"
^ here
It seems 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.
Obviously it does start and finish with double quotes but the carat is at the escape character in my grep query, so it seems reasonable to think that this is the cause of the problem; if I remove the backslashes my grep query doesn't return anything.
How can I escape this correctly please?

Multiline Template - string escaping in Ansible

I'm trying to get an effect similar to this article: https://gryzli.info/2017/12/21/ansible-debug-print-variables/
Which means in my case:
- name: Gather facts
vars:
msg: |
"{{ansible_distribution}}"
"{{ansible_distribution_major_version}}"
"{{ansible_distribution_release}}"
"{{ansible_distribution_version}}"
The problem ist that without quotes it throws an error to add the quotes. With quotes it throws the same error:
We could be wrong, but this one looks like it might be an issue with missing quotes. Always quote template expression brackets when theystart a value....
How do I correctly escape this multiline string so that Ansible can parse it? Or does this kind of code no longer work?
Q: "How do I correctly escape this multiline string so that Ansible can parse it?"
A: The problem is the indentation of the block. Quoting from Example 8.3. Invalid Block Scalar Indentation Indicators
ERROR:
A leading all-space line must not have too many spaces.
A following text line must not be less indented.
The text is less indented than the indicated level.
The correct syntax is (with or without quotation)
vars:
msg: |
"{{ansible_distribution}}"
"{{ansible_distribution_major_version}}"
"{{ansible_distribution_release}}"
"{{ansible_distribution_version}}"

Unable to print string containing double quotes in GitLab CI YAML

I'm using the CI Lint tester to try and figure out how to store an expected JSON result, which I later compare to a curl response. Neither of these work:
Attempt 1
---
image: ruby:2.1
script:
- EXPECT_SERVER_OUTPUT='{"message": "Hello World"}'
Fails with:
did not find expected key while parsing a block mapping at line 4 column 5
Attempt 2
---
image: ruby:2.1
script:
- EXPECT_SERVER_OUTPUT="{\"message\": \"Hello World\"}"
Fails with:
jobs:script config should be a hash
I've tried using various combinations of echo as well, without a working solution.
You could use literal block scalar1 style notation and put the variable definition and subsequent script lines on separate lines2 without worrying about quoting:
myjob:
script:
- |
EXPECT_SERVER_OUTPUT='{"message": "Hello World"}'
or you can escape the nested double quotes:
myjob:
script:
- "EXPECT_SERVER_OUTPUT='{\"message\": \"Hello World\"}'"
but you may also want to just use variables like:
myjob:
variables:
EXPECT_SERVER_OUTPUT: '{"message": "Hello World"}'
script:
- dothething.sh
Note: variables are by default expanded inside variable definitions so take care with any $ characters inside the variable value (they must be written as $$ to be literal). This feature can also be turned off.
1See this answer for an explanation of this and related notation
2See this section of the GitLab docs for more info on multi-line commands
I made it work like this:
script: |
"EXPECT_SERVER_OUTPUT='{\"message\": \"Hello World\"}'"
echo $EXPECT_SERVER_OUTPUT

Resources