Skip to content
Tech Blog / Ansible and Db2 for z/OS – Even More Fun with Collections

Ansible and Db2 for z/OS – Even More Fun with Collections

Ansible on Db2 for z/OS More Fun with Collections

Introduction

In the last blog on Ansible and z/OS we walked through how to create a collection of modules to provide extended functionality. There was a lot of great information in that post about getting this all together and publishing on to Ansible Galaxy, but a part that I hadn’t worked out when I wrote that one (okay, hadn’t read up on) was how to implement usable shared functions for the modules in the collection.

This should be really simple – and mostly it is – but the challenge is really how we direct the module to find the function in the collection without accidentally making the function visible to the outside world. More on this after a better explanation of the challenge with an example.

 

Collection Module Functions

The challenge is probably best defined as “Where does Ansible load my module’s external functions from?”. In Windows or Linux operating systems we have well defined environment variables (PATH, LD_LIBRARY_PATH) that give the operating system a search path in the filesystem directories.

An example – actually in use in the triton.db2_zos collection:

  • The collection contains several modules that need to execute a Db2 for z/OS command through the TSO command processor:
    • db2_cmd.py
    • db2_get_bpsize.py

:

  • We’d like to create a single shared function – fn_db2_cmd – to perform this task

 

Where To Put Shared Functions

In the collection directory structure, modules that can be used by Ansible are placed in the “plugins/modules” path. Functions that can be called by these modules are generally shared in the “plugins/module_utils” path. This keeps their available scope limited to the collection modules and prevents them being accidentally made available to Ansible callers.

 

How To Reference Shared Functions In Collection Modules

To reference one of these functions, we need to use a specific route in the “ansible_collections” namespace – i.e.

ansible_collections.<col_ns>.<collection>.plugins.module_utils.<fn_module>

Where

  • <col_ns> = collection namespace
  • <collection> = collection name
  • <fn_module> is the name of the function module name

 

An Example

Returning to our example above, in the triton.db2_zos collection, we want to introduce a shared function module called fn_db2.py which contains a function fn_db2_cmd to execute Db2 for z/OS commands for us and return the results.

With the fn_db2.py shared function module saved in plugins/module_utils, the collection directory structure looks like this:

Ansible and Db2 for z/OS – Even More Fun with Collections

We want to use the fn_db2_cmd function in our Ansible modules (e.g. db2_cmd.py), so we have to import the function like this:

from ansible_collections.triton.db2_zos.plugins.module_utils.fn_db2 import fn_db2_cmd

Then we can call it in the usual way:

result = fn_db2_cmd(db2ssid,command)

 

Conclusions

This is a really simple way of implementing these functions with the proviso that we don’t want to expose them outside of the collection.

Ansible continues to gain popularity for its clean and simple approach to automating tasks – even on mainframes! Combined with IBM’s port of Python – including ZIIP offload – it provides a powerful way to implement tasks across the estate.