Got an error message Syntax Error in ansible-playbook [duplicate] - ansible

This question already has answers here:
Quotes in ansible lineinfile
(4 answers)
Closed 4 years ago.
ERROR! Syntax Error while loading YAML.
did not find expected key
The error appears to have been in '/etc/ansible/main.yml': line 73, column 50, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Ensure IP forwarding is disabled
shell: "sysctl net.ipv4.ip_forward ; grep "net\.ipv4\.ip_forward" /etc/sysctl.conf /etc/sysctl.d/*"
^ here
We could be wrong, but this one looks like it might be an issue with
unbalanced quotes. If starting a value with a quote, make sure the
line ends with the same set of quotes. For instance this arbitrary
example:
I using grep with "" into shell module in ansible playbook and got an ERROR message as follow "ERROR! Syntax Error while loading YAML."
- name: Ensure IP forwarding is disabled
shell: "sysctl net.ipv4.ip_forward ; grep "net\.ipv4\.ip_forward" /etc/sysctl.conf /etc/sysctl.d/*"
register: CIS_3.1.1
ignore_errors: True

That configuration file for ansible is in the YAML format and in YAML a scalar that represents a string can be in multiple formats:
plain: no quotes, has restrictions on the start character and internal character sequences, no escapes
single quoted: can contain double quotes, no escapes except for repeating single quotes
double quoted: backslash escapes in string, in string double quotes need to be escaped
literal: newlines are preserved, no escapes
folded: newlines are converted to spaces, no escapes
You are using double quoted style, and in that you would need to escape the internal double quotes (") and backslashes (\). That gets ugly and unreadble real soon. It is much more useful to use literal style in such cases:
- name: Ensure IP forwarding is disabled
shell: |-
sysctl net.ipv4.ip_forward ; grep "net\.ipv4\.ip_forward" /etc/sysctl.conf /etc/sysctl.d/*
I.e. you put |- (the minus is to strip the final newline of the following line), then put the line without starting or end quotes, indented, on the next line.

Related

replacing the special characters in a string in Ansible or Appending \ to special characters in the given string in Ansible

In my ansible playbook, I need to get a string an input from the user which may have special characters such as double quotes ("), paranthesis. I would like to add \ (slash) before every such special character.
For Example,
"(msg.commandCode=303 or msg.commandCode=302 or msg.commandCode=301) and msg.dest-host avpExists"
is to be changed to
\"\(msg.commandCode=303 or msg.commandCode=302 or msg.commandCode=301\) and msg.dest-host avpExists\"
Can someone help me on this ?
The |regex_replace filter is designed for that purpose
- debug:
msg: the new string is {{ the_string | regex_replace(re1, re2) }}
vars:
the_string: '"(msg.commandCode=303 or msg.commandCode=302 or msg.commandCode=301) and msg.dest-host avpExists"'
re1: '(["()])'
re2: '\\\1'
where \\ is the literal backslash character, and \1 is the reference to the first capture group (of which there is only one)
I find using vars: and single quoted strings easier than fighting with yaml and backslashes, but it would work fine inlined into the jinja2 pipeline, also, if you manage to find the correct amount of additional backslashes to use

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?

Quotes in makefile

this is my first post here (maybe more later ^^)
So, here we are :
I'm using Gitlab-CI, docker, makefile, firebase.
So in my Makefile :
firebase-deploy: ## Deploy the application
$(FIREBASE) deploy -m "$(comment)"
in my CI :
variables:
DOCKER_DRIVER: overlay2
MESSAGE: $CI_COMMIT_MESSAGE
deploy-firebase:
stage: deploy
script:
- make install
- make deploy comment="$MESSAGE"
The problem is actually, i have
docker-compose exec -T js node_modules/firebase-tools/lib/bin/firebase.js deploy -m "test ci ?
/bin/sh: syntax error: unterminated quoted string
So, as you can see, the double quote at the end is ... not here.
I tested a few things
\"Comment\"
\'Comment\'
"Comment\"
And more, but none of them work.
One thing interesting is that if i commit FROM gitlab.com it work as expected, but from my computer on push : nop.
Do you have any advice, or something to look for ?
Thanks!
If your commit message contains end of lines you cannot pass it to your script as it is. Try, maybe, to substitute end of lines by another character, e.g. -. Of course the way to do it depends on the shell that executes your CI scripts. If it is bash, for instance, the following should work:
make deploy comment="${MESSAGE//$'\n'/-}"
If you must also escape other characters you can chain substitutions. Example if you want to substitute end of lines and double quotes by - and ':
c="${MESSAGE//$'\n'/-}"; c="${c//\"/\'}"; make deploy comment="$c"
To learn more about these bash substitutions just type man bash and read section EXPANSION, sub-section Parameter Expansion. The parameter expansion I used is:
${parameter/pattern/string}
that replaces pattern by string in the value of variable parameter (in bash parlance parameter is another name for variable). When the pattern begins with a / all matches of pattern are replaced with string, else only the first match is replaced. So the first parameter expansion:
c="${MESSAGE//$'\n'/-}"
substitutes all end-of-line characters in the value of variable MESSAGE by - (more on $'\n' later) and assigns the result to variable c. Note the enclosing double quotes, they are needed because you can have spaces in the message. And the second:
c="${c//\"/\'}"
substitutes all " in the value of variable c by ' and assigns again the result to variable c.
In this case the most complicated is to put a end-of-line character in the first pattern, a double quote in the second and a single quotes in the second string. The $'string' construct is explained in the QUOTING section of the bash manual:
Words of the form $'string' are treated specially. The word expands to
string, with backslash-escaped characters replaced as specified by the
ANSI C standard.
So $'\n' is replaced by the end-of-line character. In the second pattern and string you just need to escape the double and single quotes with a backslash to have them interpreted literally.
Finally the 3 commands of this little shell script are chained by ;, the bash sequence operator. They are executed one after the other in the same bash invocation.

YAML syntax sed in Gitlab-CI

I've made a mistake in the file below, but I cannot see where my mistake is. I have this command in my .gitlab-ci.yml configuration file.
- sed "s/use_scm_version=True/use_scm_version={'write_to': '..\/version.txt', 'root': '..'},\/"setup.py
It seems that the ":" are interpreted as a semicolon even if I surround the entire sed between double quotes.
(<unknown>): did not find expected key while parsing a block mapping at line 109 column 11
Any ideas ?
Since your double quotes are not at the beginning of the scalar node, they don't have special meaning in YAML and the colon is seen as the normal value indicator (and both the key and value have an embedded double quote).
I recommend you quote the whole scalar:
- "sed s/use_scm_version=True/use_scm_version={'write_to': '..\/version.txt', 'root': '..'},\/setup.py"
And optionally add \" (backslash escaped double quotes) as necessary within there if that doesn't work.

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}}"

Resources