if else clause for Dockerfile variable not working - docker

The following doesn't work in my Dockerfile:
RUN if $SSH_PRIVATE_KEY -eq ""; then echo "SSH key is not set, aborting"; exit 1; else echo "SSH key is set"; fi
I get the following error:
Step 4/15 : RUN if $SSH_PRIVATE_KEY -eq ""; then echo "SSH key is not set, aborting"; exit 1; else echo "SSH key is set"; fi
---> Running in 3bd29320f0e3
/bin/sh: -eq: command not found
I would like to check if the $SSH_PRIVATE_KEY variable contains anything at all.

Add quotes around your variable (if it might have spaces in it) and simply use = operator for string comparison.
In Bourne shell it would be :
if [ "$SSH_PRIVATE_KEY" = "" ]; then echo "SSH key is not set, aborting"; exit 1; else echo "SSH key is set"; fi

You have to put square brackets there.. Otherwise to test an empty variable is better -z switch.
RUN if [ -z "$SSH_PRIVATE_KEY" ]; then echo "SSH key is not set, aborting"; exit 1; else echo "SSH key is set"; fi

Related

how to escape double quotes in bash inside jenkins?

I have a Jenkins step as below.
stage('Initialize Namespace') {
when {
expression { params.initNS }
}
steps {
script {
setBuildStatus(processing_test_context, 'Initializing namespace', 'PENDING');
}
sh """ #!/bin/bash
set -e
namespaces="\${kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{\"\n\"}{end}'}"
echo "\${namespaces}"
if [[ \$namespaces =~ \$NAMESPACE ]]
then
kubectl create namespace $NAMESPACE || true
else
echo "The namespace already exists. Will be using the same"
fi
"""
}
How do I store the output of the command kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' in a variable? Currently, the error I am getting is ${kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{" "}{end}'}: bad substitution.
How do I escape " in the command?
Here is a working shell block for the script you provided.
sh"""
#!/bin/bash
namespaces=\$(kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{\"\\n\"}{end}')
echo "\$namespaces"
if [[ \$namespaces =~ \$NAMESPACE ]]
then
echo "Creating Namespace"
kubectl create namespace \$NAMESPACE || true
else
echo "The namespace already exists. Will be using the same"
fi
"""
If you don't need variable substitution(String interpolation) in your sh block you can use 3 single quotes rather than using double quotes which will allow you to get rid of multiple escape characters.
On a different note, the following is a different way to get what you need. Here $NAMESPACE has to be not empty always.
sh'''
#!/bin/bash
NS=$(kubectl get namespace $NAMESPACE --ignore-not-found);
echo $NS
if [[ -z "$NS" ]]; then
echo "Creating namespace $NAMESPACE"
kubectl create namespace $NAMESPACE || true
else
echo "The namespace already exists. Will be using the same"
fi
'''

SSH into machine, check to see if file exists, then fail Jenkins Execute shell if it does

I am trying to SSH into a machine from a Jenkins Execute shell, check to see if a file exists on the machine and if it does then fail the shell. I have the following code however I can seem to get Jenkins to recognize that the output of echo is "yes" or no"
Please let me know what you think...
sshpass -p ${ServerNodePw} ssh -T -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${ServerNodeUser}#${ServerNodeIP} << EOSSH
(ls /Volumes/ServerHD/Users/username/Desktop/JenkinsVMbuild.lock && echo yes) || echo no
2>/dev/null 1>/dev/null
echo "$?"
if [ "$?" = yes ]
then
echo "File found"
exit 1
currentBuild.result = 'FAILURE'
else
echo "File not found"
fi
EOSSH
The value of $? is the exit status of the last executed command (or pipeline). In your case, it would always expand to 0.
You can use command substitution instead if you want to store the echoed string in a variable.
You will also need to properly escape (or quote) the script in your here document. Otherwise $var will be substituted by the caller before passing the script to ssh.

How to pass a target argument in a sh script to run Docker build for a specific environment

