From 1db6d5598abb465738a7176d8b7c64a7143c6628 Mon Sep 17 00:00:00 2001 From: saranyasridharan Date: Sat, 16 Feb 2019 06:38:55 +0530 Subject: [PATCH] Adding custom module to get PID of the process (#50896) --- lib/ansible/modules/system/pids.py | 74 +++++++++++++++++++ test/integration/targets/pids/aliases | 1 + .../targets/pids/files/obtainpid.sh | 3 + test/integration/targets/pids/tasks/main.yml | 59 +++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 lib/ansible/modules/system/pids.py create mode 100644 test/integration/targets/pids/aliases create mode 100644 test/integration/targets/pids/files/obtainpid.sh create mode 100644 test/integration/targets/pids/tasks/main.yml diff --git a/lib/ansible/modules/system/pids.py b/lib/ansible/modules/system/pids.py new file mode 100644 index 00000000000..fe861998b44 --- /dev/null +++ b/lib/ansible/modules/system/pids.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# Copyright: (c) 2019, Saranya Sridharan +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = ''' +module: pids +version_added: 2.8 +description: "Retrieves a list of PIDs of given process name in Ansible controller/controlled machines.Returns an empty list if no process in that name exists." +short_description: "Retrieves process IDs list if the process is running otherwise return empty list" +author: + - Saranya Sridharan (@saranyasridharan) +requirements: + - psutil(python module) +options: + name: + description: the name of the process you want to get PID for. + required: true + type: str +''' + +EXAMPLES = ''' +# Pass the process name +- name: Getting process IDs of the process + pids: + name: python + register: pids_of_python + +- name: Printing the process IDs obtained + debug: + msg: "PIDS of python:{{pids_of_python.pids|join(',')}}" +''' + +RETURN = ''' +pids: + description: Process IDs of the given process + returned: list of none, one, or more process IDs + type: list + sample: [100,200] +''' + +from ansible.module_utils.basic import AnsibleModule +try: + import psutil + HAS_PSUTIL = True +except ImportError: + HAS_PSUTIL = False + + +def get_pid(name): + return [p.info['pid'] for p in psutil.process_iter(attrs=['pid', 'name']) if name == p.info['name']] + + +def main(): + module = AnsibleModule( + argument_spec=dict( + name=dict(required=True, type="str"), + ), + supports_check_mode=True, + ) + if not HAS_PSUTIL: + module.fail_json(msg="Missing required 'psutil' python module. Try installing it with: pip install psutil") + name = module.params["name"] + response = dict(pids=get_pid(name)) + module.exit_json(**response) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/pids/aliases b/test/integration/targets/pids/aliases new file mode 100644 index 00000000000..b59832142f2 --- /dev/null +++ b/test/integration/targets/pids/aliases @@ -0,0 +1 @@ +shippable/posix/group3 diff --git a/test/integration/targets/pids/files/obtainpid.sh b/test/integration/targets/pids/files/obtainpid.sh new file mode 100644 index 00000000000..8e4f4d37661 --- /dev/null +++ b/test/integration/targets/pids/files/obtainpid.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +"$1" 100 & +echo "$!" > "$2" diff --git a/test/integration/targets/pids/tasks/main.yml b/test/integration/targets/pids/tasks/main.yml new file mode 100644 index 00000000000..c7a5963483e --- /dev/null +++ b/test/integration/targets/pids/tasks/main.yml @@ -0,0 +1,59 @@ +# Test code for the pids module +# Copyright: (c) 2019, Saranya Sridharan +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +- name: "Installing the psutil module" + pip: + name: psutil + +- name: "Checking the empty result" + pids: + name: "blahblah" + register: emptypids + +- name: "Verify that the list of Process IDs (PIDs) returned is empty" + assert: + that: + - emptypids is not changed + - emptypids.pids == [] + +- name: "Picking a random process name" + command: "echo 'some-random-long-name-{{ 99999999 | random }}'" + register: random_name + +- name: "finding the 'sleep' binary" + command: which sleep + register: find_sleep + +- name: "copying 'sleep' binary" + copy: + src: "{{ find_sleep.stdout }}" + dest: "{{ output_dir }}/{{ random_name.stdout }}" + mode: "0777" + +- name: "Running the copy of 'sleep' binary" + command: "sh {{ role_path }}/files/obtainpid.sh '{{ output_dir }}/{{ random_name.stdout }}' '{{ output_dir }}/obtainpid.txt'" + + async: 100 + poll: 0 + +- name: "Checking the process IDs (PIDs) of sleep binary" + pids: + name: "{{ random_name.stdout }}" + register: pids + +- name: "Checking that exact non-substring matches are required" + pids: + name: "{{ random_name.stdout[0:5] }}" + register: exactpidmatch + +- name: "Reading pid from the file" + slurp: + src: "{{ output_dir }}/obtainpid.txt" + register: newpid + +- name: "Verify that the Process IDs (PIDs) returned is not empty and also equal to the PIDs obtained in console" + assert: + that: + - "pids.pids | join(' ') == newpid.content | b64decode | trim" + - "pids.pids | length > 0" + - "exactpidmatch.pids == []"