Skip to content

Commit

Permalink
make name optional to delete all resources for the specified resource…
Browse files Browse the repository at this point in the history
… type (#517)

make name optional to delete all resources for the specified resource type

SUMMARY

closes #504
k8s module should allow deleting all namespace resources for the specified resource type.

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

k8s
ADDITIONAL INFORMATION


Delete all Pods from namespace test

- k8s:
    namespace: test
    kind: Pod
    api_version: v1
    delete_all: true
    state: absent

Reviewed-by: Gonéri Le Bouder <goneri@lebouder.net>
Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Bikouo Aubin
  • Loading branch information
abikouo authored Mar 23, 2023
1 parent 09a3c83 commit 151ed82
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 5 deletions.
3 changes: 3 additions & 0 deletions changelogs/fragments/517-k8s-make-name-optional.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- k8s - add new option delete_all to support deletion of all resources when state is set to absent. (https://github.com/ansible-collections/kubernetes.core/issues/504)
45 changes: 40 additions & 5 deletions plugins/module_utils/k8s/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,51 @@ def _prepend_resource_info(resource, msg):
return [_prepend_resource_info(resource, msg) for msg in warnings + errors]


def get_definitions(svc, params):
try:
definitions = create_definitions(params)
except Exception as e:
msg = "Failed to load resource definition: {0}".format(e)
raise CoreException(msg) from e

delete_all = params.get("delete_all")
src = params.get("src")
resource_definition = params.get("resource_definition")
name = params.get("name")
state = params.get("state")

if (
delete_all
and state == "absent"
and name is None
and resource_definition is None
and src is None
):
# Delete all resources in the namespace for the specified resource type
if params.get("kind") is None:
raise CoreException(
"'kind' option is required to specify the resource type."
)

resource = svc.find_resource(
params.get("kind"), params.get("api_version"), fail=True
)
definitions = svc.retrieve_all(
resource,
params.get("namespace"),
params.get("label_selectors"),
)

return definitions


def run_module(module) -> None:
results = []
changed = False
client = get_api_client(module)
svc = K8sService(client, module)
try:
definitions = create_definitions(module.params)
except Exception as e:
msg = "Failed to load resource definition: {0}".format(e)
raise CoreException(msg) from e

definitions = get_definitions(svc, module.params)

for definition in definitions:
result = {"changed": False, "result": {}}
Expand Down
24 changes: 24 additions & 0 deletions plugins/module_utils/k8s/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,30 @@ def retrieve(self, resource: Resource, definition: Dict) -> ResourceInstance:

return existing

def retrieve_all(
self, resource: Resource, namespace: str, label_selectors: List[str] = None
) -> List[Dict]:
definitions: List[ResourceInstance] = []

try:
params = dict(namespace=namespace)
if label_selectors:
params["label_selector"] = ",".join(label_selectors)
resource_list = self.client.get(resource, **params)
for item in resource_list.items:
existing = self.client.get(
resource, name=item.metadata.name, namespace=namespace
)
definitions.append(existing.to_dict())
except (NotFoundError, MethodNotAllowedError):
pass
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to retrieve requested object: {0}".format(reason)
raise CoreException(msg) from e

return definitions

def find(
self,
kind: str,
Expand Down
22 changes: 22 additions & 0 deletions plugins/modules/k8s.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,19 @@
- When set to True, server-side apply will force the changes against conflicts.
type: bool
default: False
delete_all:
description:
- When this option is set to I(true) and I(state=absent),
module will delete all resources of the specified resource type in the requested namespace.
- Ignored when C(state) is not set to I(absent) or when one of (src),
C(name) or C(resource_definition) is provided.
- Parameter C(kind) is required to use this option.
- This parameter can be used with C(label_selectors) to restrict the resources to be deleted.
type: bool
default: false
version_added: 2.5.0
aliases:
- all
requirements:
- "python >= 3.6"
Expand Down Expand Up @@ -343,6 +356,14 @@
apply: yes
server_side_apply:
field_manager: ansible
# Delete all Deployment from specified namespace
- name: Delete all Deployment from specified namespace
kubernetes.core.k8s:
api_version: apps/v1
namespace: testing
kind: Deployment
delete_all: true
"""

RETURN = r"""
Expand Down Expand Up @@ -450,6 +471,7 @@ def argspec():
argument_spec["server_side_apply"] = dict(
type="dict", default=None, options=server_apply_spec()
)
argument_spec["delete_all"] = dict(type="bool", default=False, aliases=["all"])

return argument_spec

Expand Down
70 changes: 70 additions & 0 deletions tests/integration/targets/k8s_delete/files/deployments.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-d
labels:
context: ansible
spec:
replicas: 1
selector:
matchLabels:
context: ansible
template:
metadata:
labels:
context: ansible
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: openjdk-d
labels:
context: ansible
spec:
replicas: 2
selector:
matchLabels:
context: ansible
template:
metadata:
labels:
context: ansible
spec:
containers:
- name: openjdk
image: openjdk:17
command:
- /bin/sh
- -c
- while true;do date;sleep 5; done
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: alpine-d
labels:
context: ansible
spec:
replicas: 3
selector:
matchLabels:
context: ansible
template:
metadata:
labels:
context: ansible
spec:
containers:
- name: alpine
image: alpine
command:
- /bin/sh
- -c
- while true;do date;sleep 5; done
71 changes: 71 additions & 0 deletions tests/integration/targets/k8s_delete/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,77 @@
that:
- _result.resources | length == 0

# test deletion using delete_all=true
- name: Create deployments
k8s:
namespace: "{{ test_namespace }}"
src: files/deployments.yaml
wait: true
register: result

- name: Trying to delete deployments without name and label_selectors and select_all=false
k8s:
kind: Deployment
api_version: apps/v1
namespace: "{{ test_namespace }}"
state: absent
register: _delete

- name: Ensure Deployment were not deleted
assert:
that:
- _delete is not changed

- name: Validate that Deployment still exist
k8s_info:
kind: Deployment
api_version: apps/v1
namespace: "{{ test_namespace }}"
label_selectors:
- context=ansible
register: _deployment
failed_when: _deployment.resources | length == 0

- name: Trying to delete using delete_all=true but missing kind option
k8s:
api_version: apps/v1
namespace: "{{ test_namespace }}"
delete_all: true
state: absent
register: _delete
ignore_errors: true

- name: assert task failed with proper message
assert:
that:
- _delete is failed
- _delete.msg == "'kind' option is required to specify the resource type."

- name: Trying to delete deployments without name and label_selectors and delete_all=true
k8s:
kind: Deployment
api_version: apps/v1
namespace: "{{ test_namespace }}"
delete_all: true
wait: true
state: absent
register: _delete

- name: Ensure Deployment were deleted
assert:
that:
- _delete is changed

- name: Validate that Deployment do not exist anymore
k8s_info:
kind: Deployment
api_version: apps/v1
namespace: "{{ test_namespace }}"
label_selectors:
- context=ansible
register: _deployment
failed_when: _deployment.resources | length > 0

always:
- name: Remove namespace
k8s:
Expand Down
1 change: 1 addition & 0 deletions tests/sanity/ignore-2.11.txt
Original file line number Diff line number Diff line change
Expand Up @@ -590,3 +590,4 @@ tests/integration/targets/setup_kubeconfig/library/test_inventory_read_credentia
tests/integration/targets/helm/library/helm_test_version.py compile-2.6!skip
tests/integration/targets/helm/library/helm_test_version.py compile-2.7!skip
tests/integration/targets/helm/library/helm_test_version.py compile-3.5!skip
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
1 change: 1 addition & 0 deletions tests/sanity/ignore-2.12.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ plugins/modules/k8s.py validate-modules:return-syntax-error
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
plugins/modules/k8s_service.py validate-modules:return-syntax-error
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
1 change: 1 addition & 0 deletions tests/sanity/ignore-2.13.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ plugins/modules/k8s.py validate-modules:return-syntax-error
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
plugins/modules/k8s_service.py validate-modules:return-syntax-error
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
1 change: 1 addition & 0 deletions tests/sanity/ignore-2.14.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ plugins/modules/k8s.py validate-modules:return-syntax-error
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
plugins/modules/k8s_service.py validate-modules:return-syntax-error
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
1 change: 1 addition & 0 deletions tests/sanity/refresh_ignore_files
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ YAML_LINT_SKIPS = [
"tests/integration/targets/helm/files/test-chart/templates/configmap.yaml",
"tests/integration/targets/helm_diff/files/test-chart/templates/configmap.yaml",
"tests/integration/targets/k8s_scale/files/deployment.yaml",
"tests/integration/targets/k8s_delete/files/deployments.yaml",
]

# Add shebang!skip
Expand Down

0 comments on commit 151ed82

Please sign in to comment.