I'm building a sh script to be able to run Docker containers all in once. In this way, I no need to run single containers every time.
What I need to add now is a way to run my docker-compose up --build -target=<ENV> the ENV will be DEV or PROD. In this way, I can run the right environment in my Docker setup.
At this time my script looks as follow but when I try to pass $2 = $DEV is giving me an error of [: =: unary operator expected and I don't know what could be the right fix to this
#!/bin/bash
CLEAN="clean"
RUN="run"
STOP="stop"
DEV="dev"
PROD="prod"
if [ "$#" -eq 0 ] || [ $1 = "-h" ] || [ $1 = "--help" ]; then
echo "Usage: ./myapp [OPTIONS] COMMAND [arg...]"
echo " ./myapp [ -h | --help ]"
echo ""
echo "Options:"
echo " -h, --help Prints usage."
echo ""
echo "Commands:"
echo " $CLEAN - Stop and Remove containers."
echo " $RUN - Build and Run containers."
echo " $STOP - Stop containers."
exit
fi
clean() {
stop_existing
remove_stopped_containers
remove_unused_volumes
}
run() {
echo "Cleaning..."
clean
echo "Running docker..."
if [ $2 = $DEV ]; then
echo "$DEV - Running in - $DEV - environment"
docker-compose up --build -target=$DEV
fi
}
stop_existing() {
MYAPP="$(docker ps --all --quiet --filter=name=wetaxitask_api_dev)"
REDIS="$(docker ps --all --quiet --filter=name=wetaxitask_redis)"
MONGO="$(docker ps --all --quiet --filter=name=wetaxitask_mongodb)"
if [ -n "$MYAPP" ]; then
docker stop $MYAPP
fi
if [ -n "$REDIS" ]; then
docker stop $REDIS
fi
if [ -n "$MONGO" ]; then
docker stop $MONGO
fi
}
remove_stopped_containers() {
CONTAINERS="$(docker ps -a -f status=exited -q)"
if [ ${#CONTAINERS} -gt 0 ]; then
echo "Removing all stopped containers."
docker rm $CONTAINERS
else
echo "There are no stopped containers to be removed."
fi
}
remove_unused_volumes() {
CONTAINERS="$(docker volume ls -qf dangling=true)"
if [ ${#CONTAINERS} -gt 0 ]; then
echo "Removing all unused volumes."
docker volume rm $CONTAINERS
else
echo "There are no unused volumes to be removed."
fi
}
if [ $1 = $CLEAN ]; then
echo "Cleaning..."
clean
exit
fi
if [ $1 = $RUN ]; then
run
exit
fi
if [ $1 = $STOP ]; then
stop_existing
exit
fi
What I want to achieve is that possible to run my sh as follow
./script.sh run dev or prod
When you invoke a shell function, it has its own argument list. The POSIX shell spec indicates:
The operands to the command temporarily shall become the positional parameters during the execution of the compound-command
So, if you define and call a shell function
print_two_things() {
echo "dollars one is $1"
echo "dollars two is $2"
}
print_two_things foo bar
print_two_things
$1 and $2 are the arguments to the function, not the script.
In your script, there are two errors in the run function
run() {
if [ $2 = $DEV ]; then :; fi
}
Here, again, $2 is the second argument to the function, not the script; since you invoke this as just run with no arguments it's an empty string. Second, you don't quote either of these variables, so the empty string just gets dropped. This expands to the nonsensical [ = dev ] which produces the error you see.
You need to either capture the positional parameters in variables at the top level, or pass them down to the shell function. An example of the latter approach could be:
run() {
environment="$1" # first parameter _to this function_
clean
if [ "$environment" = "$DEV" ]; then :; fi
}
# at the top level; parameters _to the script_
if [ "$1" = "$RUN" ]; then
run "$2"
exit 0
fi
In a Docker context you might find it easier just to pass this in as an environment variable. Anything you set with a docker run -e option or similar settings will be directly available as environment variables in shell scripts. It's also usually considered a best practice to run identical images in dev, test, and prod if at all possible.

jenkins Post Build if statement

Doing Jenkins Declarative Pipeline,
So I'm looking for "Post" action that will send e-mail only if there is 1 file which exists and is biggger then 0kb.
Very similiar to bash function : if [-s]
I can do that in a bash script, but how is done in jenkins for POST BUILD:
See how is made in bash:
if [ -s "$file" ]
then
/usr/bin/mutt -s "Master Failed 3Days" $emails -a $file < /dev/null
exit 1
else
echo "$file is empty."
/usr/bin/mutt -s "Master Success 3Days" $emails_success -a $file < /dev/null
exit 0
fi
This approach is working:
1. You are doing a global variable with your shell script in stage
result = sh(script: '''
if [ -s "$file" ]
then
/usr/bin/mutt -s "Master Failed 3Days" $emails -a $file < /dev/null
echo 'found'
else
echo "$file is empty."
/usr/bin/mutt -s "Master Success 3Days" $emails_success -a $file < /dev/null
echo 'not'
fi
''', returnStdout: true).trim()
You are adding post definitions
post {
always {
script {
if (result.contains('found')) {
<your logic to sending email>
}
}
}
}

How to get curl exit status from sh step command?

I'm trying to get the result of a command into a boolean variable in my Jenkinsfile. The command is: curl -o/dev/null -sfI "$url", which can be used in sh like this:
if ( curl -o/dev/null -sfI "$url" ); then
echo "URL exists"
else
echo "URL does not exist"
fi
So, I need this condition in my jenkinsfile but I don't know how to recreate it. This is what I've tried:
def fileAlreadyExists = sh(
script: "curl -o/dev/null -sfI \"$url\"",
returnStdout: true
)
But seems to return false always.
Your command does not return any output due to -o /dev/null switch. If you want to catch exit code you would have to set returnStatus and not returnStdout option, like:
def fileAlreadyExists = sh(
script: "curl -o/dev/null -sfI \"$url\"",
returnStatus: true
)
Alternatively you could extend your Bash command to do echo $? after the curl command to echo last command exit code:
def fileAlreadyExists = sh(
script: "curl -o/dev/null -sfI \"$url\"; echo \\\$?",
returnStdout: true
) as Integer // explicit casting needed, because it returns String
The variable fileAlreadyExists stores an integer value, so you can use it in if () statement (Groovy evalutes if (0) to false, so if you expect 0 exit code then it is good idea to make this comparison explicit like:
if (fileAlreadyExists == 0) { /* exists */ } else { /* not exist */ }
As a side note: remember to escape \ if you want to pass it to the sh command - Jenkins strips single escape character, so if you want to pass e.g. double quote the underlying script then you have to escape it in the following way: \\\".

Resources