I started using ansible a week a go and I’m loving it, but I ran into a problem with conditions. I read that concatenation isn’t supported so I tried the following
This works if all options are set to true, but with the example below it fails because one of the options is false and the variable is defined but contains no stdout. I tried adding the following snippet, but apparently the variable is always set even if the condition is not met.
- name: Nginx | Set null option
command: echo
register: nginx_cache_purge_option
when: not nginx_cache_purge
I guess there’s probably a better way to handle this. Keep in mind that there will be more options
settings.yml:
_NGINX_VERSION: ‘1.5.6’
nginx_spdy: true
nginx_upload_progress: true
nginx_cache_purge: false
roles/nginx/tasks/build_from_source.yml:
-
name: Nginx | Update apt cache
apt: update_cache=yes cache_valid_time=3600
-
name: Nginx | Dependencies
apt: pkg={{ item }} state=present
with_items:
-
libpcre3
-
libpcre3-dev
-
libgeoip-dev
-
name: Nginx | Remove nginx dir
command: chdir=/var/opt removes=/var/opt/nginx* rm -rf /var/opt/nginx*
nginx
-
name: Nginx | Get archive
get_url: url=http://files.aegir.cc/dev/src/nginx-{{ _NGINX_VERSION }}.tar.gz dest=/var/opt/nginx-{{ _NGINX_VERSION }}.tar.gz
-
name: Nginx | Extract archive
command: chdir=/var/opt creates=/var/opt/nginx-{{ _NGINX_VERSION }} tar xvf nginx-{{ _NGINX_VERSION }}.tar.gz
-
name: Nginx | Remove archive
command: removes=/var/opt/nginx-{{ _NGINX_VERSION }}.tar.gz rm /var/opt/nginx-{{ _NGINX_VERSION }}.tar.gz
nginx-upload-progress-module
-
name: Nginx | Get archive
get_url: url=http://files.aegir.cc/dev/src/nginx-upload-progress-module.tar.gz dest=/var/opt/nginx-upload-progress-module.tar.gz
when: nginx_upload_progress
-
name: Nginx | Extract archive
command: chdir=/var/opt creates=/var/opt/nginx-upload-progress-module tar xvf nginx-upload-progress-module.tar.gz
when: nginx_upload_progress
-
name: Nginx | Remove archive
command: removes=/var/opt/nginx-upload-progress-module.tar.gz rm /var/opt/nginx-upload-progress-module.tar.gz
when: nginx_upload_progress
-
name: Nginx | Set option
command: echo --add-module=/var/opt/nginx-upload-progress-module/
register: nginx_upload_progress_option
when: nginx_upload_progress
ngx-cache-purge
-
name: Nginx | Get archive
get_url: url=http://files.aegir.cc/dev/src/ngx-cache-purge.tar.gz dest=/var/opt/ngx-cache-purge.tar.gz
when: nginx_cache_purge
-
name: Nginx | Extract archive
command: chdir=/var/opt creates=/var/opt/ngx-cache-purge tar xvf ngx-cache-purge.tar.gz
when: nginx_cache_purge
-
name: Nginx | Remove archive
command: removes=/var/opt/ngx-cache-purge.tar.gz rm /var/opt/ngx-cache-purge.tar.gz
when: nginx_cache_purge
-
name: Nginx | Set option
command: echo --add-module=/var/opt/ngx-cache-purge/
register: nginx_cache_purge_option
when: nginx_cache_purge
spdy - nginx_spdy
- name: Nginx | Set option
command: echo --with-http_spdy_module
register: nginx_spdy_option
when: nginx_spdy
compile time
- name: Nginx | Configure
command: chdir=/var/opt/nginx-{{ _NGINX_VERSION }} sh ./configure --prefix=/usr --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --user=www-data --group=www-data --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_ssl_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --without-http_scgi_module --without-http_uwsgi_module --with-ipv6 --with-http_geoip_module --with-debug {{ nginx_spdy_option.stdout }} {{ nginx_cache_purge_option.stdout }} {{ nginx_upload_progress_option.stdout }}
- name: Nginx | Make
command: chdir=/var/opt/nginx-{{ _NGINX_VERSION }} make --quiet
- name: Nginx | Install
command: chdir=/var/opt/nginx-{{ _NGINX_VERSION }} make --quiet install
“I read that concatenation isn’t supported so I tried the following”
Be careful what you read on the internet I’d be curious on specifically what you think is not possible if you are referring to strings
“but with the example below it fails because one of the options is false and the variable is defined but contains no stdout”
Which step fails? That’s a lot of copy/paste there…
Sorry about the wall of text, here’s a short example
spdy - nginx_spdy
-
name: Nginx | Set option
command: echo --with-http_spdy_module
register: nginx_spdy_option
when: nginx_spdy
-
name: Nginx | Configure
command: chdir=/var/opt/nginx-{{ _NGINX_VERSION }} sh ./configure --prefix=/usr --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --user=www-data --group=www-data --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_ssl_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --without-http_scgi_module --without-http_uwsgi_module --with-ipv6 --with-http_geoip_module --with-debug {{ nginx_spdy_option.stdout }}
When nginx_spdy == true this works, but when I set nginx_spdy to false I get
TASK: [nginx | debug msg=“nginx_spdy_option is {{nginx_spdy_option}}”] ********
ok: [vagrant1] => {
“item”: “”,
“msg”: “nginx_spdy_option is {u’skipped’: True, u’changed’: False}”
}
TASK: [nginx | Nginx | Configure] *********************************************
fatal: [vagrant1] => One or more undefined variables: ‘dict object’ has no attribute ‘stdout’
If concatenate is possible, what is the syntax to do something like this
-
name: Nginx | Set option
command: “–with-http_spdy_module” > {{ nginx_build_options }}
when: nginx_spdy
-
name: Nginx | Configure
command: chdir=/var/opt/nginx-{{ _NGINX_VERSION }} … {{ nginx_build_options }}
Looks like you should also apply the conditional on the second task and maybe have another version of the task that uses the “not false” vs “false” criteria and doesn’t use that variable.
This will work for 1 option, but I have like 7 of them, if I use that approach it means I have to add a task for any possible combination
Is there a way to concatenate strings, because then I could just add all options to one string variable?
Cheers,
Peter
I'm not sure I follow your example, but concatenation in jinja is just this
syntax:
{{ "some string " ~ var1 ~ " " ~ var2 }}
While Imho cleaner, it's the same as
"some string {{ var1 }} {{ var2 }}"
or
"some string {{ var1 ~' '~ var2 }}"
Using + for concatenation also works, but I the Jinja2 docs somewhere
mention ~ is preferred for string concatenation.
Now, if you have a default setting for nginx_build_options, you can do:
set_fact: nginx_build_options={{ nginx_build_options ~ '
--with-http_spdy_module'
}}
when: nginx_spdy
HTH,
Serge
Hello,
I did not know the set_fact plugin it is worth investigating thanks.
Here are 2 other options :
(1) concatenate via echo
- hosts: localhost
gather_facts: no
tasks:
- name: initialize nginx build options
command: echo “./configure”
register: nginx_build_options
- name: nginx_spdy option
command: echo “{{ nginx_build_options.stdout ~ ’ --with-http_spdy_module’}}”
register: nginx_build_options
when: nginx_spdy
- name: nginx_upload_progress option
command: echo “{{ nginx_build_options.stdout ~ ’ --add-module=/var/opt/nginx-upload-progress-module/'}}”
register: nginx_build_options
when: nginx_upload_progress
- name: output
debug: var=nginx_build_options
beware: this will make a lot of ssh round trips i guess i you have tons of options. maybe using local_action: could help here.
(2) template: and command:
use the template: module to send to the remote a templated build script.
in this template, you will be able to hide all the complexity of the configure options without making a long list of nearly useless tasks + you will send a lot less ssh commands
then execute your script with the command: module
Hope this helps
Jerome
Definitely, plus even with local action, you have an extra process spawned
to execute the command, and you have to use the more "ugly"
registered.stdout aftwerwards.
set_fact is just an action plugin which stays local
Jerome, Serge,
Thanks for your assistance, I have a working version. In case somebody else is looking for something similar
in settings.yml
nginx_spdy: true
nginx_upload_progress: true
nginx_cache_purge: false
nginx_build_options: ‘’
in the role.yml
- name: Nginx spdy | Set option
set_fact:
nginx_build_options: “{{ nginx_build_options }} --with-http_spdy_module”
when: nginx_spdy
Using a separate build script is probably an option as well, I’ll keep it in mind.
Cheers and thanks for the help
Peter