diff --git a/kubernetes/e2e_test/test_utils.py b/kubernetes/e2e_test/test_utils.py index 4096bf86e..98768b0c9 100644 --- a/kubernetes/e2e_test/test_utils.py +++ b/kubernetes/e2e_test/test_utils.py @@ -288,6 +288,28 @@ class TestUtils(unittest.TestCase): core_api.delete_namespaced_service(name="mock-4", namespace="default", body={}) + # Tests for creating multi-resource from directory + + def test_create_multi_resource_from_directory(self): + """ + Should be able to create a service and a replication controller + from a directory + """ + k8s_client = client.api_client.ApiClient(configuration=self.config) + utils.create_from_directory( + k8s_client, self.path_prefix + "multi-resource/") + core_api = client.CoreV1Api(k8s_client) + svc = core_api.read_namespaced_service(name="mock", + namespace="default") + self.assertIsNotNone(svc) + ctr = core_api.read_namespaced_replication_controller( + name="mock", namespace="default") + self.assertIsNotNone(ctr) + core_api.delete_namespaced_replication_controller( + name="mock", namespace="default", propagation_policy="Background") + core_api.delete_namespaced_service(name="mock", + namespace="default", body={}) + # Tests for multi-resource yaml objects def test_create_from_multi_resource_yaml(self): diff --git a/kubernetes/e2e_test/test_yaml/multi-resource/multi-resource-replication-controller.yaml b/kubernetes/e2e_test/test_yaml/multi-resource/multi-resource-replication-controller.yaml new file mode 100644 index 000000000..e644305ab --- /dev/null +++ b/kubernetes/e2e_test/test_yaml/multi-resource/multi-resource-replication-controller.yaml @@ -0,0 +1,19 @@ +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 \ No newline at end of file diff --git a/kubernetes/e2e_test/test_yaml/multi-resource/multi-resource-service.yaml b/kubernetes/e2e_test/test_yaml/multi-resource/multi-resource-service.yaml new file mode 100644 index 000000000..2e3a9fa06 --- /dev/null +++ b/kubernetes/e2e_test/test_yaml/multi-resource/multi-resource-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: mock + labels: + app: mock +spec: + ports: + - port: 99 + protocol: TCP + targetPort: 9949 + selector: + app: mock \ No newline at end of file diff --git a/kubernetes/utils/__init__.py b/kubernetes/utils/__init__.py index 8add80bcf..217d9ccbc 100644 --- a/kubernetes/utils/__init__.py +++ b/kubernetes/utils/__init__.py @@ -15,5 +15,5 @@ from __future__ import absolute_import from .create_from_yaml import (FailToCreateError, create_from_dict, - create_from_yaml) + create_from_yaml, create_from_directory) from .quantity import parse_quantity diff --git a/kubernetes/utils/create_from_yaml.py b/kubernetes/utils/create_from_yaml.py index 3a996a13d..7ca4cd7bc 100644 --- a/kubernetes/utils/create_from_yaml.py +++ b/kubernetes/utils/create_from_yaml.py @@ -14,7 +14,7 @@ import re -from os import path +import os import yaml @@ -24,6 +24,76 @@ UPPER_FOLLOWED_BY_LOWER_RE = re.compile('(.)([A-Z][a-z]+)') LOWER_OR_NUM_FOLLOWED_BY_UPPER_RE = re.compile('([a-z0-9])([A-Z])') +def create_from_directory( + k8s_client, + yaml_dir=None, + verbose=False, + namespace="default", + **kwargs): + """ + Perform an action from files from a directory. Pass True for verbose to + print confirmation information. + + Input: + k8s_client: an ApiClient object, initialized with the client args. + yaml_dir: string. Contains the path to directory. + 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 : + :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 + + Returns: + The list containing the created kubernetes API objects. + + Raises: + FailToCreateError which holds list of `client.rest.ApiException` + instances for each object that failed to create. + """ + + if not yaml_dir: + raise ValueError( + '`yaml_dir` argument must be provided') + elif not os.path.isdir(yaml_dir): + raise ValueError( + '`yaml_dir` argument must be a path to directory') + + files = [os.path.join(yaml_dir, i) for i in os.listdir(yaml_dir) + if os.path.isfile(os.path.join(yaml_dir, i))] + if not files: + raise ValueError( + '`yaml_dir` contains no files') + + failures = [] + k8s_objects_all = [] + + for file in files: + try: + k8s_objects = create_from_yaml(k8s_client, file, + verbose=verbose, + namespace=namespace, + **kwargs) + k8s_objects_all.append(k8s_objects) + except FailToCreateError as failure: + failures.extend(failure.api_exceptions) + if failures: + raise FailToCreateError(failures) + return k8s_objects_all + + def create_from_yaml( k8s_client, yaml_file=None, @@ -87,7 +157,7 @@ def create_from_yaml( yml_document_all = yaml_objects return create_with(yml_document_all) elif yaml_file: - with open(path.abspath(yaml_file)) as f: + with open(os.path.abspath(yaml_file)) as f: yml_document_all = yaml.safe_load_all(f) return create_with(yml_document_all) else: