Datadope Discovery Part 2 – Generating support for new software

 Reading time: 5

Introduction

As we explored in part 1 of the blog, Datadope Discovery’s Ansible collection offers a set of tools that make it easy to extract information from servers. Now, we are going to leverage those tools to add support for a new software typology (in this case, telegraf).

Preliminary analysis

Before elaborating the tasks that allow to extract the information of interest, it is important to make a previous analysis. For example, we can see in the list of supported software that telegraf has basic support. This lets us know if it is installed on the machine, but does not give us any additional information by running specific tasks.

We can also analyze an instance of telegraf running on a machine to try to get more information. For example, by running:

				
					ps aux | grep telegraf
				
			

We get:

				
					root     20827  0.9  1.9 1476720 75108 ?       Ssl  mar23 1071:48 /usr/bin/telegraf --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d
				
			

This already gives us some relevant information, such as that telegraf provides its configuration file with the –config parameter or that, looking at the configuration file located in /etc/telegraf/telegraf.conf, telegraf’s configuration is in TOML format.

This preliminary analysis provides us with a list of tasks that will allow us to elaborate our new extraction:

  • Extend the definition of telegraf to run our custom tasks.
  • Extract the value of the –config parameter if it is in the cmdline of the detected process.
  • Store the path to the configuration file.
  • Validate that you have access to the configuration file.
  • Read the configuration file.
  • Store the configuration file.

Implementation

Execution of custom tasks

To extend the telegraf definition, and include our custom tasks, it is necessary to update the software_discovery__software_list variable replacing the telegraf entry or rewrite the entire variable indicating only the new telegraf entry, whichever is more appropriate to our situation. In our case, we are going to redefine the telegraf entry leaving it exactly as it comes originally, but adding a path to the file where we are going to define our new custom tasks:

				
					- name: Telegraf
  cmd_regexp: '/usr/bin/telegraf'
  pkg_regexp: 'telegraf|iometrics-agent'
  process_type: parent
  return_children: false
  return_packages: true
  custom_tasks:
    - name: Include Telegraf specific plugins
      include_tasks:
        file: "/tmp/telegraf_tasks.yaml"

				
			

Extraction of the -config parameter

Performing the extraction of the –config parameter requires considering several possibilities. On the one hand, the configuration parameter may be given as –config or –config–. On the other hand, it is important to consider that the parameter may not be defined and that the execution of the regular expression could cause a failure.

The way to make an implementation that meets the above requirements is to elaborate a task that is controlled for failure and that tries to extract the configuration parameter and register it, making use of a regex that supports both configuration parameters.

On the other hand, it is important to consider that the parameter may not be defined and that the execution of the regular expression could cause a failure.

A possible improvement for the text would be the following implementation: execute a regex that meets the above conditions, access the first regex extraction group and record the result in the instance’s _config_path variable (__instance__._config_path) using the set_instance_fact module, while controlling possible errors that may arise (for example, when accessing the group of a regex with no result) with the ignore_errors: yes parameter of the task:

				
					- name: Get _config_path regex
  set_instance_fact:
    _config_path: "<< __instance__.process.cmdline | regex_search('-?-config ([\\S]+)', '\\1' ,ignorecase=True) | first  >>"
  ignore_errors: yes

				
			

NOTE

It´s important to be careful with the inclusion of double escapes (\\) in the face of templating, as this may lead to errors.

Storage of the extracted parameter

In case you have been able to register the variable, it is advisable to store it in the file key of the instance. This can be easily done with the following task, which will also take care of separating the file from its parent directory:

				
					- name: Save _config_path in files
  add_file_info:
    path: "<< __instance__._config_path | dirname >>"
    name: "<< __instance__._config_path | basename >>"
    type: 'config'
    subtype: 'config_file'
  when: __instance__._config_path is defined

				
			

NOTE

Note that to use Datadope Discovery’s own variables, such __instance__, it is necessary to use << and >> for the templating escaping<< y >>, instead of {{ y }}. In case you want to use directly the Ansible templating (to which delegates the Datadope Discovery one), you can use directly {{ and }} as usual.

Permissions validation

The stat module allows us to verify if we have access to a file by simply running the module and logging its result. For example:

				
					- name: Check if _config_path is accessible
  stat:
    path: "<< __instance__._config_path >>"
  register: stat_result
  when: __instance__._config_path is defined

				
			

