Running ansible from jenkins execute shell

Hi All,

I am trying to run an ansible playbook from jenkins build to have jenkins trigger my ansible execution.

As part of my ansible-playbook run i need to pass extra-vars to the playbook during execution.

eg:

ansible-playbook -i $inventory-file $role-name --extra-vars"var1=$var1-value, var2=$var2-value"

when i put this line in the execute shell of jenkins the double quotes are evaluated and so aren’t available to the ansible-playbook command, so i escaped them as follows:

ansible-playbook -i $inventory-file $role-name --extra-vars"var1=$var1-value, var2=$var2-value"

But if i do this,

shell adds extra quotes around it as below:

ansible-playbook -i --extra-vars ’ "var1=var1-value,’ var2=var2-value, 'var3=var3-value " ’

And ansible give the following error:

Traceback (most recent call last):

File “/usr/local/bin/ansible-playbook”, line 317, in

sys.exit(main(sys.argv[1:]))

File “/usr/local/bin/ansible-playbook”, line 148, in main

extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt))

File “/Library/Python/2.7/site-packages/ansible/utils/init.py”, line 621, in parse_kv

vargs = split_args(args)

File “/Library/Python/2.7/site-packages/ansible/utils/splitter.py”, line 148, in split_args

raise Exception(“error while splitting arguments, either an unbalanced jinja2 block or quotes”)

Exception: error while splitting arguments, either an unbalanced jinja2 block or quotes

Has anyone come across such a situation before ?

I use ansible-playbook within “Execute shell” steps and I have had no issues. Here’s what I have in the “Execute shell” step:

ansible-playbook -i inventory playbook.yml --extra-vars=“var1=${VALUE1} var2=${VALUE2}”

You can put all your variables in a YAML file and pass it as --extra-vars=“@my_vars.yml

Given your example, your command will look like this:
ansible-playbook -i $inventory-file $role-name --extra-vars=“@my_vars.yml

and my_vars.yml should contain:

`

What version of Ansible are you using?

Hi,

Sorry for hi-jacking this old thread but I’m experiencing exactly the same problems as the original poster Naween. Have also tried Damirs workaround without success, just get the same result as when not using a vars file.

I’m running the following versions of Ansible and other related software:

OS: CentOS 6.5
Ansible verision:ansible-1.7.2-2.el6.noarch (from epel repo)
Python Jinja version: python-jinja2-2.2.1-1.el6.rf.x86_64 (think it was from rpmbone because of dependency trouble with other jinjas)
Jenkins version: jenkins-1.499-1.1.noarch

I tried this with ansible-1.7.0-1.el6.noarch also from epel repo with the same result. Everything works great with dynamic extra-vars variables from the command line but not from Jenkins.

Best regards,

//Jon

What does your execute shell look like with Damir's workaround? Were
you also able to see the values of the substitution has extra quotes
in that case or is it the same traceback but not necessarily the same
place that quotes are being mismatched?

-Toshio

I’m not sure I’m following, can you clarify exactly what your issue is?

The start of this thread was about how to pass variables.

Hi,

Sorry for being unclear about my problem. The issue is still about passing variables from Jenkins to Ansible as --extra-vars. I have done some more testing and biggest part of the problem was that I was trying to build up the complete ansible-playbook command from variables in Jenkins including extra-vars. Now when I just tried pasting the complete raw ansible-playbook command line in the Jenkins execute-shell box directly, it works just fine.

For example this works:
/usr/bin/python2 -u ansible-playbook manage_service.yml -l ${hosts} --extra-vars “service=${service} manage=${manage} serial=${serial} secs=${secs}”

But all the following examples causes trouble:
cmd=“/usr/bin/python2 -u ansible-playbook manage_service.yml -l ${hosts} --extra-vars “service=${service} manage=${manage} serial=${serial} secs=${secs}””
cmd=“/usr/bin/python2 -u ansible-playbook manage_service.yml -l ${hosts} --extra-vars "service=${service} manage=${manage} serial=${serial} secs=${secs}"”
cmd=“/usr/bin/python2 -u ansible-playbook manage_service.yml -l ${hosts} --extra-vars ‘service=${service} manage=${manage} serial=${serial} secs=${secs}’”

I also tried the workaround by using --extra-vars “@manage_service_vars.yml” but that produced a failure with the following message which seems to indicate that the variable does’nt get expanded:

msg: value of state must be one of: running,started,stopped,restarted,reloaded, got: $manage

I have also tried:
cmd=$(/usr/bin/python2 -u ansible-playbook manage_service.yml -l ${hosts} --extra-vars “service=${service} manage=${manage} serial=${serial} secs=${secs}”)
Which works but you get all the output from ansible in one line.

The reason for still building the complete command as a variable is to be able to add even more parameters to ansible as options to the Jenkins job without having the complete command line in several different sections of the execute-shell code.

For example:
if [ “${debug}” == “true” ]; then
runcmd=“${cmd} -vvvv”
else
runcmd=“${cmd}”
fi

It would be great if someone more knowledgeable than me :slight_smile: could give some input on how to solve the problem with not being able to build up the complete ansible-playbook command as a variable without breaking the --extra-vars parameter?

Best regards,

//Jon

It might help to split each --extra-vars into a separate args (you can have multiple --extra-vars in a single command). This should make it simpler to reason about quoting rules (in my opinion).

Our build script ends up looking something like this (hosts, site_rev, site_count) come from jenkins params:

args=“–extra-vars site_rev=$site_rev”
args=“${args} --extra-vars site_count=$site_count”
args=“${args} --limit localhost,$hosts”

ansible-playbook deploy_site.yml ${args}

This avoids having to worry about quoting the variables for ansible itself.

–michael

I’d recommend using bash arrays:

args=(
–extra-vars “site=$site”
–extra-vars “service=$service”
)
args+=( -l “$hosts” )

if [ -n “$just_joking” ]; then
args+=( --check )
fi

ansible-playbook “${args[@]}” # this is magic to stop bash from mangling the args

This is much more robust, and can even survive spaces in extra vars easily :slight_smile:

Michael Schultz mjschultz@gmail.com napisał:

To capitalize on Tomasz’s information, there’s a way to get bash to prefix the boilerplate “–extra-vars” string to each extra arg for you:

extra_args=( “site=$site” “service=$service” )

ansible-playbook “${extra_args[@]/#/–extra-args }”

(note the space character between “args” and “}”)

A short example:

#!/bin/bash

site=one

service=two
extra_args=( “site=$site” “service=$service” )

echo ansible-playbook “${extra_args[@]/#/–extra-args }”

will output:

ansible-playbook --extra-args site=one --extra-args service=two

There’s a similar syntax to add a suffix on each element of an array.

I haven’t used this particular function on bash versions earlier than 4.2, so be sure to test that it will work on your machine.

-Greg

Many thanks to you all for the nice working solutions! You never get too old to learn new stuff and improving your Bash skills :slight_smile:

//Jon

Did you get a final resolution on this? I’ve tried several suggestions here to no avail.

Strangely, when I copy the command line output from jenkins log and run it locally, it works fine! Only when running within jenkins does it fail…

Is jenkins adding some special characters that aren’t evident?