Reputation: 1741
I'm trying to get the value of a variable in a file into an Ansible variable so I can use it.
Here's what I've got:
- name: extract Unique Key
shell: "grep UNIQUE_KEY ../config.py | cut -d' ' -f 3"
register: command_output
- set_fact:
unique_key: x{{ command_output.stdout | regex_replace("^'", '') | regex_replace('^"', '') | regex_replace("'$", '') | regex_replace('"$', '') }}
- set_fact:
unique_key: "{{ unique_key | regex_replace('^x', '') }}"
- debug: var=unique_key
This works, but feels kludgy and looks ugly.
I've already tried to add sed to my original shell module, but I couldn't figure out how to get the quotes escaped correctly. I also couldn't figure out how to escape the regex_replace to get it to work in a single variable assignment.
Is there a simpler way to go from this:
"TEST"
or
'TEST'
to this:
TEST
in Ansible? (I'm also really new to Ansible so that's not helping either)
EDIT: After the answer by @Vladimir-Botka which I initially accepted, I found this issue:
If I don't strip the quotes and embed the variable in another variable, it keeps the quotes:
I need to use this value to construct a path:
vars:
service_location: "/opt/{{ unique_key }}-scheduler-service"
If I don't remove the quotes using my method above, The variable will contain the quotes as in this output of a debug statement:
ok: [fedorasvr1] => {
"service_location": "/opt/'TEST'-scheduler-service"
}
Upvotes: 8
Views: 26098
Reputation: 11435
I believe this may be the simplest way to strip double quotes:
{{ ""My oddly quoted string" | from_json }}
I had an issue upgrading ansible where the json value was no longer being returned (Because my uri module wasn't actually returning json) so I couldn't trick ansible into populating something in the json response and I had to go back to using content.
Because these were passwords and we didn't notice this for a week this led to much sadness and explanations of "just add quotes around your password when you type it next time"
We were going to implement the other solutions here to remove quotes using regex, but I thought, lets just do what ansible was going to do in the first place and see if that works, and it did - very well.
note, this will only work for double quotes. But if you use single quotes to quote a string, you're probably going to have a purist/linter fix your code so you might as well be proactive
Upvotes: 0
Reputation: 692
Slightly different, but maybe related: I was getting unwanted quotes when using a lookup to initialize a variable which were then used in a "blockinfile" task. But it turns out the quotes were caused by the "blockinfile" and not the lookup, ie:
- name: set some variables
set_fact:
my_var: "{{ lookup('ini', 'my_var section=variables file=~/myconf.ini') }}"
- name: update myconf.cfg
blockinfile:
dest: myconf.cfg
state: present
create: true
owner: "{{user}}"
group: "{{user}}"
block: |
[Credentials]
access_key_id = blabla
secret_access_key = "{{my_var}}"
become: true
removing the quotes from this line worked:
secret_access_key = "{{my_var}}"
Upvotes: 1
Reputation: 68034
The short answer is "omit the first and the last character" if the quotes are part of the string
- set_fact:
unique_key: command_output.stdout[1:-1]
Internal interpretation is all the same. The quotes control the expansion of the variables. See 7.3.1. Double-Quoted Style and 7.3.2. Single-Quoted Style.
As an example. The play below
- hosts: localhost
vars:
var1: TEST
var2: 'TEST'
var3: "TEST"
tasks:
- template:
src: test.j2
dest: test
and the template
shell> cat test.j2
{{ var1 }}
{{ var2 }}
{{ var3 }}
give
shell> cat test
TEST
TEST
TEST
The quotes, if part of the string, can be removed. As an example the play below
- hosts: localhost
vars:
regex: "[`'\"]"
replace: ""
service_location: "/opt/{{ item|regex_replace(regex, replace)
}}-scheduler-service"
tasks:
- debug:
var: service_location
loop:
- '`TEST`'
- '"TEST"'
- '''TEST'''
- "'TEST'"
gives
ok: [localhost] => (item=`TEST`) =>
item: '`TEST`'
service_location: /opt/TEST-scheduler-service
ok: [localhost] => (item="TEST") =>
item: '"TEST"'
service_location: /opt/TEST-scheduler-service
ok: [localhost] => (item='TEST') =>
item: '''TEST'''
service_location: /opt/TEST-scheduler-service
ok: [localhost] => (item='TEST') =>
item: '''TEST'''
service_location: /opt/TEST-scheduler-service
It is also possible to use custom filter_plugins/string_filters.py which might be more convenient than complex escape constructs.
As an example. The play below
- hosts: localhost
vars:
replace: ""
service_location: "/opt/{{ item.0|string_replace(item.1, replace)
}}-scheduler-service"
tasks:
- debug:
var: service_location
with_together:
- - '`TEST`'
- '"TEST"'
- "'TEST'"
- - '`'
- '"'
- "'"
gives
ok: [localhost] => (item=[u'`TEST`', u'`']) =>
item:
- '`TEST`'
- '`'
service_location: /opt/TEST-scheduler-service
ok: [localhost] => (item=[u'"TEST"', u'"']) =>
item:
- '"TEST"'
- '"'
service_location: /opt/TEST-scheduler-service
ok: [localhost] => (item=[u"'TEST'", u"'"]) =>
item:
- '''TEST'''
- ''''
service_location: /opt/TEST-scheduler-service
FWIW, see other examples of filter_plugins.
Upvotes: 8