How can I get configmap value where the key is dynamic in Kubernetes - regex

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.

Related

Add a new field in ISTIO envoy access log based on regex

I have an IstioOperator deployment with logs enabled in JSON format:
spec:
meshConfig:
accessLogFile: /dev/stdout
accessLogEncoding: JSON
No specific accessLogFormat is defined so default one applies.
[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %RESPONSE_CODE_DETAILS% %CONNECTION_TERMINATION_DETAILS%
\"%UPSTREAM_TRANSPORT_FAILURE_REASON%\" %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\"
\"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" %UPSTREAM_CLUSTER% %UPSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %DOWNSTREAM_REMOTE_ADDRESS% %REQUESTED_SERVER_NAME% %ROUTE_NAME%\n
However, what i want is to add another field at the end of log by the name PATH_MAIN which is derived from original path attribute but based on same regex (regex patterns already figured out) it would alter some values, such as redacting GUIDs etc.
My question is, how can I, if possible define a new field in Log Format by giving another field as attribute and defining its value based on regex.

Ansible: What is the correct syntax for a variable within a findall regex

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.

Regular expressions : How to exclude specific string inside a line

I'm trying to filter out API call names using regex.
The problem is that I can't filter out specific strings from the API calls which I don't need.
In the following examples I need to filter out/cut from the API call which contains the string "sg-" (if exists) what comes after it including the string itself and the others leave untouched.
Here is the example:
GET /api/cloudsecuritygroup/sg-91f988f7/history - 443
GET /api/cloudsecuritygroup/sg-30333554 - 443
GET /api/cloudaccounts/secret - 443
GET /api/audit/event-types - 443
GET /api/user/me/iam-safe/devices - 443
The result should look like this:
cloudsecuritygroup
cloudsecuritygroup
cloudaccounts/secret
audit/event-types
user/me/iam-safe/devices
Maybe this is regex you are looking for:
(?<=GET \/api)(.+(?=\/sg-)|[^\s]+)
Check it out here

Ansible Lineinfile - escaping single quote when using a back reference

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.

How specify a list value as variable in ansible inventory file?

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.