how to reuse (reference) variables from other rules block in gitlab ci? - gitlab-ci

I have am creating a gitlab ci and have rules as below:
include:
- template: "Workflows/Branch-Pipelines.gitlab-ci.yml"
.rule_a:
rules:
- if: $CI_COMMIT_BRANCH == $PRODUCTION_BRANCH
variables:
VAR1: "var1"
.rule_b:
rules:
- if: $CI_COMMIT_BRANCH == $STAGING_BRANCH
variables:
VAR2: # I need to read from VAR1 in rule_a
How can I do something like !reference [.rule_a, rules, variables, VAR2]?
https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#reference-tags

You can't reference items in an arrary. But you could separate out your variables for rule_a into its own hidden key.
.variables_1
variables:
VAR1: "var1"
.rule_a:
rules:
- if: $CI_COMMIT_BRANCH == $PRODUCTION_BRANCH
variables: !reference [.variables_1, variables]
.rule_b:
rules:
- if: $CI_COMMIT_BRANCH == $STAGING_BRANCH
variables:
VAR2: !reference [.variables_1, variables, VAR1]

Related

Ansible - Concatinating variable give error `can only concatenate list (not \"NoneType\") to list"`

I have three variable files app1.yml, app2.yml and app3.yml having the same variable name viz dbconn
cat app1-webapps-dev.yml
dbconn:
- host1 port1
cat app2-webapps-dev.yml
dbconn:
- host4 port4
- host5 port5
cat app3-webapps-dev.yml
dbconn:
As you can see the variable dbconnin app3.yml is empty. When empty the below ansible play to concat the variable fails with error:
- set_fact:
dbconn: "{{ dbconn|d([]) + (lookup('file', item ~ '-webapps-' + ENV ~ '.yml' )|from_yaml).dbconn }}"
loop:
- app1
- app2
- app3
Error:
fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type
error occurred on ({{ dbconn|d([]) + (lookup('file', item ~
'-webapps-' + ENV ~ '.yml' )|from_yaml).dbconn }}): can only
concatenate list (not "NoneType") to list"}
Can you please suggest?
you can add a condition, as a NoneType equals false
- set_fact:
dbconn: "{{ dbconn|d([]) + (lookup('file', item ~ '-webapps-dev'~ '.yml' )|from_yaml).dbconn }}"
when: ((lookup('file', item ~ '-webapps-dev'~ '.yml' )|from_yaml).dbconn)

Need help on bask awk to update Yaml file by finding the pattern in the file

