From d1fc2702ec916cf6dbdbf878b880dd3c28caf62b Mon Sep 17 00:00:00 2001 From: John Westcott IV <32551173+john-westcott-iv@users.noreply.github.com> Date: Thu, 28 Jul 2022 12:16:47 -0400 Subject: [PATCH] Adding subscriptions module and adding pool_id to license module (#12560) --- awx_collection/meta/runtime.yml | 1 + awx_collection/plugins/modules/license.py | 31 ++++-- .../plugins/modules/subscriptions.py | 101 ++++++++++++++++++ awx_collection/test/awx/test_completeness.py | 1 + 4 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 awx_collection/plugins/modules/subscriptions.py diff --git a/awx_collection/meta/runtime.yml b/awx_collection/meta/runtime.yml index e611902ccf..56b6c54bb7 100644 --- a/awx_collection/meta/runtime.yml +++ b/awx_collection/meta/runtime.yml @@ -33,6 +33,7 @@ action_groups: - role - schedule - settings + - subscriptions - team - token - user diff --git a/awx_collection/plugins/modules/license.py b/awx_collection/plugins/modules/license.py index 5cea090d5e..ed9b937274 100644 --- a/awx_collection/plugins/modules/license.py +++ b/awx_collection/plugins/modules/license.py @@ -23,7 +23,7 @@ options: manifest: description: - file path to a Red Hat subscription manifest (a .zip file) - required: True + required: False type: str force: description: @@ -31,6 +31,11 @@ options: unlicensed or trial licensed. When force=true, the license is always applied. type: bool default: 'False' + pool_id: + description: + - Red Hat or Red Hat Satellite pool_id to attach to + required: False + type: str state: description: - Desired state of the resource. @@ -47,6 +52,10 @@ EXAMPLES = ''' license: manifest: "/tmp/my_manifest.zip" +- name: Attach to a pool + license: + pool_id: 123456 + - name: Remove license license: state: absent @@ -61,12 +70,14 @@ def main(): module = ControllerAPIModule( argument_spec=dict( manifest=dict(type='str', required=False), + pool_id=dict(type='str', required=False), force=dict(type='bool', default=False), state=dict(choices=['present', 'absent'], default='present'), ), required_if=[ - ['state', 'present', ['manifest']], + ['state', 'present', ['manifest', 'pool_id'], True], ], + mutually_exclusive=[("manifest", "pool_id")], ) json_output = {'changed': False} @@ -77,11 +88,12 @@ def main(): module.delete_endpoint('config') module.exit_json(**json_output) - try: - with open(module.params.get('manifest'), 'rb') as fid: - manifest = base64.b64encode(fid.read()) - except OSError as e: - module.fail_json(msg=str(e)) + if module.params.get('manifest', None): + try: + with open(module.params.get('manifest'), 'rb') as fid: + manifest = base64.b64encode(fid.read()) + except OSError as e: + module.fail_json(msg=str(e)) # Check if Tower is already licensed config = module.get_endpoint('config')['json'] @@ -104,7 +116,10 @@ def main(): # Do the actual install, if we need to if perform_install: json_output['changed'] = True - module.post_endpoint('config', data={'manifest': manifest.decode()}) + if module.params.get('manifest', None): + module.post_endpoint('config', data={'manifest': manifest.decode()}) + else: + module.post_endpoint('config/attach', data={'pool_id': module.params.get('pool_id')}) module.exit_json(**json_output) diff --git a/awx_collection/plugins/modules/subscriptions.py b/awx_collection/plugins/modules/subscriptions.py new file mode 100644 index 0000000000..4cb2506af9 --- /dev/null +++ b/awx_collection/plugins/modules/subscriptions.py @@ -0,0 +1,101 @@ +#!/usr/bin/python +# coding: utf-8 -*- + +# (c) 2019, John Westcott IV +# 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: subscriptions +author: "John Westcott IV (@john-westcott-iv)" +short_description: Get subscription list +description: + - Get subscriptions available to Automation Platform Controller. See + U(https://www.ansible.com/tower) for an overview. +options: + username: + description: + - Red Hat or Red Hat Satellite username to get available subscriptions. + - The credentials you use will be stored for future use in retrieving renewal or expanded subscriptions + required: True + type: str + password: + description: + - Red Hat or Red Hat Satellite password to get available subscriptions. + - The credentials you use will be stored for future use in retrieving renewal or expanded subscriptions + required: True + type: str + filters: + description: + - Client side filters to apply to the subscriptions. + - For any entries in this dict, if there is a corresponding entry in the subscription it must contain the value from this dict + - Note This is a client side search, not an API side search + required: False + type: dict +extends_documentation_fragment: awx.awx.auth +''' + +RETURN = ''' +subscriptions: + description: dictionary containing information about the subscriptions + returned: If login succeeded + type: dict +''' + +EXAMPLES = ''' +- name: Get subscriptions + subscriptions: + username: "my_username" + password: "My Password" + +- name: Get subscriptions with a filter + subscriptions: + username: "my_username" + password: "My Password" + filters: + product_name: "Red Hat Ansible Automation Platform" + support_level: "Self-Support" +''' + +from ..module_utils.controller_api import ControllerAPIModule + + +def main(): + + module = ControllerAPIModule( + argument_spec=dict( + username=dict(type='str', required=True), + password=dict(type='str', no_log=True, required=True), + filters=dict(type='dict', required=False, default={}), + ), + ) + + json_output = {'changed': False} + + # Check if Tower is already licensed + post_data = { + 'subscriptions_password': module.params.get('password'), + 'subscriptions_username': module.params.get('username'), + } + all_subscriptions = module.post_endpoint('config/subscriptions', data=post_data)['json'] + json_output['subscriptions'] = [] + for subscription in all_subscriptions: + add = True + for key in module.params.get('filters').keys(): + if subscription.get(key, None) and module.params.get('filters')[key] not in subscription.get(key): + add = False + if add: + json_output['subscriptions'].append(subscription) + + module.exit_json(**json_output) + + +if __name__ == '__main__': + main() diff --git a/awx_collection/test/awx/test_completeness.py b/awx_collection/test/awx/test_completeness.py index b3c4163f3b..75e6bff29f 100644 --- a/awx_collection/test/awx/test_completeness.py +++ b/awx_collection/test/awx/test_completeness.py @@ -41,6 +41,7 @@ no_endpoint_for_module = [ 'workflow_template', 'ad_hoc_command_wait', 'ad_hoc_command_cancel', + 'subscriptions', # Subscription deals with config/subscriptions ] # Global module parameters we can ignore