Jenkinsfile with ansibleplaybook using multiple inventory files - ansible

When I need to include multiple inventory files using ansible-playbook in cli y usually use:
ansible-playbook -i inventory/dev-hosts -i inventory/staging-hosts playbooks/run.yml
Now I want to do this, but in a Jenkinsfile . I´m using the following code:
stage('1') {
steps {
ansiColor('xterm') {
ansiblePlaybook([
colorized: true,
inventory: inventory/dev-hosts , inventory/staging-hosts ,
playbook: playbooks/run.yml
])
}
}
}
But this not working. I can´t find information how to do this using Jenkinsfile. Any idea on how to solve it ?

Related

Access string variable from bash in jenkinsfile groovy script

I'm building several android apps in a docker image using gradle and a bash script. The script is triggered by jenkins, which runs the docker image.
In the bash script I gather information about the successes of the builds. I want to pass that information to the groovy script of the jenkinsfile.
I tried to create a txt file in the docker container, but the groovy script in the jenkinsfile can not find that file.
This is the groovy script of my jenkinsfile:
script {
try {
sh script:'''
#!/bin/bash
./jenkins.sh
'''
} catch(e){
currentBuild.result = "FAILURE"
} finally {
String buildResults = null
try {
def pathToBuildResults="[...]/buildResults.txt"
buildResults = readFile "${pathToBuildResults}"
} catch(e) {
buildResults = "error receiving build results. Error: " + e.toString()
}
}
}
In my jenkins.sh bash script I do the following:
[...]
buildResults+=" $appName: Build Failed!" //this is done for several apps
echo "$buildResults" | cat > $pathToBuildResults //this works I checked, if the file is created
[...]
The file is created, but groovy cannot find it. I think the reason is, that the jenkins script does not run inside the docker container.
How can I access the string buildResults of the bash script in my groovy jenkins script?
One option that you have in order to avoid the need to read the results file is to modify your jenkins.sh script to print the results to the output instead of writing them to a file and then use the sh step to capture that output and use it instead of the file.
Something like:
script {
try {
String buildResults = sh returnStdout: true, script:'''
#!/bin/bash
./jenkins.sh
'''
// You now have the output of jenkins.sh inside the buildResults parameter
} catch(e){
currentBuild.result = "FAILURE"
}
}
This way you are avoiding the need to handle the output files and directly get the results you need, which you can then parse and use however you need.

How to pass environment variable to sh script?

I want to create an environment variable in Jenkinsfile which will consist of current workspace (using envirnoment variable WORKSPACE). Then I want to pass this new variable to sh script in next stage.
I've tried declaring variable in the following way:
environment {
artefact_path = "${env.WORKSPACE}/temp/unzipped/${artefact_name}/dev"
}
But after passing it to sh script:
sh "ansible-playbook -i inventory playbook.yml -e \"artefact_path=${env.artefact_path}\""
I get the following output:
+ ansible-playbook -i inventory playbook.yml -e 'artefact_path=C:\nowy_dir\workspace\something/temp/unzipped/something/dev'
PLAY [play] **************************************************************
TASK [task] *********************************************************
fatal: [host]: FAILED! => {"changed": false, "dest": "D:/inetpub/something", "msg": "Get-AnsibleParam: Parameter 'src' has an invalid path 'C:\nowy_dir\\workspace\\something/temp/unzipped/something/dev' specified.", "src": "C:\nowy_dir\\workspace\\something/temp/unzipped/something/dev"}
to retry, use: --limit #/etc/ansible/ansible-scripts/playbook.retry
As you can see the variable is passed with two \ instead of one. How can I prevent this from happening?
EDIT 1
I decided to change the way in which I declare the variable to:
def get_deploy_path() {
def site = get_site()
def wspace = "${env.WORKSPACE}"
def deploy_path = wspace.toString() + "\\temp\\snapshot\\" + site + "\\"
return deploy_path
}
environment {
deploy_path = get_deploy_path()
}
Now I have a problem with workspace. I'm operating on two agents (first is Windows and the second is Linux based). I need the path to be the same both in stages on Windows and on Linux. Any idea how I can make it happen?

Ansible pass multiple lines in input variable file

