How to Properly Convert String to Integer in Ansible Playbook for Conditional Tasks


10 views

When working with Ansible playbooks, one common pitfall is improper type conversion when evaluating conditions. The specific case where a PowerShell output needs to be converted to an integer for a when condition is particularly tricky due to hidden newlines or whitespace in the output.

The initial attempt to convert the output using | int filter might fail because:

- name: Problematic conversion example
  debug:
    msg: "{{ message_count.stdout | int }}"
  when: message_count.stdout | int == 0  # Might still fail

Here are three reliable approaches to handle this conversion:

Method 1: Using regex_replace to clean input

- name: Clean and convert output
  set_fact:
    clean_count: "{{ message_count.stdout | regex_replace('\\D', '') | int }}"

Method 2: Combined type checking and conversion

- name: Type-safe conversion
  set_fact:
    safe_count: "{{ (message_count.stdout is number) | ternary(message_count.stdout, 0) }}"
  when: message_count.stdout is defined

Method 3: Using Ansible's type_debug for troubleshooting

- name: Debug variable type
  debug:
    msg: "Type before conversion: {{ message_count.stdout | type_debug }}"

Here's a full playbook example that handles edge cases:

- hosts: localhost
  tasks:
    - name: Get message count
      shell: |
        # Your PowerShell command here
        echo "0"
      register: message_count
    
    - name: Convert and clean output
      set_fact:
        final_count: "{{ message_count.stdout | trim | int }}"
    
    - name: Send notification if zero
      mail:
        host: smtp.example.com
        port: 25
        from: noreply@example.com
        to: admin@example.com
        subject: "Zero count alert"
        body: "Detected zero messages"
      when: final_count == 0
  • Newlines or whitespace in the output string
  • Non-numeric characters in what appears to be a number
  • Undefined variables when the source command fails
  • Locale-specific number formatting

For complex scenarios, consider creating a custom filter plugin:

# filter_plugins/safe_convert.py
def to_int_safe(value, default=0):
    try:
        return int(str(value).strip())
    except:
        return default

class FilterModule(object):
    def filters(self):
        return {'to_int_safe': to_int_safe}

Usage in playbook:

- set_fact:
    verified_count: "{{ message_count.stdout | to_int_safe }}"

When working with Ansible playbooks that process PowerShell output, a common challenge arises when trying to use numeric values in conditional statements. The specific case where a message count of 0 isn't triggering the expected email notification typically stems from improper type conversion.

- name: Get message_count
  shell: echo "{{ (output.stdout | from_json).MessageCount }}"
  register: message_count
  delegate_to: localhost

The key observation here is that even after using the int filter, the condition might fail because:

  • The JSON parsing might return a string wrapped in quotes
  • The shell echo command adds another layer of string conversion
  • Ansible's type coercion rules might behave unexpectedly

Solution 1: Direct Type Conversion

- name: Convert count properly
  set_fact:
    actual_count: "{{ (output.stdout | from_json).MessageCount | int }}"
    
- debug:
    var: actual_count
    verbosity: 1

Solution 2: Using Jinja2 Type Testing

when: (countt | string) == "0"
- name: Process message count
  hosts: localhost
  tasks:
    - name: Get PowerShell output
      win_shell: |
        [PSCustomObject]@{
          MessageCount = 0
        } | ConvertTo-Json
      register: output
      
    - name: Convert count
      set_fact:
        processed_count: "{{ (output.stdout | from_json).MessageCount | int }}"
        
    - name: Debug output
      debug:
        var: processed_count
        
    - name: Send notification if zero
      mail:
        host: smtp.example.com
        port: 25
        from: no-reply@example.com
        to: admin@example.com
        subject: "Alert: Zero messages"
        body: "No messages were processed"
      when: processed_count == 0
  • Always debug your variables with debug before using them in conditions
  • Consider using type_debug filter to verify variable types
  • When dealing with external command outputs, add explicit conversion steps
  • For PowerShell specifically, consider using win_shell instead of shell module