Get up to 50% off on CKA, CKAD, CKS, KCNA, KCSA exams and courses!

Python inside Ansible Playbook

I want to share some tips on how to directly use Python inside an Ansible playbook.

Python String Method

Ooops, error: “template error while templating string: no filter named ‘split’…” . This error is not abnormal when you execute the below task.

Normally it is caused by the plugin filter setup.

vars:
    s1: "Abc,Efg"

  tasks:
  - name: convert string to list
    set_fact:
      list_01: "{{ s1 | split(',') }}"

Is there any quick workaround?

The answer is to directly use the Python string method “split()”:

tasks:
  - name: convert string to list
    set_fact:
      list_02: "{{ s1.split(',') }}"

The below simple playbook demonstrates more of the Python string methods. “upper()”, “replace()”, “count()” and “isdigit()”.

Directly using Python string methods can improve the playbook string handling capability.

- hosts: localhost
  connection: local
  gather_facts: no
  vars:
    s1: "red hat, red hat"
    d1: '123'
  tasks:
  - name: Python String Methods
    debug:
      msg:
      - "Original String s1 - {{ s1 }}; d1 - {{ d1 }}"
      - "Converts a string into upper case - s1.upper(): {{ s1.upper() }}"
      - "Converts a string into upper case - s1.replace('r','R').replace('h','H'): {{ s1.replace('r','R').replace('h','H') }}"
      - "Returns the number of times a specified value occurs in a string - s1.count('red'): {{ s1.count('red') }}"
      - "Returns True if all characters in the string are digits - d1.isdigit(): {{ d1.isdigit() }}"

The output of the playbook:

PLAY [localhost] ****************************************************************************************************************************************************

TASK [Python String Methods] ****************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "Original String s1 - red hat, red hat; d1 - 123",
        "Converts a string into upper case - s1.upper(): RED HAT, RED HAT",
        "Converts a string into upper case - s1.replace('r','R').replace('h','H'): Red Hat, Red Hat",
        "Returns the number of times a specified value occurs in a string - s1.count('red'): 2",
        "Returns True if all characters in the string are digits - d1.isdigit(): True"
    ]
}

PLAY RECAP **********************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Python print() Method

Let’s view the below use case. It is part of the requirements to auto-generate the hostname during VM provision.

Convert ‘numeric’ index to 3 character string:

  • 1 ⇒ 001
  • 10 ⇒ 010
  • 100 ⇒ 100

Standard Ansible code looks like this. It includes three tasks.

- hosts: localhost
  connection: local
  gather_facts: no

  vars:
    vm_index: 10

  tasks:
  - name: index less 10
    debug:
      msg: "{{ '00' + vm_index | string }}"
    when: vm_index < 10

  - name: index less 100
    debug:
      msg: "{{ '0' + vm_index | string }}"
    when:
    - vm_index < 100
    - vm_index >= 10

  - name: index less 1000
    debug:
      msg: "{{ vm_index | string }}"
    when:
    - vm_index < 1000
    - vm_index >= 100

It can be simplified using Python if statement. It includes one task.

- name: index string
    debug:
      msg: "{{ '00' + vm_index | string
               if vm_index < 10
               else '0' + vm_index | string
               if vm_index < 100
               else vm_index
               if vm_index < 999
               else '---' }}"

Can we make it better? Yes, using Python print() method.

Simpler, nicer.

- name: index string
    debug:
      msg: "{{ '%03d' % vm_index }}"

Python Code

Sometimes, the Ansible module is not available for certain tasks. This task can be done within Python with less than 10 lines of code but to write a customized Python module would incur too much “overhead” work. In such a scenario, I prefer to extract and use the Python code inside the playbook.

One use case is to convert the SGT time to UTC time. I was not able to find the available Ansible module for such a simple task. But I know it can be done easily with a few Python codes. I used the Python code inside the playbook to solve this problem.

The server’s time zone is “Asia/Singapore”. Below is the playbook. It demonstrates how to directly use Python code and how to pass the input and output value between Python code and playbook.

- debug:
          msg: "Singapore Time: {{ year }}-{{ month }}-{{ date }}T{{ hour }}:{{ min }}:{{ sec }}"

  # it is easy to do time conversion in the python
  # Below is to directly use python code for time conversion
  # It requires tzdata packge and environment TZ is SGT
  - name: python code converts SGT to UTC
    command: /usr/bin/python3
    args:
      stdin: |
        from datetime import datetime
        import pytz

        dt_str  = "{{ year }}{{ month }}{{ date }}T{{ hour }}{{ min }}{{ sec }}"
        format = "%Y%m%dT%H%M%S"
        local_dt = datetime.strptime(dt_str, format)

        dt_utc = local_dt.astimezone(pytz.UTC)
        format = "%Y-%m-%dT%H:%M:%SZ"
        dt_utc_str = dt_utc.strftime(format)

        print(dt_utc_str)
    register: results

  - set_fact:
      utc_date: "{{ results.stdout }}"
Jin Zhang

Jin Zhang

I’m Jin, Red Hat ASEAN Senior Platform Consultant. My primary focus is Ansible Automation (Infrastructure as Code), OpenShift, and OpenStack.


Note

Disclaimer: The views expressed and the content shared in all published articles on this website are solely those of the respective authors, and they do not necessarily reflect the views of the author’s employer or the techbeatly platform. We strive to ensure the accuracy and validity of the content published on our website. However, we cannot guarantee the absolute correctness or completeness of the information provided. It is the responsibility of the readers and users of this website to verify the accuracy and appropriateness of any information or opinions expressed within the articles. If you come across any content that you believe to be incorrect or invalid, please contact us immediately so that we can address the issue promptly.

Share :

Related Posts

Ansible Automates 2020 on 9th & 10th September

Ansible Automates 2020 on 9th & 10th September

Another good news during this unusual time as Ansible Automate 2020 is a Virtual Event this year and we all will get the chance to attend the same …

Ansible Collections [LIVE]

Ansible Collection is a great way of getting content contributions from various Ansible Developers. We will learn what is Ansible Collection and how …

How to set up and use Python virtual environments for Ansible

How to set up and use Python virtual environments for Ansible

It’s vital to test new technology before rolling it out into your production environment. I like to use Python virtual environments provided by the …