forked from kubernetes-client/python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdelete_from_yaml.py
executable file
·146 lines (130 loc) · 5.69 KB
/
delete_from_yaml.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
from os import path
import yaml
from kubernetes import client
def delete_from_yaml(k8s_client, yaml_file, verbose=False,
namespace="default", **kwargs):
"""Input:
yaml_file: string. Contains the path to yaml file.
k8s_client: an ApiClient object, initialized with the client args.
verbose: If True, print confirmation from the create action.
Default is False.
namespace: string. Contains the namespace to create all
resources inside. The namespace must preexist otherwise
the resource creation will fail. If the API object in
the yaml file already contains a namespace definition
this parameter has no effect.
Available parameters for creating <kind>:
:param async_req bool
:param str pretty: If 'true', then the output is pretty printed.
:param str dry_run: When present, indicates that modifications
should not be persisted. An invalid or unrecognized dryRun
directive will result in an error response and no further
processing of the request.
Valid values are: - All: all dry run stages will be processed
Raises:
FailToDeleteError which holds list of `client.rest.ApiException`
instances for each object that failed to delete.
"""
with open(path.abspath(yaml_file)) as f:
yml_document_all = yaml.safe_load_all(f)
failures = []
for yml_document in yml_document_all:
try:
# call delete from dict function
delete_from_dict(k8s_client, yml_document, verbose,
namespace=namespace, **kwargs)
except FailToDeleteError as failure:
failures.extend(failure.api_exceptions)
if failures:
raise FailToDeleteError(failures)
def delete_from_dict(k8s_client, yml_document, verbose,
namespace="default", **kwargs):
api_exceptions = []
if "List" in yml_document["kind"]:
kind = yml_document["kind"].replace("List", "")
for yml_doc in yml_document["items"]:
if kind != "":
yml_doc["apiVersion"] = yml_document["apiVersion"]
yml_doc["kind"] = kind
try:
delete_from_yaml_single_item(
k8s_client, yml_doc, verbose, namespace=namespace, **kwargs
)
except client.rest.ApiException as api_exception:
api_exceptions.append(api_exception)
else:
try:
delete_from_yaml_single_item(
k8s_client, yml_document, verbose,
namespace=namespace, **kwargs
)
except client.rest.ApiException as api_exception:
api_exceptions.append(api_exception)
if api_exceptions:
raise FailToDeleteError(api_exceptions)
def delete_from_yaml_single_item(k8s_client,
yml_document, verbose=False, **kwargs):
# get group and version from apiVersion
group, _, version = yml_document["apiVersion"].partition("/")
if version == "":
version = group
group = "core"
# Take care for the case e.g. api_type is "apiextensions.k8s.io"
group = "".join(group.rsplit(".k8s.io", 1))
# convert group name from DNS subdomain format to
# python class name convention
group = "".join(word.capitalize() for word in group.split('.'))
func = "{0}{1}Api".format(group, version.capitalize())
k8s_api = getattr(client, func)(k8s_client)
kind = yml_document["kind"]
kind = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', kind)
kind = re.sub('([a-z0-9])([A-Z])', r'\1_\2', kind).lower()
if hasattr(k8s_api, "create_namespaced_{0}".format(kind)):
if "namespace" in yml_document["metadata"]:
namespace = yml_document["metadata"]["namespace"]
kwargs["namespace"] = namespace
name = yml_document["metadata"]["name"]
res = getattr(k8s_api, "delete_namespaced_{}".format(kind))(
name=name,
body=client.V1DeleteOptions(propagation_policy="Background",
grace_period_seconds=5), **kwargs)
else:
# get name of object to delete
name = yml_document["metadata"]["name"]
kwargs.pop('namespace', None)
res = getattr(k8s_api, "delete_{}".format(kind))(
name=name,
body=client.V1DeleteOptions(propagation_policy="Background",
grace_period_seconds=5), **kwargs)
if verbose:
msg = "{0} deleted.".format(kind)
if hasattr(res, 'status'):
msg += " status='{0}'".format(str(res.status))
print(msg)
class FailToDeleteError(Exception):
"""
An exception class for handling error if an error occurred when
handling a yaml file during deletion of the resource.
"""
def __init__(self, api_exceptions):
self.api_exceptions = api_exceptions
def __str__(self):
msg = ""
for api_exception in self.api_exceptions:
msg += "Error from server ({0}):{1}".format(
api_exception.reason, api_exception.body)
return msg