CONTEXT: I am very new to UNIX scripting and bash.
I have a .bash script that takes a .yaml and an array of VMs passed as arguments.
(e.g.)
myscript.sh my.yaml neo1 neo2 neo3 alice1 alice2 alice3
How to find the monitor_vm key pattern and file the last lime of the that monitor section and add at the last lines of that section?
Have got one sample function which identifies some pattern to give line number of that inserting line ....but it requires some changes. Please advise
example
getline() {
awk '
BEGIN { monitor_vms="'${}'"; ln=1; fnd=0; }
(fnd==1 && $0 ~ /^ [a-z]/) { exit }
($0~/^monitor_vms:/) { fnd = 1 }
($0 ~ /./ && $0 !~ /^#/) { ln = NR }
END { print ln }' ${1}
}
for name in $VM_LIST; do
line=`getline my.yaml monitor_vms`
sed -i -e ${line}"a\- name: \"${vmname}\"\n my.yaml
done
The file my.yaml looks like the following:
---
- someotherkey: hello
value: some_value
- someotherkey1: hello1
value1: some_value1
- monitor_vms:
- name: sujana
cnt: 5
- name: vijaya
cnt: 5
- static_configs:
- location:
datacenter:
I would expect to produce the required my.yaml, after update:
---
- someotherkey: hello
value: some_value
- someotherkey1: hello1
value1: some_value1
- monitor_vms:
- name: sujana
cnt: 5
- name: vijaya
cnt: 5
- name: neo1
- name: neo2
- name: neo3
- name: alice1
- name: alice2
- name: alice3
- static_configs:
- location:
datacenter:
You never need sed when you're using awk, you're letting shell variables expand to become part of scripts, and you have other shell errors in your code. As a starting point you should copy/paste all your scripts into http://shellcheck.net and fix the errors it tells you about.
This uses GNU awk for "inplace" editing since you were using GNU sed to do the same:
$ cat myscript.sh
#!/usr/bin/env bash
file="$1"
shift
awk -i inplace -v vms="$*" '
/^-/ {
if ( $2 == "monitor_vms:" ) {
inBlock = 1
}
else {
prtVms()
}
}
$1 == "-" {
prev = $0
}
{ print }
END { prtVms() }
function prtVms( vmsArr, i, n) {
if ( inBlock ) {
sub(/:.*/,":",prev)
n = split(vms,vmsArr)
for (i=1; i<=n; i++) {
print prev, vmsArr[i]
}
}
inBlock = 0
}
' "$file"
$ cat my.yaml
---
- someotherkey: hello
value: some_value
- someotherkey1: hello1
value1: some_value1
- monitor_vms:
- name: sujana
cnt: 5
- name: vijaya
cnt: 5
- static_configs:
- location:
datacenter:
$ ./myscript.sh my.yaml neo1 neo2 neo3 alice1 alice2 alice3
$ cat my.yaml
---
- someotherkey: hello
value: some_value
- someotherkey1: hello1
value1: some_value1
- monitor_vms:
- name: sujana
cnt: 5
- name: vijaya
cnt: 5
- name: neo1
- name: neo2
- name: neo3
- name: alice1
- name: alice2
- name: alice3
- static_configs:
- location:
datacenter:

SED, GREP, AWK, regex do not display content between two patterns contain and match a string inside on the second occurrence pattern

Is there a way to not display a block between two patterns when it matches a string inside the block and only to the 2nd occurrence of the second pattern?
example :
test, test-xxx-a2, Deployment (apps) has changed:
...
- value: 4.x.x
+ value: x.3.x
...
test, test-xxxio-3, Deployment (apps) has changed:
...
- replicas: 3
+ replicas: 5
...
test, test-xxx-xxx, Deployment (apps) has changed:
...
- value: x.2.x
+ value: x.x.x
...
test, test-xxxio-1, Deployment (apps) has changed:
...
- replicas: 3
+ replicas: 5
...
test, test-xxxio-4, Deployment (apps) has add:
...
text...
...
test, test-xxx-test2, Deployment (apps) has changed:
...
- replicas: 3
+ replicas: 2
...
text, text-123-xxx, Deployment (apps) has changed:
...
- replicas: 1
+ replicas: 2
...
- value: 2.1.0
+ value: 42.4.0
...
Output desire:
test, test-xxx-a2, Deployment (apps) has changed:
...
- value: 4.x.x
+ value: x.3.x
...
test, test-xxx-xxx, Deployment (apps) has changed:
...
- value: x.2.x
+ value: x.x.x
...
test, test-xxxio-4, Deployment (apps) has add:
...
text...
...
text, text-123-xxx, Deployment (apps) has changed:
...
- value: 2.1.0
+ value: 42.4.0
...
first pattern: changed:
second pattern: ... (only the second)
string in to contain: replicas
the regex I'm working https://regex101.com/r/FTGBxG/1, but of course, it's not my output desire.
$ awk -v ORS= '
{ buf = buf $0 RS }
($0 == "...") && ((++sepCnt % 2) == 0) {
if ( buf !~ /replicas/ ) {
print buf
}
buf=""
}
' file
test, test-xxx-a2, Deployment (apps) has changed:
...
- value: 4.x.x
+ value: x.3.x
...
test, test-xxx-xxx, Deployment (apps) has changed:
...
- value: x.2.x
+ value: x.x.x
...
test, test-xxxio-4, Deployment (apps) has add:
...
text...
...
You may use this awk script:
cat filter.awk
index($0, "Deployment (apps)") {
p = 1
s = ""
num3dots = 0
}
p {s = s $0 ORS}
index($0, "...") == 1 && ++num3dots == 2 {
if ( s !~ /changed:.* replicas/ )
printf "%s", s
p = 0
}
Then use it as:
awk -f filter.awk file
test, test-xxx-a2, Deployment (apps) has changed:
...
- value: 4.x.x
+ value: x.3.x
...
test, test-xxx-xxx, Deployment (apps) has changed:
...
- value: x.2.x
+ value: x.x.x
...
test, test-xxxio-4, Deployment (apps) has add:
...
text...
...

Take process input from either of two channels

How do I allow a process to take an input from either one of two channels that are outputs of processes with mutually exclusive conditions for running? For example, something like:
params.condition = false
process a {
output:
path "a.out" into a_into_c
when:
params.condition == true
"""
touch a.out
"""
}
process b {
output:
path "b.out" into b_into_c
when:
params.condition == false
"""
touch b.out
"""
}
process c {
publishDir baseDir, mode: 'copy'
input:
path foo from a_into_c or b_into_c
output:
path "final.out"
"""
echo $foo > final.out
"""
}
where final.out will contain a.out if params.condition is true (e.g. --condition is given on the command line), and b.out if it is false.
You can use the mix operator for this:
process c {
publishDir baseDir, mode: 'copy'
input:
path foo from a_into_c.mix(b_into_c)
output:
path "final.out"
"""
echo $foo > final.out
"""
}

if/else logic in gitlab ci based on return code of python script

I have a gitlab-ci.yml file that I'm invoking a python script from like:
- /usr/bin/python3.6 file.py
This file.py file returns either True or False
In pseudocode I'm trying to do:
- run file.py
- if True: do x
- else do y
How can I achieve this in gitlabci ?
Thanks
How does it return True or False - by writing to stdout?
If so then
- RES=$(run file.py)
- |
if [[ $RES == "True" ]]; then
...
else
...
fi