I've been using Ansible for a few years, mostly for server provisioning and
configuration management. I think it's a fantastic tool. For a new project,
I've also begun to attempt to use Ansible as a web application deployment
tool where I would have previously used ant. However, there are a couple of
snags that have me questioning whether the Ansible model is the best fit
for this type of task.
For example, the first thing I want to is download the deployment artefact
from Jenkins. This is only available internally, so my plan was to download
locally and then upload to the production servers. I quickly realised that
this was totally different to anything I'd done before as I was trying to
perform a task that wasn't really associated with any remote hosts. After a
bit of searching, I found this:
- hosts: 127.0.0.1
connection: local
Which works perfectly well, and could have been designed for exactly this
type of task, but it feels a bit like trying to fit a round peg in to a
square hole. I understand that since all modules assume that they are
executing within the context of a host, there is really no other way it
could be, but it got me thinking if Ansible is a good place to write these
type of non-host specific, pre-deployment steps?
The next challenge then was to have the play book prompt the user for the
job and build to deploy. var_prompt seemed perfect for this, so I ended up
with a playbook like so:
- hosts: 127.0.0.1
connection: local
vars_prompt:
jenkins_job: "Job Name"
jenkins_build: "Build Number"
roles:
- jenkinsfetch
- hosts: dashboards
roles:
- { role: uploadapp, app_name: 'dashboard' }
Which seemed to work well until I tried to reference jenkins_job and
jenkins_build from within the uploadapp role and couldn't:
TASK: [uploadapp | upload build tar] ***************************************
fatal: [local.dev] => One or more undefined variables: 'jenkins_job' is
undefined
FATAL: all hosts have already failed -- aborting
I spent a bit of time trying to figure out how to make these variables
visible across the plays but couldn't. I tried set_fact, which didn't work
as it's host specific. I tried to include both roles within the same play
but couldn't (obviously as I don't want to run uploadapp on 127.0.0.1) and
finally just resolved to put the variables as part of a global var file
rather than prompt for them. I can workaround this works, but it feels to
me like I'm trying to make Ansible do something it really doesn't want to.
The variable problem also came up when I wanted to abbreviate some paths
within my jenkinsfetch role:
---
- name: create builds dir
file: >
path=/tmp/builds/{{jenkins_job}}
state=directory
- name: fetch build from jenkins
get_url: >
url={{jenkins_url}}/job/{{jenkins_job}}/{{jenkins_build}}/artifact/build/output/{{jenkins_job}}_{{jenkins_build}}.tar.gz
dest=/tmp/builds/{{jenkins_job}}
So rather than reference /tmp/builds/{{jenkins_job}} twice, I wanted to
redefine a new variable, something along the lines of:
---
- name: set build dir
var: >
name=build_dir
value=/tmp/builds/{{jenkins_job}}
- name: create builds dir
file: >
path=/tmp/builds/{{jenkins_job}}
state=directory
In this case, set_fact may happen to work, but I'm not setting a fact about
a host, I'm just wanting to define a new variable (and have that visible
across the rest of the plays).
So I will carry on, but given these small snags, I'm curious if anyone else
has had the same experience - that when trying to implement a set of
deployment steps in Ansible, it sometimes feels like trying to force the
tool to do something it wasn't designed for?
Thanks
--
You received this message because you are subscribed to the Google Groups
"Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/ansible-project/a66caad5-c6b8-4244-aa17-9b1c5d7d13d7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.