Troubleshooting Ansible Playbook Failures When Building curl with Complex Configure Switches


2 views

>
>
>
>

When working with Ansible to compile software from source, the command and shell modules behave differently in how they handle command arguments. In this case, we're seeing failures specifically during the ./configure step of building curl from source.

>
>
>
>

- name: Build CURL with openssl
>
>  command: 'chdir={{ curl_dir }} "{{ item }}"'
>
>  with_items:
>
>    - ./buildconf
>
>    - ./configure --with-gssapi --with-libidn --with-libssh2 --prefix=/usr --without-nss
>
>    - make
>
>    - make install
>
>    - ldconfig

>
>

The error occurs because Ansible's command module doesn't handle shell-style command parsing. It tries to execute the entire configure string as a single command name rather than parsing the switches.

>
>
>
>

The proper way to handle complex configure commands is to use the shell module with proper quoting:

>
>

- name: Configure and build CURL
>
>  shell: |
>
>    cd {{ curl_dir }} && \
>
>    ./buildconf && \
>
>    ./configure --with-gssapi --with-libidn --with-libssh2 --prefix=/usr --without-nss && \
>
>    make && \
>
>    make install && \
>
>    ldconfig
>
>  args:
>
>    executable: /bin/bash

>
>
>
>

For better error handling and idempotency, consider breaking this into separate tasks:

>
>

- name: Run buildconf
>
>  command: ./buildconf
>
>  args:
>
>    chdir: "{{ curl_dir }}"
>
>- name: Run configure
>
>  command: ./configure --with-gssapi --with-libidn --with-libssh2 --prefix=/usr --without-nss
>
>  args:
>
>    chdir: "{{ curl_dir }}"
>
>  register: configure_result
>
>  changed_when: "'config.status' not in lookup('file', '{{ curl_dir }}/config.status')"
>
>- name: Run make
>
>  make:
>
>    chdir: "{{ curl_dir }}"
>
>    target: all
>
>- name: Install curl
>
>  make:
>
>    chdir: "{{ curl_dir }}"
>
>    target: install

>
>
>
>

Ensure all build dependencies are installed. For CentOS/RHEL systems, this includes:

>
>

- name: Install build dependencies
>
>  yum:
>
>    name:
>
>      - make
>
>      - gcc
>
>      - libtool
>
>      - automake
>
>      - autoconf
>
>      - libidn-devel
>
>      - libssh2-devel
>
>      - krb5-devel
>
>      - openssl-devel
>
>    state: present

>
>
>
>

Add debug tasks to verify the build environment:

>
>

- name: Check directory structure
>
>  command: ls -la {{ curl_dir }}
>
>  register: dir_listing
>
>  changed_when: false
>
>- debug:
>
>    var: dir_listing.stdout_lines

>
>
>
>

    >
    >

  • Always clean the source directory between runs if recompiling
  • >
    >

  • Consider using creates parameter to make tasks idempotent
  • >
    >

  • Capture build output in log files for debugging
  • >
    >

  • Test the playbook in a clean environment
  • >
    >

>
>


The root issue stems from how Ansible's command module handles complex command strings differently than direct shell execution. In your playbook, the configure command fails because:

The command module treats the entire string as a single executable path rather than parsing it as a shell would. The error occurs because:

"./configure --with-gssapi --with-libidn --with-libssh2 --prefix=/usr --without-nss"

is interpreted as looking for a single file with that complete name rather than executing ./configure with parameters.

There are several better approaches to execute build commands in Ansible:

- name: Build CURL with openssl (Recommended approach)
  shell: |
    cd {{ curl_dir }} &&
    ./buildconf &&
    ./configure --with-gssapi --with-libidn --with-libssh2 --prefix=/usr --without-nss &&
    make &&
    make install &&
    ldconfig
  args:
    chdir: "{{ curl_dir }}"

Or using separate tasks with proper module selection:

- name: Run buildconf
  command: ./buildconf
  args:
    chdir: "{{ curl_dir }}"

- name: Run configure
  command: ./configure
  args:
    chdir: "{{ curl_dir }}"
    argv:
      - "--with-gssapi"
      - "--with-libidn"
      - "--with-libssh2"
      - "--prefix=/usr"
      - "--without-nss"
  1. Using shell for complex command sequences with proper chdir handling
  2. Proper argument splitting when using command module
  3. Maintaining idempotence through proper creates/removes parameters
  4. Better error handling through sequential execution with &&

Here's the corrected version of your playbook section:

- name: Build and install CURL
  block:
    - name: Run build steps
      shell: |
        ./buildconf &&
        ./configure {{ configure_flags }} &&
        make &&
        make install &&
        ldconfig
      args:
        chdir: "{{ curl_dir }}"
      vars:
        configure_flags: >
          --with-gssapi
          --with-libidn
          --with-libssh2
          --prefix=/usr
          --without-nss
      environment:
        PATH: "{{ ansible_env.PATH }}:/usr/local/bin"