NOTE

The results of register parameters of the tasks are not stored as instance variables, so there is no need to delete them when they are no longer needed.

Reading the configuration file

Once we have validated if we have access to the configuration file, we will be able to read this file in case the result has been positive. To do this reading, we can use the module read_remote_file:

				
					- name: Read config file
  read_remote_file:
    file_path: "<< __instance__._config_path >>"
  register: _config_file
  when:
    - stat_result is not failed
    - stat_result is not skipped

				
			

NOTE

As the previous task had a when, it is important not only to validate if the task has failed, but also to check if the task has been skipped because the when was not fulfilled, which would cause a skipped: true.

Configuration file storage

If the reading of the configuration file did not cause any errors, the result can be stored in the configuration key of __instance__ using the set_instance_fact module:

				
					- name: Set configuration
  set_instance_fact:
    configuration: "<< _config_file.content >>"
  when:
    - _config_file is not failed
    - _config_file is not skipped

				
			

NOTE

As in the previous task, in this one also note that _config_file can be either failed or skipped, depending on whether the task failed or was skipped because of when.

Extra: Cleaning up variables.

Once we are not going to make use of temporary variables of the instance, it is advisable to delete them so that these variables are not included in the result. In this case, the only variable to delete would be _config_path, a task that can be performed using the del_instance_fact module:

				
					- name: Remove temporary vars
  del_instance_fact:
    - _config_path

				
			

NOTE

As mentioned above, the registers do not store the results in the instance, so it is not necessary to delete these results manually.

Result

The result of implementing all of the above is a custom task file named telegraf_tasks.yaml like the following:

				
					- name: Get _config_path regex
  set_instance_fact:
    _config_path: "<< __instance__.process.cmdline | regex_search('-?-config ([\\S]+)', '\\1' ,ignorecase=True) | first  >>"
  ignore_errors: yes

- name: Save _config_path in files
  add_file_info:
    path: "<< __instance__._config_path | dirname >>"
    name: "<< __instance__._config_path | basename >>"
    type: 'config'
    subtype: 'config_file'
  when: __instance__._config_path is defined

- name: Check if _config_path is accessible
  stat:
    path: "<< __instance__._config_path >>"
  register: stat_result
  when: __instance__._config_path is defined

- name: Read config file
  read_remote_file:
    file_path: "<< __instance__._config_path >>"
  register: _config_file
  when:
    - stat_result is not failed
    - stat_result is not skipped

- name: Set configuration
  set_instance_fact:
    configuration: "<< _config_file.content >>"
  when:
    - _config_file is not failed
    - _config_file is not skipped

- name: Remove temporary vars
  del_instance_fact:
    - _config_path

				
			

It will be supplemented by a playbook as included below, which includes the rewrite of the software definitions and a reference to the file described above:

				
					---
- hosts: all
  name: Execute role software_discovery
  become: yes
  vars:
    software_discovery__software_list:
      - name: Telegraf
        cmd_regexp: '/usr/bin/telegraf'
        pkg_regexp: 'telegraf|iometrics-agent'
        process_type: parent
        return_children: false
        return_packages: true
        custom_tasks:
          - name: Include Telegraf specific plugins
            include_tasks:
              file: "/tmp/telegraf_tasks.yaml"
  roles:
    - role: datadope.discovery.software_discovery

				
			

Conclusion

In this second part of the Datadope Discovery blog we have explained, as an example, how to use some of the tools offered by Datadope Discovery’s Ansible collection to extract information from a software, in this case Telegraf. The set of tools offered is very broad, being able to extract almost any information from a software running on a machine.

We encourage you to deepen the use of these tools using the resources provided and use them to extract information from more types of software, in addition to all those already provided directly from the collection. And that you can contribute to it, so that, between all of us, we can expand the catalog of software that the collection is able to discover.

Resources

Ansible Datadope Discovery Collection:
https://github.com/datadope-io/ansible_collection_discovery

Documentation on installing collections in ansible:
https://docs.ansible.com/ansible/latest/collections_guide/collections_installing.html

David Nieto Sanz
Ana Ramírez

Ana Ramírez

Did you find it interesting?

Leave a Reply

Your email address will not be published. Required fields are marked *

FOLLOW US

CATEGORIES

LATEST POST