Skip to content

Commit ef7109b

Browse files
committed
feat: add function to create objects from dict
1 parent 7bf1100 commit ef7109b

File tree

3 files changed

+113
-26
lines changed

3 files changed

+113
-26
lines changed

kubernetes_asyncio/utils/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@
1515
from __future__ import absolute_import
1616

1717
from .create_from_yaml import (
18-
FailToCreateError, create_from_yaml, create_from_yaml_single_item,
18+
FailToCreateError, create_from_dict, create_from_yaml,
19+
create_from_yaml_single_item,
1920
)

kubernetes_asyncio/utils/create_from_yaml.py

+83-23
Original file line numberDiff line numberDiff line change
@@ -61,35 +61,94 @@ async def create_from_yaml(
6161
with open(path.abspath(yaml_file)) as f:
6262
yml_document_all = yaml.safe_load_all(f)
6363
api_exceptions = []
64+
k8s_objects = []
6465
# Load all documents from a single YAML file
6566
for yml_document in yml_document_all:
66-
# If it is a list type, will need to iterate its items
67-
if "List" in yml_document["kind"]:
68-
# Could be "List" or "Pod/Service/...List"
69-
# This is a list type. iterate within its items
70-
kind = yml_document["kind"].replace("List", "")
71-
for yml_object in yml_document["items"]:
72-
# Mitigate cases when server returns a xxxList object
73-
# See kubernetes-client/python#586
74-
if kind != "":
75-
yml_object["apiVersion"] = yml_document["apiVersion"]
76-
yml_object["kind"] = kind
77-
try:
78-
await create_from_yaml_single_item(
79-
k8s_client, yml_object, verbose, namespace, **kwargs)
80-
except client.rest.ApiException as api_exception:
81-
api_exceptions.append(api_exception)
82-
else:
83-
# This is a single object. Call the single item method
84-
try:
85-
await create_from_yaml_single_item(
86-
k8s_client, yml_document, verbose, namespace, **kwargs)
87-
except client.rest.ApiException as api_exception:
88-
api_exceptions.append(api_exception)
67+
try:
68+
created = await create_from_dict(k8s_client, yml_document,
69+
verbose, namespace=namespace,
70+
**kwargs)
71+
k8s_objects.append(created)
72+
except FailToCreateError as failure:
73+
api_exceptions.extend(failure)
74+
8975
# In case we have exceptions waiting for us, raise them
9076
if api_exceptions:
9177
raise FailToCreateError(api_exceptions)
9278

79+
return k8s_objects
80+
81+
82+
async def create_from_dict(
83+
k8s_client,
84+
data,
85+
verbose=False,
86+
namespace="default",
87+
**kwargs):
88+
"""
89+
Perform an action from a yaml file. Pass True for verbose to
90+
print confirmation information.
91+
Input:
92+
yaml_file: string. Contains the path to yaml file.
93+
data: a dictionary holding valid kubernetes objects
94+
verbose: If True, print confirmation from the create action.
95+
Default is False.
96+
namespace: string. Contains the namespace to create all
97+
resources inside. The namespace must preexist otherwise
98+
the resource creation will fail. If the API object in
99+
the yaml file already contains a namespace definition
100+
this parameter has no effect.
101+
Returns:
102+
An k8s api object or list of apis objects created from dict.
103+
When a single object is generated, return type is dependent
104+
on output_list.
105+
Throws a FailToCreateError exception if creation of any object
106+
fails with helpful messages from the server.
107+
Available parameters for creating <kind>:
108+
:param async_req bool
109+
:param bool include_uninitialized: If true, partially initialized
110+
resources are included in the response.
111+
:param str pretty: If 'true', then the output is pretty printed.
112+
:param str dry_run: When present, indicates that modifications
113+
should not be persisted. An invalid or unrecognized dryRun
114+
directive will result in an error response and no further
115+
processing of the request.
116+
Valid values are: - All: all dry run stages will be processed
117+
"""
118+
api_exceptions = []
119+
k8s_objects = []
120+
121+
# If it is a list type, will need to iterate its items
122+
if "List" in data["kind"]:
123+
# Could be "List" or "Pod/Service/...List"
124+
# This is a list type. iterate within its items
125+
kind = data["kind"].replace("List", "")
126+
for yml_object in data["items"]:
127+
# Mitigate cases when server returns a xxxList object
128+
# See kubernetes-client/python#586
129+
if kind != "":
130+
yml_object["apiVersion"] = data["apiVersion"]
131+
yml_object["kind"] = kind
132+
try:
133+
created = await create_from_yaml_single_item(
134+
k8s_client, yml_object, verbose, namespace, **kwargs)
135+
k8s_objects.append(created)
136+
except client.rest.ApiException as api_exception:
137+
api_exceptions.append(api_exception)
138+
else:
139+
# This is a single object. Call the single item method
140+
try:
141+
created = await create_from_yaml_single_item(
142+
k8s_client, data, verbose, namespace, **kwargs)
143+
k8s_objects.append(created)
144+
except client.rest.ApiException as api_exception:
145+
api_exceptions.append(api_exception)
146+
147+
if api_exceptions:
148+
raise FailToCreateError(api_exceptions)
149+
150+
return k8s_objects
151+
93152

94153
async def create_from_yaml_single_item(
95154
k8s_client,
@@ -126,6 +185,7 @@ async def create_from_yaml_single_item(
126185
body=yml_object, **kwargs)
127186
if verbose:
128187
print("{0} created. status='{1}'".format(kind, str(resp.status)))
188+
return resp
129189

130190

131191
class FailToCreateError(Exception):

kubernetes_asyncio/utils/create_from_yaml_test.py

+28-2
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,47 @@
1414

1515
from asynctest import CoroutineMock, TestCase
1616

17-
from kubernetes_asyncio.utils import create_from_yaml
17+
from kubernetes_asyncio.utils import create_from_dict, create_from_yaml
1818

1919

2020
class CreateFromYamlTest(TestCase):
2121

2222
async def test_create_from_yaml(self):
2323
api_client = CoroutineMock()
2424
api_client.call_api = CoroutineMock()
25+
api_client.call_api.return_value = 'mock-value'
2526

26-
await create_from_yaml(api_client, 'examples/nginx-deployment.yaml')
27+
created = await create_from_yaml(api_client, 'examples/nginx-deployment.yaml')
2728

2829
# simple check for api call
2930
self.assertEqual(api_client.call_api.call_args[0][0],
3031
'/apis/apps/v1/namespaces/{namespace}/deployments')
3132

33+
# returned values
34+
self.assertEqual(created, [['mock-value']])
35+
36+
async def test_create_from_dict(self):
37+
api_client = CoroutineMock()
38+
api_client.call_api = CoroutineMock()
39+
api_client.call_api.return_value = 'mock-value'
40+
41+
created = await create_from_dict(api_client, {
42+
'apiVersion': 'apps/v1',
43+
'kind': 'Deployment',
44+
'metadata': {
45+
'name': 'nginx-deployment'},
46+
'spec': {
47+
'replicas': 3,
48+
}
49+
})
50+
51+
# simple check for api call
52+
self.assertEqual(api_client.call_api.call_args[0][0],
53+
'/apis/apps/v1/namespaces/{namespace}/deployments')
54+
55+
# returned values
56+
self.assertEqual(created, ['mock-value'])
57+
3258

3359
if __name__ == '__main__':
3460
import asynctest

0 commit comments

Comments
 (0)