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


2 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