Conditions and configure options

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 :slight_smile: 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 :confused:

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