summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--awx_collection/plugins/module_utils/controller_api.py2
-rw-r--r--awx_collection/plugins/modules/instance.py148
-rw-r--r--awx_collection/test/awx/test_completeness.py1
-rw-r--r--awx_collection/tests/integration/targets/instance/tasks/main.yml55
4 files changed, 205 insertions, 1 deletions
diff --git a/awx_collection/plugins/module_utils/controller_api.py b/awx_collection/plugins/module_utils/controller_api.py
index 567a753c8f..50d10f8104 100644
--- a/awx_collection/plugins/module_utils/controller_api.py
+++ b/awx_collection/plugins/module_utils/controller_api.py
@@ -903,6 +903,8 @@ class ControllerAPIModule(ControllerModule):
item_name = existing_item['identifier']
elif item_type == 'credential_input_source':
item_name = existing_item['id']
+ elif item_type == 'instance':
+ item_name = existing_item['hostname']
else:
item_name = existing_item['name']
item_id = existing_item['id']
diff --git a/awx_collection/plugins/modules/instance.py b/awx_collection/plugins/modules/instance.py
new file mode 100644
index 0000000000..a20b6c831c
--- /dev/null
+++ b/awx_collection/plugins/modules/instance.py
@@ -0,0 +1,148 @@
+#!/usr/bin/python
+# coding: utf-8 -*-
+
+
+# (c) 2022 Red Hat, Inc.
+# 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: instance
+author: "Rick Elrod (@relrod)"
+version_added: "4.3.0"
+short_description: create, update, or destroy Automation Platform Controller instances.
+description:
+ - Create, update, or destroy Automation Platform Controller instances. See
+ U(https://www.ansible.com/tower) for an overview.
+options:
+ hostname:
+ description:
+ - Hostname of this instance.
+ required: True
+ type: str
+ capacity_adjustment:
+ description:
+ - Capacity adjustment (0 <= capacity_adjustment <= 1)
+ required: False
+ type: float
+ enabled:
+ description:
+ - If true, the instance will be enabled and used.
+ required: False
+ type: bool
+ default: True
+ managed_by_policy:
+ description:
+ - Managed by policy
+ required: False
+ default: True
+ type: bool
+ node_type:
+ description:
+ - Role that this node plays in the mesh.
+ choices:
+ - control
+ - execution
+ - hybrid
+ - hop
+ required: False
+ type: str
+ default: execution
+ node_state:
+ description:
+ - Indicates the current life cycle stage of this instance.
+ choices:
+ - provisioning
+ - provision-fail
+ - installed
+ - ready
+ - unavailable
+ - deprovisioning
+ - deprovision-fail
+ required: False
+ default: installed
+ type: str
+ listener_port:
+ description:
+ - Port that Receptor will listen for incoming connections on.
+ required: False
+ default: 27199
+ type: int
+extends_documentation_fragment: awx.awx.auth
+'''
+
+EXAMPLES = '''
+- name: Create an instance
+ awx.awx.instance:
+ hostname: my-instance.prod.example.com
+ capacity_adjustment: 0.4
+ listener_port: 31337
+
+- name: Deprovision the instance
+ awx.awx.instance:
+ hostname: my-instance.prod.example.com
+ node_state: deprovisioning
+'''
+
+from ..module_utils.controller_api import ControllerAPIModule
+
+
+def main():
+ # Any additional arguments that are not fields of the item can be added here
+ argument_spec = dict(
+ hostname=dict(required=True),
+ capacity_adjustment=dict(type='float'),
+ enabled=dict(type='bool'),
+ managed_by_policy=dict(type='bool'),
+ node_type=dict(type='str', choices=['control', 'execution', 'hybrid', 'hop']),
+ node_state=dict(type='str', choices=['provisioning', 'provision-fail', 'installed', 'ready', 'unavailable', 'deprovisioning', 'deprovision-fail']),
+ listener_port=dict(type='int'),
+ )
+
+ # Create a module for ourselves
+ module = ControllerAPIModule(argument_spec=argument_spec)
+
+ # Extract our parameters
+ hostname = module.params.get('hostname')
+ capacity_adjustment = module.params.get('capacity_adjustment')
+ enabled = module.params.get('enabled')
+ managed_by_policy = module.params.get('managed_by_policy')
+ node_type = module.params.get('node_type')
+ node_state = module.params.get('node_state')
+ listener_port = module.params.get('listener_port')
+
+ # Attempt to look up an existing item based on the provided data
+ existing_item = module.get_one('instances', name_or_id=hostname)
+
+ # Create the data that gets sent for create and update
+ new_fields = {'hostname': hostname}
+ if capacity_adjustment is not None:
+ new_fields['capacity_adjustment'] = capacity_adjustment
+ if enabled is not None:
+ new_fields['enabled'] = enabled
+ if managed_by_policy is not None:
+ new_fields['managed_by_policy'] = managed_by_policy
+ if node_type is not None:
+ new_fields['node_type'] = node_type
+ if node_state is not None:
+ new_fields['node_state'] = node_state
+ if listener_port is not None:
+ new_fields['listener_port'] = listener_port
+
+ module.create_or_update_if_needed(
+ existing_item,
+ new_fields,
+ endpoint='instances',
+ item_type='instance',
+ )
+
+
+if __name__ == '__main__':
+ main()
diff --git a/awx_collection/test/awx/test_completeness.py b/awx_collection/test/awx/test_completeness.py
index 93ddd52fea..43e225e4b8 100644
--- a/awx_collection/test/awx/test_completeness.py
+++ b/awx_collection/test/awx/test_completeness.py
@@ -82,7 +82,6 @@ needs_development = ['inventory_script', 'instance']
needs_param_development = {
'host': ['instance_id'],
'workflow_approval': ['description', 'execution_environment'],
- 'instances': ['capacity_adjustment', 'enabled', 'hostname', 'ip_address', 'managed_by_policy', 'node_state', 'node_type'],
}
# -----------------------------------------------------------------------------------------------------------
diff --git a/awx_collection/tests/integration/targets/instance/tasks/main.yml b/awx_collection/tests/integration/targets/instance/tasks/main.yml
new file mode 100644
index 0000000000..4d5a596971
--- /dev/null
+++ b/awx_collection/tests/integration/targets/instance/tasks/main.yml
@@ -0,0 +1,55 @@
+---
+- name: Generate hostnames
+ set_fact:
+ hostname1: "AWX-Collection-tests-instance1.{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}.example.com"
+ hostname2: "AWX-Collection-tests-instance2.{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}.example.com"
+ hostname3: "AWX-Collection-tests-instance3.{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}.example.com"
+ register: facts
+
+- name: Show hostnames
+ debug:
+ var: facts
+
+- block:
+ - name: Create an instance
+ awx.awx.instance:
+ hostname: "{{ item }}"
+ with_items:
+ - "{{ hostname1 }}"
+ - "{{ hostname2 }}"
+ register: result
+
+ - assert:
+ that:
+ - result is changed
+
+ - name: Create an instance with non-default config
+ awx.awx.instance:
+ hostname: "{{ hostname3 }}"
+ capacity_adjustment: 0.4
+ listener_port: 31337
+ register: result
+
+ - assert:
+ that:
+ - result is changed
+
+ - name: Update an instance
+ awx.awx.instance:
+ hostname: "{{ hostname1 }}"
+ capacity_adjustment: 0.7
+ register: result
+
+ - assert:
+ that:
+ - result is changed
+
+ always:
+ - name: Deprovision the instances
+ awx.awx.instance:
+ hostname: "{{ item }}"
+ node_state: deprovisioning
+ with_items:
+ - "{{ hostname1 }}"
+ - "{{ hostname2 }}"
+ - "{{ hostname3 }}"