I am trying using the following Ansible play to change the default weak password for a number of SQL scripts:
- name: amend SQL User Passwords
sudo: yes
lineinfile: dest=/path/to/script/{{ item.file }} state=present backup=yes
regexp="CREATE USER (.*) PASSWORD 'password';$" line='CREATE USER \1 PASSWORD ''strongpassword'';' backrefs=yes
with_items:
- { file: create_db1_users_tables.sql }
- { file: create_db2_users_tables.sql }
- ...
- { file: create_dbNN_users_tables.sql }
Though the YAML specification suggests that it should,
Inside single quotes, you can represent a single quote in your string by using two single quotes next to each other.
the double single-quote are not acting as an escape character; instead they are being completely removed from the output line:
CREATE USER user1 PASSWORD stR0ngP#55w0rD
instead of
CREATE USER user1 PASSWORD 'stR0ngP#55w0rD'
So far I have tried:
Using double quotes - this allows the single quote around the password, however the backref is no-longer parsed, and just prints out as \1. Attempting to escape this as \\1 appears to have no affect.
Various different ways of escaping the single quote - backslashes, ticks. Most produce syntax errors or just output nothing.
Surrounding all the lineinfile arguments in double quotes (and suitably escaping everything within)
I can't use the Ansible database modules
I can't use templates, the scripts create and populate a number of tables, and can change between versions of the product - keeping templates up to date would be too much overhead.
I've found a similar Ansible question, Quotes in ansible lineinfile, but the solutions did not help.
Does anyone have any further suggestions?
Not that I enjoy answering my own posts but having trawlled more of the internet I came across this post, where the suggestion was made to use the replace module instead of the lineinfile**. The play:
- name: amend SQL User Passwords
sudo: yes
replace: dest=/path/to/script/{{ item.file }}
backup=yes
regexp="^CREATE USER (.*) PASSWORD 'password';$"
replace="CREATE USER \\1 PASSWORD 'strongpassword';"
with_items:
- { file: create_db1_users_tables.sql }
- { file: create_db2_users_tables.sql }
- ...
- { file: create_dbNN_users_tables.sql }
Works as expected, generating the desired SQL.
** This also re-enforces the fact that I should spend more time reading the Ansible manuals.
Related
In one of my deployment files, I want to set an environment variable. The variable is KUBE_VERSION and values must be fetched from a ConfigMap.
kube_1_21: 1.21.10_1550
This is part of ConfigMap where I want to set 1.21.10_1550 to KUBE_VERSION, but if the cluster is of IKS 1.20, then the key will be:
kube_1_20: 1.20.21_3456
kube_ is always static. How can I set environment variable using a regex expression?
Something of this sort:
- name: KUBE_VERSION
valueFrom:
configMapKeyRef:
name: cluster-info
key: "kube_1*"
As far as I know it is unfortunately not possible to use the regular expression as you would like. Additionally, you have information about the regular expression that validates the entered data:
regex used for validation is '[-._a-zA-Z0-9]+')
It follows that you have to enter key as an alphanumeric string and additionally you can use the characters -, _ and . So it is not possible to use regex in this place.
To workaround you can write your custom script i.e. in Bash and replace the proper line with sed command.
I am using Ansible version 2.9. I want to do a GET, which returns a block of info, regex an ID from that info that corresponds to whatever host I am iterating through at the moment, and then later do things with that ID.
I have the regex working ( https://regex101.com/r/UL7V6r/2 ). And I confirmed this regex does work in the playbook when I input it exactly like in the sample. But, I need the host name at the end of that regex to be a variable matching the host I am iterating through, not a static host name. Here is the playbook, focused on just getting the regex to work:
gather_facts: no
vars:
the_name: "{{ inventory_hostname_short }}"
tasks:
- uri:
url: http://controller-sample-a1p.someplace.com/restapi/nodes
method: GET
return_content: yes
register: nodeId
delegate_to: 127.0.0.1
- debug: msg="{{ nodeId.content | regex_findall("(\w+-\w+-\w+-\w+-\w+)..<address>\d+\.\d+\.\d+\.\d+:?\d+?<\/address><name>{{ the_name }}") }}"
delegate_to: 127.0.0.1
- debug:
var: the_name
The focus is on the end of that regex, with the variable of "the_name". As you can see I am trying curly brackets here. I've tried lots of variations insulting no brackets, single quotes, double quotes, etc.
The results of this play is:
ok: [sampleFQDN2.place.com -> 127.0.0.1] => {
"msg": []
}
TASK [debug] *************************************************************************************************************************
ok: [sampleFQDN2.place.com] => {
"the_name": "sampleFQDN2"
}
Expected result would be for debug msg one to show "FJLEEJ24-3190-49F1-965D-823F63904136" (per the link).
So this suggests to me that the variable is correct (second debug). And the regex is correct because if I take the variable output of "sampleFQDN2" and plug it in directly, that first debug spits out the right response. Which leads me to believe I just have not found the right syntax to stick a variable in a regex_findall.
Does anyone know the syntax for this? Or even if it is possible?
You never nest Jinja {{...}} template markers. Within a Jinja template, if you want to combine a literal string and a variable, you can use the ~ string concatenation operator, like this:
- debug: msg="{{ nodeId.content | regex_findall("(\w+-\w+-\w+-\w+-\w+)..<address>\d+\.\d+\.\d+\.\d+:?\d+?<\/address><name>" ~ the_name) }}"
The ~ operator is like +, except it will convert arguments into
strings so that you can concatenate numeric values to a string
(writing "this " + 1 would fail, but "this " ~ 1 would work).
Or you can use Python string formatting syntax, like this:
- debug: msg="{{ nodeId.content | regex_findall("(\w+-\w+-\w+-\w+-\w+)..<address>\d+\.\d+\.\d+\.\d+:?\d+?<\/address><name>%s" % (the_name)) }}"
This syntax uses printf-style formatting tokens (%s for strings,
%d for integers, etc). Or like this:
- debug: msg="{{ nodeId.content | regex_findall("(\w+-\w+-\w+-\w+-\w+)..<address>\d+\.\d+\.\d+\.\d+:?\d+?<\/address><name>{}".format(the_name)) }}"
Here is one site that documents Python
string formatting in some detail.
When I start the server, I get this error:
I18n::InvalidLocaleData
can not load translations from /Users/Apple/myapp-website-freelance/config/locales/fr.yml: #<Psych::SyntaxError: (/Users/Apple/myapp-website-freelance/config/locales/fr.yml): did not find expected key while parsing a block mapping at line 2 column 3>
Although, the yaml file seems normal at line 2 column 3:
fr:
Electronics_Circuits_Simulator_Realistic_Interface: "Simulateur de circuits electroniques. Interface reelle."
Any idea?
This error is often misleading and points the wrong line out
Look for extra spaces in the entire YML file and try to replace all enclosing single quotes by "", it should work !
One possible reason is:
default: &default
a: 1
production: *default
b: 2
in place of:
default: &default
a: 1
production:
<<: *default
b: 2
and if you are working with many projects make sure your on the sites section the hyphens - are in line look at the pic below where i have the green line.
Check for any extra whitespace in your YML file. Also, if you were like me you might forgot to remove {} in YML template.
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
I had a comma at the end of a line from a bad copy/paste elsewhere. Removing the comma restored the YAML file back to normal use (my application.yml in this case). The error is apparently covering a wide variety of YAML syntax issues. I suspect it means that the YAML parser could not go to the next line in the YAML file because of a breaking syntax error on the current line.
In may case it was missing quotas for password fields with symbols like "!##". Check your yaml file with yaml validator .
I had a similar issue but in my case, it was not blank spaces as shown in #Dijiflex's solution but it was an apostrophe or single quote character like in the example below;
pages:
title: "I don't have time this evening"
Please take note of the word don't so what I did was to escape it as below
pages:
title: "I don\\'t have time this evening"
I hope you have the idea now?
Enjoy
If you are parsing the YAML through ERB first, check your final YAML output (e.g. embedding of environment variables) to see if they contain invalid YAML, e.g. incomplete strings, etc.
Is it possible to ignore all whitespace using regex in MongoDB queries?
My Node.js program uses Cheerio to pull data from a number of websites, parses and then stores the data in MongoDB. My database has a People collection that keys on the string field Name.
Problem occurs where one website (site-A) shows the name HTML text as John&npsp;Smith, whereas another website (site-B) shows name as John Smith. My program has two scripts, one that scrapes site-A and another to scrape site-B; both of which use the following to scrape the Name data -
var $ = cheerio.load(htmlrow);
var personobj = { name: $('td.person a').text().trim() }
Each script then uses the following MongoDb command (using the native driver) to upsert the scraped data, keying on the Name field. However, this results in two records in the People collection -
db.collection('people').update(
{ Name: personobj.name },
{ $set: { LastScan: new Date() }},
{ upsert: true },
function(){} );
Now, I tried using the regex "extended" 'x' option to query in MongoDb, but it's not working. In fact, I tried testing the 'x' option via the find operator in Robomongo, and it returns zero records. I also note that when find testing in Robomongo, and I simply type Name: "John Smith", it only returns the site-B record, the one without the $nbsp; whitespace; even though when I view the detail of both records, the name strings appear identical. (I suppose difference is caused somewhere by all the encoding/decoding going on here to scrape, parse, store, retrieve... but I'm not sure where or why).
Is it possible to ignore all whitespace when querying MongoDb using regex?
Or, is it easier to handle this in my javascript parse line, to somehow replace and 'standardize' all possible whitespace characters? (Any recommended library to do so?)
I need something like (ansible inventory file):
[example]
127.0.0.1 timezone="Europe/Amsterdam" locales="en_US","nl_NL"
However, ansible does not recognize 'locales' as a list.
You can pass a list or object like this:
[example]
127.0.0.1 timezone="Europe/Amsterdam" locales='["en_US", "nl_NL"]'
With complex variables, it's best to define them in a host_vars file rather than in the inventory file, since host_vars files support YAML syntax.
Try creating a host_vars/127.0.0.1 file with the following content:
---
timezone: Europe/Amsterdam
locales:
- en_US
- nl_NL
Ryler's answer is good in this specific case but I ran into problems using other variations with the template module.
[example]
127.0.0.1 timezone="Europe/Amsterdam" locales='["en_US", "nl_NL"]'
Is his original example and works fine.
The following variations work with template. Basically if it's a string you must remember to use the internal double quotes or the entire structure is parsed as a single string. If it's only numbers or "True" or "False" (not "yes") then you're fine. In this variation I couldn't make it work with template if it had external quotes.
I haven't done an exhaustive check of which internal use cases they do and do not break other than the template module.
I am using Ansible 2.2.1.
[example:vars]
# these work
myvar1=["foo", "bar"]
myvar2=[1,2]
myvar3=[True,False]
# These fail, they get interpreted as a single string.
myvar4=[yes, no]
myvar5=[foo,bar]
myvar6='["foo", "bar"]'
you can try split
#inventory file
[example]
127.0.0.1 timezone="Europe/Amsterdam" locales="en_US","nl_NL"
#role file
---
- debug: msg="{{ item }}"
with_items: locales.split(',')
I believe the case is where you define your variable.
if it is under a
[host:vars]
var=["a", "b"]
otherwise:
[hosts]
host1 var='["a", "b"]'
INI file with variables looks like this
$ cat ./vars/vars.yml
lvol_names=['2g-1','2g-2','2g-3']
the variable represents the list type
lvol_names:
- 2g-1
- 2g-2
- 2g-3
the variable can be read from a playbook via lookup:
$ cat ./play.yml
- name: play1
hosts: kub2_data_nodes
become: yes
vars:
- lvol_names: "{{ lookup('ini', 'lvol_names type=properties file=./vars/vars.yml') }}"
You can custom a filter, to split string to list
Github ansible example show how to create custom filter.