I am running ansible playbook via taking variables from a file outside
ansible-playbook -v /path/export.yml --extra-vars '#input.json'
Now the file has only one line like below
{ out_file: exp_app_12.xml, control_file: export_control.xml}
Now I want to push multiple lines in the input.json file like below
{ out_file: exp_app_12.xml, control_file: export_control1.xml}
{ out_file: exp_app_13.xml, control_file: export_control2.xml}
{ out_file: exp_app_14.xml, control_file: export_control3.xml}
But it's not working , how to achieve this ?
You should pass the JSON file in proper format like this;
ansible-playbook arcade.yml --extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'
I think your JSON file is not in correct format, it must be like this;
[
{"out_file": "exp_app_12.xml","control_file": "export_control1.xml"},
{"out_file": "exp_app_12.xml","control_file": "export_control1.xml"},
{"out_file": "exp_app_12.xml","control_file": "export_control1.xml"}
]
Furthermore see the ansible docs here for more understanding.

Escape chars in Terraform local exec provisioner

I want to chain Terraform and Ansible using the local-exec provisioner;
However since this requires input to Ansible from Terraform I am stuck with the following complex command:
provisioner "local-exec" {
command = 'sleep 60; ansible-playbook -i ../ansible/inventory/ ../ansible/playbooks/site.yml --extra-vars "rancher_server_rds_endpoint="${aws_db_instance.my-server-rds.endpoint}" rancher_server_elastic_ip="${aws_eip.my-server-eip.public_ip}""'
}
which keeps returning
illegal char
error;
any suggestion about escaping correctly?
If the ansible-playbook command was to run directly in the shell it would be:
ansible-playbook -i inventory playbooks/site.yml --extra-vars "my_server_rds_endpoint=my-server-db.d30ikkj222.us-west-1.rds.amazonaws.com rancher_server_elastic_ip=88.148.17.236"
(paths differ)
Terraform syntax states that:
Strings are in double-quotes.
So you need to replace single quotes with double ones, and then escape quotes inside, for example:
provisioner "local-exec" {
command = "sleep 60; ansible-playbook -i ../ansible/inventory/ ../ansible/playbooks/site.yml --extra-vars \"rancher_server_rds_endpoint='${aws_db_instance.my-server-rds.endpoint}' rancher_server_elastic_ip='${aws_eip.my-server-eip.public_ip}'\""
}
The only way I know, that will work for any special characters in variables, is to use environment, for example:
provisioner "local-exec" {
command = join(
" ", [
"sleep 60;",
"ansible-playbook -i ../ansible/inventory/",
"../ansible/playbooks/site.yml",
"--extra-vars",
"rancher_server_rds_endpoint=\"$RANCHER_SERVER_RDS_ENDPOINT\"",
"rancher_server_elastic_ip=\"$RANCHER_SERVER_ELASTIC_IP\""
]
)
environment = {
RANCHER_SERVER_RDS_ENDPOINT = aws_db_instance.my-server-rds.endpoint
RANCHER_SERVER_ELASTIC_IP = aws_eip.my-server-eip.public_ip
}
}

executing shell script and using its output as input to next gradle task

I am using gradle for build and release, so my gradle script executes a shell script. The shell script outputs an ip address which has to be provided as an input to my next gradle ssh task. I am able to get the output and print on the console but not able to use this output as an input to next task.
remotes {
web01 {
def ip = exec {
commandLine './returnid.sh'
}
println ip --> i am able to see the ip address on console
role 'webServers'
host = ip --> i tried referring as $ip '$ip' , both results into syntax error
user = 'ubuntu'
password = 'ubuntu'
}
}
task checkWebServers1 << {
ssh.run {
session(remotes.web01) {
execute 'mkdir -p /home/ubuntu/abc3'
}
}
}
but it results in error "
What went wrong:
Execution failed for task ':checkWebServers1'.
java.net.UnknownHostException: {exitValue=0, failure=null}"
Can anyone please help me use the output variable in proper syntax or provide some hints which could help me.
Thanks in advance
The reason it's not working is the fact, that exec call return is ExecResult (here is it's JavaDoc description) and it's not a text output of the execution.
If you need to get the text output, then you've to specify the standardOutput property of the exec task. This could be done so:
remotes {
web01 {
def ip = new ByteArrayOutputStream()
exec {
commandLine './returnid.sh'
standardOutput = ip
}
println ip
role 'webServers'
host = ip.toString().split("\n")[2].trim()
user = 'ubuntu'
password = 'ubuntu'
}
}
Just note, the ip value by default would have a multiline output, include the command itself, so it has to be parsed to get the correct output, For my Win machine, this could be done as:
ip.toString().split("\n")[2].trim()
Here it takes only first line of the output.

Resources