mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-07-29 10:54:41 +00:00
make name optional to delete all resources for the specified resource 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
This commit is contained in:
3
changelogs/fragments/517-k8s-make-name-optional.yaml
Normal file
3
changelogs/fragments/517-k8s-make-name-optional.yaml
Normal file
@@ -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)
|
||||||
@@ -46,16 +46,51 @@ def validate(client, module, resource):
|
|||||||
return [_prepend_resource_info(resource, msg) for msg in warnings + errors]
|
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:
|
def run_module(module) -> None:
|
||||||
results = []
|
results = []
|
||||||
changed = False
|
changed = False
|
||||||
client = get_api_client(module)
|
client = get_api_client(module)
|
||||||
svc = K8sService(client, module)
|
svc = K8sService(client, module)
|
||||||
try:
|
|
||||||
definitions = create_definitions(module.params)
|
definitions = get_definitions(svc, module.params)
|
||||||
except Exception as e:
|
|
||||||
msg = "Failed to load resource definition: {0}".format(e)
|
|
||||||
raise CoreException(msg) from e
|
|
||||||
|
|
||||||
for definition in definitions:
|
for definition in definitions:
|
||||||
result = {"changed": False, "result": {}}
|
result = {"changed": False, "result": {}}
|
||||||
|
|||||||
@@ -211,6 +211,30 @@ class K8sService:
|
|||||||
|
|
||||||
return existing
|
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(
|
def find(
|
||||||
self,
|
self,
|
||||||
kind: str,
|
kind: str,
|
||||||
|
|||||||
@@ -172,6 +172,19 @@ options:
|
|||||||
- When set to True, server-side apply will force the changes against conflicts.
|
- When set to True, server-side apply will force the changes against conflicts.
|
||||||
type: bool
|
type: bool
|
||||||
default: False
|
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:
|
requirements:
|
||||||
- "python >= 3.6"
|
- "python >= 3.6"
|
||||||
@@ -343,6 +356,14 @@ EXAMPLES = r"""
|
|||||||
apply: yes
|
apply: yes
|
||||||
server_side_apply:
|
server_side_apply:
|
||||||
field_manager: ansible
|
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"""
|
RETURN = r"""
|
||||||
@@ -450,6 +471,7 @@ def argspec():
|
|||||||
argument_spec["server_side_apply"] = dict(
|
argument_spec["server_side_apply"] = dict(
|
||||||
type="dict", default=None, options=server_apply_spec()
|
type="dict", default=None, options=server_apply_spec()
|
||||||
)
|
)
|
||||||
|
argument_spec["delete_all"] = dict(type="bool", default=False, aliases=["all"])
|
||||||
|
|
||||||
return argument_spec
|
return argument_spec
|
||||||
|
|
||||||
|
|||||||
70
tests/integration/targets/k8s_delete/files/deployments.yaml
Normal file
70
tests/integration/targets/k8s_delete/files/deployments.yaml
Normal file
@@ -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
|
||||||
@@ -121,6 +121,77 @@
|
|||||||
that:
|
that:
|
||||||
- _result.resources | length == 0
|
- _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:
|
always:
|
||||||
- name: Remove namespace
|
- name: Remove namespace
|
||||||
k8s:
|
k8s:
|
||||||
|
|||||||
@@ -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.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-2.7!skip
|
||||||
tests/integration/targets/helm/library/helm_test_version.py compile-3.5!skip
|
tests/integration/targets/helm/library/helm_test_version.py compile-3.5!skip
|
||||||
|
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||||
|
|||||||
@@ -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_scale.py validate-modules:return-syntax-error
|
||||||
plugins/modules/k8s_service.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
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
|
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||||
|
|||||||
@@ -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_scale.py validate-modules:return-syntax-error
|
||||||
plugins/modules/k8s_service.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
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
|
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||||
|
|||||||
@@ -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_scale.py validate-modules:return-syntax-error
|
||||||
plugins/modules/k8s_service.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
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
|
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ YAML_LINT_SKIPS = [
|
|||||||
"tests/integration/targets/helm/files/test-chart/templates/configmap.yaml",
|
"tests/integration/targets/helm/files/test-chart/templates/configmap.yaml",
|
||||||
"tests/integration/targets/helm_diff/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_scale/files/deployment.yaml",
|
||||||
|
"tests/integration/targets/k8s_delete/files/deployments.yaml",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Add shebang!skip
|
# Add shebang!skip
|
||||||
|
|||||||
Reference in New Issue
Block a user