WORDS BY Tadej Borovšak
It has been almost half a year since the XLAB Steampunk and Red Hat Ansible Automation Platform teams developed the first version of the Red Hat Ansible Certified Content Collection for ServiceNow IT Service Management (ITSM). You may also want to read our ServiceNow introduction if you are not familiar with this already. So, let’s take a look at what is new since the last release.
We will skip most of the technical details in this post because, let us face it, talking about interactions between API pagination and filtering is not something many people enjoy. Instead, we will focus on the new things users can do using the current 1.2.0 version of this collection.
Attachment management
ServiceNow records (incidents, problems, change requests, etc.) may contain attachments, but the first version of the ServiceNow Collection did not expose this capability to Ansible Automation Platform users. We changed this in version 1.2.0 when we added the attachments parameter to all non-info modules.
Ansible users can now upload error logs and other artifacts when creating new incidents and other ServiceNow records. They can also add them later to existing ServiceNow records. For example, users might want to attach root cause analysis results when changing the state of the problem.
In the simplest case, attaching files to a record means listing them under the attachments parameter. The following example contains one such playbook task:
- name: Attach a file to a problem
servicenow.itsm.problem:
number: INC0123456
attachments:
- path: /path/to/screenshot.png
- path: /path/to/log.txt
We have also checked to ensure that change detection still works. If a file with a matching name is not yet attached to the record, we upload it. If the attachment already exists in ServiceNow, we only update it if the local and remote files differ.
It is also possible to rename the file during the upload by specifying the name of the remote file. And in cases where Ansible cannot detect the file type from the extension, we can also supply that information manually:
- name: Attach a file to a problem
servicenow.itsm.problem:
number: INC0123456
attachments:
- path: /path/to/error.log
type: text/plain
name: specific-error.log
Filtering records
Until now, info modules from this ServiceNow collection operated in an all-or-nothing fashion. For example, users could retrieve a single record or list all records. And so, in this 1.2.0 release, we have made things more flexible.
All info modules gained a new query parameter that allows users to retrieve a subset of records. Users write the query expression using a domain-specific language (DSL) that exposes advanced filtering capabilities in a user-friendly way. The query DSL supports all operators listed in the ServiceNow documentation.
For example, the next task will retrieve all incidents that contain SAP in their short description:
- servicenow.itsm.incident_info:
query:
- short_description: LIKE SAP
It is also possible to combine multiple conditions. The following sample shows how users could fetch only SAP incidents that the admins are already working on:
- servicenow.itsm.incident_info:
query:
- short_description: LIKE SAP
state: = in_progress
Query DSL also supports combining multiple filters into one. So, for example, if users would like to retrieve resolved problems reported by two different people, we can do it in one task:
- servicenow.itsm.incident_info:
query:
- caller: = person.one
state: = resolved
- caller: = person.two
state: = resolved
Constructed inventory features
The first version of the inventory plugin offered quite a few options for filtering and grouping, but there were two areas it did not address:
- It did not allow us to construct custom variables from the data in the Configuration Management Database (CMDB).
- Its configuration options were slightly different from those that the majority of other inventory plugins use.
So we adopted the standard options while adding one ServiceNow-specific additional option. This additional option allows Ansible users to filter CMDB items using the same query DSL we discussed previously.
This is a relatively short example that demonstrates most of the options would look like:
---
plugin: servicenow.itsm.now
table: cmdb_ci_ec2_instance
columns:
- ip_address
- name
- vm_inst_id
query:
- operational_status: = 1
fqdn: ISNOTEMPTY
manufacturer: STARTSWITH Cisco
keyed_groups:
- key: environment
prefix: env_
separator: ""
groups:
development: "'devel' in environment"
compose:
ansible_host: fqdn
For more information about available options, you can consult the constructed reference documentation.
Updating multiple CMDB items at once
The newly introduced batch module does not add new capabilities. Users can update as many CMDB items as they want using the existing servicenow.itsm.configuration_item module and Ansible looping. Considering that looping in Ansible can be slower and that each loop iteration needs to establish a new ServiceNow connection, we made some optimizations.
For example, this is the "old" way of updating a specific configuration item:
---
- name: Update a single CMDB item
hosts: localhost
gather_facts: false
vars:
dataset:
- id: i-0af01c0123456789a
address_ipv4: 1.2.3.4
mac: aa:bb:cc:dd:ee:ff
tasks:
- name: Retrieve specific CMDB item
servicenow.itsm.configuration_item_info:
sys_class_name: cmdb_ci_ec2_instance
query:
- vm_inst_id: = {{ dataset.0.id }}
register: vm
- name: Make sure we only grabbed one instance
ansible.builtin.assert:
that:
- vm.records | length == 1
- name: Update CMDB item with fresh data
servicenow.itsm.configuration_item:
sys_class_name: cmdb_ci_ec2_instance
sys_id: "{{ vm.records.0.sys_id }}"
ip_address: "{{ dataset.0.address_ipv4 }}"
mac_address: "{{ dataset.0.mac }}"
With the new batch module, users can write this using a single task:
---
- name: Update a single CMDB item
hosts: localhost
gather_facts: false
vars:
dataset:
- id: i-0af01c0123456789a
address_ipv4: 1.2.3.4
mac: aa:bb:cc:dd:ee:ff
tasks:
- name: Update data in CMDB
servicenow.itsm.configuration_item_batch:
sys_class_name: cmdb_ci_ec2_instance
id_column_set: vm_inst_id
dataset: "{{ dataset }}"
map:
vm_inst_id: id
ip_address: address_ipv4
mac_address: mac
Updating multiple items using the "old" method will most likely need some clever tricks like looping over the include_tasks
invocation. However, users do not require such tricks when using the batch module. They can add as many items they need to the dataset and call it a day.
Combining things for the win
Filtering support in info modules is useful on its own, and working with transformations in the batch module can be surprisingly effective. But this is not the primary reason why we added those individual features. The real power is realized when we start combining them.
For example, let us have a look at the following playbook that will refresh information about the AWS EC2 instances stored in the ServiceNow CMDB that do not have IP address stored:
---
- name: Update a single CMDB item
hosts: localhost
gather_facts: false
vars:
dataset:
- id: i-0af01c0123456789a
address_ipv4: 1.2.3.4
mac: aa:bb:cc:dd:ee:ff
tasks:
- name: Retrieve specific CMDB item
servicenow.itsm.configuration_item_info:
sys_class_name: cmdb_ci_ec2_instance
query:
- vm_inst_id: = {{ dataset.0.id }}
register: vm
- name: Make sure we only grabbed one instance
ansible.builtin.assert:
that:
- vm.records | length == 1
- name: Update CMDB item with fresh data
servicenow.itsm.configuration_item:
sys_class_name: cmdb_ci_ec2_instance
sys_id: "{{ vm.records.0.sys_id }}"
ip_address: "{{ dataset.0.address_ipv4 }}"
mac_address: "{{ dataset.0.mac }}"
With the new batch module at their disposal, users can write this using a single task:
---
- name: Update CMDB data
hosts: localhost
gather_facts: false
tasks:
- name: Get all EC2 instances with no IP address
servicenow.itsm.configuration_item_info:
sys_class_name: cmdb_ci_ec2_instance
query:
- ip_address: ISEMPTY
register: snow_instances
- name: Fetch information about instances from AWS
amazon.aws.ec2_instance_info:
instance_ids: "{{ snow_instances | map(attribute='vm_inst_id') | list }}"
register: ec2_instances
- name: Update CMDB with data from AWS
servicenow.itsm.configuration_item_batch:
sys_class_name: cmdb_ci_ec2_instance
id_column_set: vm_inst_id
dataset: "{{ ec2_instances.instances }}"
map:
vm_inst_id: instance_id
ip_address: public_ip_adress
name: tags.Name
And so, now you are aware of the newest capabilities in this collection. Give them a try. You can download this new certified collection in the automation hub if you subscribe to Ansible Automation Platform. If you want to learn more about these features and see how you can drive your automation by integrating Ansible Automation Platform into your existing ServiceNow environment, sign up for upcoming webinar organized in collaboration with Devoteam.
Top comments (0)