Skip to content

Commit

Permalink
YAML List and Multi-Resource
Browse files Browse the repository at this point in the history
  • Loading branch information
micw523 committed Nov 2, 2018
1 parent 4d4ce21 commit d52c7ac
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 36 deletions.
2 changes: 1 addition & 1 deletion kubernetes/base
Submodule base updated 1 files
+1 −1 .travis.yml
41 changes: 40 additions & 1 deletion kubernetes/e2e_test/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,43 @@ def test_api_service(self):
name="v1alpha1.wardle.k8s.io")
self.assertIsNotNone(svc)
resp = k8s_api.delete_api_service(
name="v1alpha1.wardle.k8s.io", body={})
name="v1alpha1.wardle.k8s.io", body={})

def test_list(self):
k8s_client = client.api_client.ApiClient(configuration=self.config)
k8s_api = utils.create_from_yaml(k8s_client,
"kubernetes/e2e_test/test_yaml/list.yaml")
svc_api = k8s_api[0]
self.assertEqual("v1", svc_api.get_api_resources().group_version)
svc = svc_api.read_namespaced_service(name="list-service-test",
namespace="default")
self.assertIsNotNone(svc)
ext_api = k8s_api[1]
self.assertEqual("extensions/v1beta1",
ext_api.get_api_resources().group_version)
dep = ext_api.read_namespaced_deployment(name="list-deployment-test",
namespace="default")
self.assertIsNotNone(dep)
ext_api.delete_namespaced_deployment(name="list-deployment-test",
namespace="default", body={})
svc_api.delete_namespaced_service(name="list-service-test",
namespace="default", body={})

def test_multi_resource(self):
k8s_client = client.api_client.ApiClient(configuration=self.config)
k8s_api = utils.create_from_yaml(k8s_client,
"kubernetes/e2e_test/test_yaml/multi-resource-yaml.yaml")
svc_api = k8s_api[0]
self.assertEqual("v1", svc_api.get_api_resources().group_version)
svc = svc_api.read_namespaced_service(name="mock",
namespace="default")
self.assertIsNotNone(svc)
ctr_api = k8s_api[1]
self.assertEqual("v1", ctr_api.get_api_resources().group_version)
ctr = ctr_api.read_namespaced_replication_controller(
name="mock", namespace="default")
self.assertIsNotNone(ctr)
ctr_api.delete_namespaced_replication_controller(name="mock",
namespace="default", body={})
svc_api.delete_namespaced_service(name="mock",
namespace="default", body={})
29 changes: 29 additions & 0 deletions kubernetes/e2e_test/test_yaml/list.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: Service
metadata:
name: list-service-test
spec:
ports:
- protocol: TCP
port: 80
selector:
app: list-deployment-test
- apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: list-deployment-test
labels:
app: list-deployment-test
spec:
replicas: 1
template:
metadata:
labels:
app: list-deployment-test
spec:
containers:
- name: nginx
image: nginx
33 changes: 33 additions & 0 deletions kubernetes/e2e_test/test_yaml/multi-resource-yaml.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: v1
kind: Service
metadata:
name: mock
labels:
app: mock
spec:
ports:
- port: 99
protocol: TCP
targetPort: 9949
selector:
app: mock
---
apiVersion: v1
kind: ReplicationController
metadata:
name: mock
spec:
replicas: 1
selector:
app: mock
template:
metadata:
labels:
app: mock
spec:
containers:
- name: mock-container
image: k8s.gcr.io/pause:2.0
ports:
- containerPort: 9949
protocol: TCP
102 changes: 68 additions & 34 deletions kubernetes/utils/create_from_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,51 +23,85 @@
from kubernetes import client


