Adding hosts bulk deletion feature (#14462)

* Adding hosts bulk deletion feature

Signed-off-by: Avi Layani <alayani@redhat.com>

* fix the type of the argument

Signed-off-by: Avi Layani <alayani@redhat.com>

* fixing activity_entry tracking

Signed-off-by: Avi Layani <alayani@redhat.com>

* Revert "fixing activity_entry tracking"

This reverts commit c8eab52c2ccc5abe215d56d1704ba1157e5fbbd0.
Since the bulk_delete is not related to an inventory, only hosts which
can be from different inventories.

* get only needed vars to reduce memory consumption

Signed-off-by: Avi Layani <alayani@redhat.com>

* filtering the data to reduce memory increase the number of queries

Signed-off-by: Avi Layani <alayani@redhat.com>

* update the activity stream for inventories

Signed-off-by: Avi Layani <alayani@redhat.com>

* fix the changes dict initialiazation

Signed-off-by: Avi Layani <alayani@redhat.com>

---------

Signed-off-by: Avi Layani <alayani@redhat.com>
This commit is contained in:
Avi Layani
2023-12-13 18:28:31 +02:00
committed by GitHub
parent 0d825a744b
commit df24cb692b
15 changed files with 498 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ action_groups:
- application
- bulk_job_launch
- bulk_host_create
- bulk_host_delete
- controller_meta
- credential_input_source
- credential

View File

@@ -0,0 +1,65 @@
#!/usr/bin/python
# coding: utf-8 -*-
# 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: bulk_host_delete
author: "Avi Layani (@Avilir)"
short_description: Bulk host delete in Automation Platform Controller
description:
- Single-request bulk host deletion in Automation Platform Controller.
- Provides a way to delete many hosts at once from inventories in Controller.
options:
hosts:
description:
- List of hosts id's to delete from inventory.
required: True
type: list
elements: int
extends_documentation_fragment: awx.awx.auth
'''
EXAMPLES = '''
- name: Bulk host delete
bulk_host_delete:
hosts:
- 1
- 2
'''
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(
hosts=dict(required=True, type='list', elements='int'),
)
# Create a module for ourselves
module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters
hosts = module.params.get('hosts')
# Delete the hosts
result = module.post_endpoint("bulk/host_delete", data={"hosts": hosts})
if result['status_code'] != 201:
module.fail_json(msg="Failed to delete hosts, see response for details", response=result)
module.json_output['changed'] = True
module.exit_json(**module.json_output)
if __name__ == '__main__':
main()

View File

@@ -45,3 +45,28 @@ def test_bulk_host_create(run_module, admin_user, inventory):
resp_hosts = inventory.hosts.all().values_list('name', flat=True)
for h in hosts:
assert h['name'] in resp_hosts
@pytest.mark.django_db
def test_bulk_host_delete(run_module, admin_user, inventory):
hosts = [dict(name="127.0.0.1"), dict(name="foo.dns.org")]
result = run_module(
'bulk_host_create',
{
'inventory': inventory.name,
'hosts': hosts,
},
admin_user,
)
assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result
resp_hosts_ids = list(inventory.hosts.all().values_list('id', flat=True))
result = run_module(
'bulk_host_delete',
{
'hosts': resp_hosts_ids,
},
admin_user,
)
assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result

View File

@@ -50,6 +50,7 @@ no_endpoint_for_module = [
extra_endpoints = {
'bulk_job_launch': '/api/v2/bulk/job_launch/',
'bulk_host_create': '/api/v2/bulk/host_create/',
'bulk_host_delete': '/api/v2/bulk/host_delete/',
}
# Global module parameters we can ignore

View File

@@ -0,0 +1,80 @@
---
- name: "Generate a random string for test"
set_fact:
test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
when: "test_id is not defined"
- name: "Generate a unique name"
set_fact:
bulk_inv_name: "AWX-Collection-tests-bulk_host_create-{{ test_id }}"
- name: "Get our collection package"
controller_meta:
register: "controller_meta"
- name: "Generate the name of our plugin"
set_fact:
plugin_name: "{{ controller_meta.prefix }}.controller_api"
- name: "Create an inventory"
inventory:
name: "{{ bulk_inv_name }}"
organization: "Default"
state: "present"
register: "inventory_result"
- name: "Bulk Host Create"
bulk_host_create:
hosts:
- name: "123.456.789.123"
description: "myhost1"
variables:
food: "carrot"
color: "orange"
- name: "example.dns.gg"
description: "myhost2"
enabled: "false"
inventory: "{{ bulk_inv_name }}"
register: "result"
- assert:
that:
- "result is not failed"
- name: "Get our collection package"
controller_meta:
register: "controller_meta"
- name: "Generate the name of our plugin"
set_fact:
plugin_name: "{{ controller_meta.prefix }}.controller_api"
- name: "Setting the inventory hosts endpoint"
set_fact:
endpoint: "inventories/{{ inventory_result.id }}/hosts/"
- name: "Get hosts information from inventory"
set_fact:
hosts_created: "{{ query(plugin_name, endpoint, return_objects=True) }}"
host_id_list: []
- name: "Extract host IDs from hosts information"
set_fact:
host_id_list: "{{ host_id_list + [item.id] }}"
loop: "{{ hosts_created }}"
- name: "Bulk Host Delete"
bulk_host_delete:
hosts: "{{ host_id_list }}"
register: "result"
- assert:
that:
- "result is not failed"
# cleanup
- name: "Delete inventory"
inventory:
name: "{{ bulk_inv_name }}"
organization: "Default"
state: "absent"