Export of a variable from a bash script - jenkins

I've got to some variables which will be done with kubenetes command so I thought it best to put these in a bash script. I've managed to do that and called on it and see that variables get created but when it comes out of the bash script they are not assigned.
Within the Jenkinsfile script I have
steps {
sh '''
./bin/kube.sh
echo "Kube2 = ${SCRET}"
.....
and within the kube.sh file I have
#!/bin/bash
export SCRET=`kubectl -n keycloak get secret auser -o yaml | grep password | awk '{print $2}'`
echo "Kube2 = ${SCRET}"
I get the following results
+ ./bin/kube.sh
Kube1 = XXXXXXXX
+ echo 'SCRET = XXXXXXXX'
Kube2 =
Why is it that it gets unset again? What am I missing

Variables set in a subshell evaporate with that shell, and are not exported to the parent.
To set variables in the current environment using a script, you must source the code into the current context.
$: cat x
foo=bar
$: ./x && echo $foo # runs in a subshell - foo ends with ./x
$: . x && echo $foo # runs in current shell - foo is set
bar

Related

How to see the PATH inside a shell without opening a shell

Use the command flag looked like a solution but it doesn't work
Inside the following shell:
nix shell github:nixos/nixpkgs/nixpkgs-unstable#hello
the path contain a directory with an executable hello
I've tried this:
nix shell github:nixos/nixpkgs/nixpkgs-unstable#hello --command echo $PATH
I can't see the hello executable
My eyes are not the problem.
diff <( echo $PATH ) <( nix shell github:nixos/nixpkgs/nixpkgs-unstable#hello --command echo $PATH)
It see no difference. It means that the printed path doesn't not contains hello.
Why?
The printed path does not contain hello because if your starting PATH was /nix/var/nix/profiles/default/bin:/run/current-system/sw/bin, then you just ran:
nix shell 'github:nixos/nixpkgs/nixpkgs-unstable#hello' --command \
echo /nix/var/nix/profiles/default/bin:/run/current-system/sw/bin
That is to say, you passed your original path as an argument to the nix shell command, instead of passing it a reference to a variable for it to expand later.
The easiest way to accomplish what you're looking for is:
nix shell 'github:nixos/nixpkgs/nixpkgs-unstable#hello' --command \
sh -c 'echo "$PATH"'
The single quotes prevent your shell from expanding $PATH before a copy of sh invoked by nix is started.
Of course, if you really don't want to start any kind of child shell, then you can run a non-shell tool to print environment variables:
nix shell 'github:nixos/nixpkgs/nixpkgs-unstable#hello' --command \
env | grep '^PATH='

Echo dynamic sed to file inside Dockerfile

I am working on a Dockerfile, inside of which I want to dynamically create a sed expression based on the input argument variable, and write this expression to a file.
Here's part of the Dockerfile:
FROM ubuntu
ARG VERSION
RUN echo $VERSION > /usr/local/testfile
RUN echo '#!/bin/sh \n\
sed -i "s/\"version\"/\${VERSION}/g" file' > /usr/local/foo.sh
the image builds fine.
When I start a container from that image, and inspect the files:
# cat /usr/local/testfile
0.0.1
# cat /usr/local/foo.sh
#!/bin/sh
sed -i "s/\"version\"/\${VERSION}/g" file
I notice that the $VERSION was not replaced correctly in the sed command. What am I missing here? I've tried a few different things (e.g. "$VERSION") but none of them worked.
I ended up breaking down the command. I created a variable for the sed command by using string concatenation and then I echoed that to the file separately:
FROM ubuntu
ARG VERSION
ENV command="sed -i s/\"version\"/""$VERSION""/g"
RUN echo '#!/bin/sh' > /usr/local/foo.sh
RUN echo $command >> usr/local/foo.sh
# cat /usr/local/foo.sh
#!/bin/sh
sed -i s/"version"/0.0.1/g

How to set an environment variable for just one command in the Fish shell?

I have an environment variable GO111MODULE which is set to on in my ~/.config/fish/config.fish:
> echo $GO111MODULE
on
Following https://fishshell.com/docs/2.2/faq.html#faq-single-env, I would like to set it to off for a single command. As a sanity check I tried the echo command like so:
> env GO111MODULE=off echo $GO111MODULE
on
However, I notice that this is printing on instead of off as I would expect. Can anyone explain why this is not working?
When you enter the command
env GO111MODULE=off echo $GO111MODULE
the variable $GO111MODULE is substituted immediately (in the current context) before env ever runs or gets a chance to set the variable. So env just sees GO111MODULE=off echo on as its arguments.
In order to see the effect of the environment change, you need to arrange to do the envvar lookup after env has set it. So something like:
env GO111MODULE=off sh -c 'echo $GO111MODULE'
will show the changed variable -- the single ' around it will prevent the current shell from expanding the var, so env will get 4 arguments: GO111MODULE=off sh -c and echo $GO111MODULE. It will then invoke sh with two args, which will in turn exapnd the variable and run echo with a single off arg.
Alternative:
set -lx GO111MODULE off; echo $GO111MODULE
echo $GO111MODULE
Sets local environment variable and unfortunately retains it for this session, which might not be what you want.

Groovy shell script with a sed command in a Jenkins Pipeline

So writing Groovy with basic shell scripts seem to be much more difficult than it really should be.
I have a pipeline that needs to replace an entry in a file after running a packer command. It seems sensible to do this in the same shell script as the packer command as the variables are not available outside of the shell script even when exported.
The problem is that the sed command needs escape upon escape and still doesn't work. So this is what the Jenkins Pipeline Syntax generator suggested:
parallel (
"build my-application" : {
sh '''#!/bin/bash
export PATH=$PATH:~/bin
cd ${WORKSPACE}/platform/packer
packer build -machine-readable template.json | tee packer.out
AMI_APP=$(grep amazon-ebs,artifact,0,id,eu-west-2:ami- packer.out | awk -F: \'{ print $NF }\')
[[ ! ${AMI_APP} ]] && exit 1
sed -i.bak \'s!aws_ami_app = \\".*\\"!aws_ami_app = \\"\'"${AMI_APP}"\'\\"!\' ${WORKSPACE}/platform/terraform/env-${ENV}/env.auto.tfvars
'''
},
"build some-more-apps" : {
sh ''' *** same again different name ***
'''
}
)
What is the correct way to get a variable is a sed command working in a bash script running in groovy?
Any tips for the correct syntax going forward with Jenkins, groovy and bash - any documentation that actually helps?
EDIT
The original sed command that is running in a Jenkins Job shell is:
sed -i.bak 's!aws_ami_app = \".*\"!aws_ami_app = \"'"${AMI_APP}"'\"!' ${WORKSPACE}/platform/terraform/env-${ENV}/env.auto.tfvars
Because you put the shell script inside ''' which won't trigger Groovy String interpolation.
So you no need to escape any character, write the script as when you typing in Shell cmd window.
Below is example:
sh '''#!/bin/bash +x
echo "aws_ami_app = docker.xy.com/xy-ap123/conn:7et45u.1.23" > test.txt
echo "cpu = 512" >> test.txt
cat test.txt
AMI_APP=docker.xy.com/xy-ap123/conn:7et45u.1.25
sed -i 's,aws_ami_app.*,aws_ami_app = '"$AMI_APP"',' test.txt
cat test.txt
'''
Output in jenkins console:
[Pipeline] sh
[poc] Running shell script
aws_ami_app = docker.xy.com/xy-ap123/conn:7et45u.1.23
cpu = 512
aws_ami_app = docker.xy.com/xy-ap123/conn:7et45u.1.25
cpu = 512

Jenkins Groovy pass variables to parallel runs

I am having problems figuring out how to pass some variables into the parallel runs in the Jenkins groovy script below:
#!/usr/bin/env groovy
def call(version, project) {
sh '''#!/bin/bash
[[ ! -e ${WORKSPACE}/target/rpm/${project}/RPMS/ ]] && mkdir -p ${WORKSPACE}/target/rpm/${project}/RPMS/
(( $(ls ${WORKSPACE}/target/rpm/${project}/RPMS/*.rpm | wc -l) != 0 )) && rm ${WORKSPACE}/target/rpm/${project}/RPMS/*.rpm
cd ${WORKSPACE}/scripts/fpm_requirements && bundle install && bundle show fpm
'''
parallel (
"package foo": {
sh '''#!/bin/bash
export PATH=$PATH:~/bin:~/.gem/ruby/gems
cd ${WORKSPACE}/scripts/fpm_requirements
echo Project is ${project}
echo Version is ${version}
echo Iteration is $(echo ${version} | cut -d . -f 3)
'''
},
"package bar": {
sh '''#!/bin/bash
export PATH=$PATH:~/bin:~/.gem/ruby/gems
cd ${WORKSPACE}/scripts/fpm_requirements
echo Project is ${project}
echo Version is ${version}
echo Iteration is $(echo ${version} | cut -d . -f 3)
'''
}
)
}
So the version and project variables are populated in the first shell that is called but when they hit the two parallel runs they are not being pulled in.
I have tried a few different options to pass them in but none have worked.
Does anyone have any relevant ideas that might help?
You should change the ''' to """. In Groovy, string inside single/triple quote won't trigger string interpolation, but string inside single/triple double quote will do that.
So the ${version} and ${project} in your Shell script will be treated as variable from Shell context, but actually they are exist in Groovy context.
More about Groovy String at here, Below option 2 more suitable for your issue.
Option 1) using "" or """
"package foo": {
sh """#!/bin/bash
export PATH=\$PATH:~/bin:~/.gem/ruby/gems
cd \${WORKSPACE}/scripts/fpm_requirements
echo Project is ${project}
echo Version is ${version}
echo Iteration is \$(echo ${version} | cut -d . -f 3)
"""
},
"package bar": {
sh """#!/bin/bash
export PATH=\$PATH:~/bin:~/.gem/ruby/gems
cd \${WORKSPACE}/scripts/fpm_requirements
echo Project is ${project}
echo Version is ${version}
echo Iteration is \$(echo ${version} | cut -d . -f 3)
"""
}
Attention: need to escape the $ ahead of ${WORKSPACE} and $(echo ..), because we hope $ be kept after interpolation.
Option 2) using ' or ''' and inject version and project into Environment Variables of Shell context.
def call(version, project) {
env.version=version
env.project=project
// Groovy env api used to inject groovy value into environment variable
// so that you can refer groovy value later in shell script
// still use ''' in following code, no need to change
...

Resources