def create_from_yaml(k8s_client, yaml_file, verbose=False, **kwargs):
def create_from_yaml(
k8s_client,
yaml_file,
verbose=False,
output_list=False,
**kwargs):
"""
Perform an action from a yaml file. Pass True for verbose to
print confirmation information.
Input:
yaml_file: string. Contains the path to yaml file.
k8s_cline: an ApiClient object, initialized with the client args.
verbose: If True, print confirmation from the create action. Default is False.
output_list: compatibility option with v8.0.0. Default is False.
Function returns a single api object when there is only one when set False.
Does not affect when multiple objects are generated.
Available parameters for performing the subsequent action:
Returns:
An k8s api object or list of apis objects created from YAML.
When a single object is generated, return type is dependent on output_list.
Available parameters for creating <kind>:
:param async_req bool
:param bool include_uninitialized: If true, partially initialized resources are included in the response.
: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
"""

k8s_api_all = []
with open(path.abspath(yaml_file)) as f:
yml_object = yaml.load(f)
# TODO: case of yaml file containing multiple objects
group, _, version = yml_object["apiVersion"].partition("/")
if version == "":
version = group
group = "core"
# Take care for the case e.g. api_type is "apiextensions.k8s.io"
# Only replace the last instance
group = "".join(group.rsplit(".k8s.io", 1))
fcn_to_call = "{0}{1}Api".format(group.capitalize(),
version.capitalize())
k8s_api = getattr(client, fcn_to_call)(k8s_client)
# Replace CamelCased action_type into snake_case
kind = yml_object["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()
# Decide which namespace we are going to put the object in,
# if any
if "namespace" in yml_object["metadata"]:
namespace = yml_object["metadata"]["namespace"]
else:
namespace = "default"
# Expect the user to create namespaced objects more often
if hasattr(k8s_api, "create_namespaced_{0}".format(kind)):
resp = getattr(k8s_api, "create_namespaced_{0}".format(kind))(
body=yml_object, namespace=namespace, **kwargs)
else:
resp = getattr(k8s_api, "create_{0}".format(kind))(
body=yml_object, **kwargs)
if verbose:
print("{0} created. status='{1}'".format(kind, str(resp.status)))
return k8s_api
yml_document_all = yaml.load_all(f)
# Load all documents from a single YAML file
for yml_document in yml_document_all:
# If it is a list type, will need to iterate its items
if "List" in yml_document["kind"]:
# Could be "List" or "Pod/Service/...List"
# This is a list type. iterate within its items
for yml_object in yml_document["items"]:
k8s_api_all.append(create_from_yaml_single_item(
k8s_client, yml_object, verbose, **kwargs))
else:
# This is a single object. Call the single item method
k8s_api_all.append(create_from_yaml_single_item(
k8s_client, yml_document, verbose, **kwargs))
if output_list is False:
if len(k8s_api_all) == 1:
return k8s_api_all[0]
return k8s_api_all


def create_from_yaml_single_item(
k8s_client, yml_object, verbose=False, **kwargs):
group, _, version = yml_object["apiVersion"].partition("/")
if version == "":
version = group
group = "core"
# Take care for the case e.g. api_type is "apiextensions.k8s.io"
# Only replace the last instance
group = "".join(group.rsplit(".k8s.io", 1))
fcn_to_call = "{0}{1}Api".format(group.capitalize(),
version.capitalize())
k8s_api = getattr(client, fcn_to_call)(k8s_client)
# Replace CamelCased action_type into snake_case
kind = yml_object["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()
# Decide which namespace we are going to put the object in,
# if any
if "namespace" in yml_object["metadata"]:
namespace = yml_object["metadata"]["namespace"]
else:
namespace = "default"
# Expect the user to create namespaced objects more often
if hasattr(k8s_api, "create_namespaced_{0}".format(kind)):
resp = getattr(k8s_api, "create_namespaced_{0}".format(kind))(
body=yml_object, namespace=namespace, **kwargs)
else:
resp = getattr(k8s_api, "create_{0}".format(kind))(
body=yml_object, **kwargs)
if verbose:
print("{0} created. status='{1}'".format(kind, str(resp.status)))
return k8s_api

0 comments on commit d52c7ac

Please sign in to comment.