summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--k8s/.coveragerc21
-rw-r--r--k8s/LICENSE.txt2
-rw-r--r--k8s/k8s-node-type.yaml8
-rw-r--r--k8s/k8sclient/k8sclient.py6
-rw-r--r--k8s/pom.xml4
-rw-r--r--k8s/setup.py2
-rw-r--r--k8s/tests/test_k8sclient.py125
7 files changed, 154 insertions, 14 deletions
diff --git a/k8s/.coveragerc b/k8s/.coveragerc
new file mode 100644
index 0000000..088c2da
--- /dev/null
+++ b/k8s/.coveragerc
@@ -0,0 +1,21 @@
+# .coveragerc to control coverage.py
+[run]
+branch = True
+
+[report]
+# Regexes for lines to exclude from consideration
+exclude_lines =
+ # Have to re-enable the standard pragma
+ pragma: no cover
+
+ # Don't complain about missing debug-only code:
+ def __repr__
+ if self\.debug
+
+ # Don't complain if tests don't hit defensive assertion code:
+ raise AssertionError
+ raise NotImplementedError
+
+ # Don't complain if non-runnable code isn't run:
+ if 0:
+ if __name__ == .__main__.:
diff --git a/k8s/LICENSE.txt b/k8s/LICENSE.txt
index e266d0a..43098d1 100644
--- a/k8s/LICENSE.txt
+++ b/k8s/LICENSE.txt
@@ -1,7 +1,7 @@
============LICENSE_START=======================================================
org.onap.dcae
================================================================================
-Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
+Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved.
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/k8s/k8s-node-type.yaml b/k8s/k8s-node-type.yaml
index f63f822..166e430 100644
--- a/k8s/k8s-node-type.yaml
+++ b/k8s/k8s-node-type.yaml
@@ -19,13 +19,13 @@
tosca_definitions_version: cloudify_dsl_1_3
imports:
- - http://www.getcloudify.org/spec/cloudify/4.2/types.yaml
+ - http://www.getcloudify.org/spec/cloudify/3.4/types.yaml
plugins:
k8s:
executor: 'central_deployment_agent'
package_name: k8splugin
- package_version: 1.4.6
+ package_version: 1.4.7
data_types:
@@ -123,9 +123,9 @@ node_types:
default: {}
description: >
This is used to specify the cpu and memory request and limit for container.
- Please specify "requests" property and/or a "limits" property, with subproproperties
+ Please specify "requests" property and/or a "limits" property, with subproproperties
for cpu and memory. (https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/)
-
+
log_info:
type: dcae.types.LoggingInfo
diff --git a/k8s/k8sclient/k8sclient.py b/k8s/k8sclient/k8sclient.py
index 84ca84f..31631ad 100644
--- a/k8s/k8sclient/k8sclient.py
+++ b/k8s/k8sclient/k8sclient.py
@@ -38,7 +38,7 @@ FACTORS = {None: 1, "s": 1, "m": 60, "h": 3600}
# group 3: protocol
# group 4: host port
PORTS = re.compile("^([0-9]+)(/(udp|UDP|tcp|TCP))?:([0-9]+)$")
-
+
def _create_deployment_name(component_name):
return "dep-{0}".format(component_name)
@@ -126,7 +126,7 @@ def _create_resources(resources=None):
resources_obj = client.V1ResourceRequirements(
limits = resources.get("limits"),
requests = resources.get("requests")
- )
+ )
return resources_obj
else:
return None
@@ -398,9 +398,9 @@ def deploy(namespace, component_name, image, replicas, always_pull, k8sconfig, r
}
try:
- _configure_api()
# Get API handles
+ _configure_api()
core = client.CoreV1Api()
ext = client.ExtensionsV1beta1Api()
diff --git a/k8s/pom.xml b/k8s/pom.xml
index 844f214..45c5a39 100644
--- a/k8s/pom.xml
+++ b/k8s/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
================================================================================
-Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
+Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved.
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property.
<groupId>org.onap.dcaegen2.platform.plugins</groupId>
<artifactId>k8s</artifactId>
<name>k8s-plugin</name>
- <version>1.4.5-SNAPSHOT</version>
+ <version>1.4.7-SNAPSHOT</version>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
diff --git a/k8s/setup.py b/k8s/setup.py
index 36fbe05..9ad35bf 100644
--- a/k8s/setup.py
+++ b/k8s/setup.py
@@ -23,7 +23,7 @@ from setuptools import setup
setup(
name='k8splugin',
description='Cloudify plugin for containerized components deployed using Kubernetes',
- version="1.4.6",
+ version="1.4.7",
author='J. F. Lucas, Michael Hwang, Tommy Carpenter',
packages=['k8splugin','k8sclient','msb','configure'],
zip_safe=False,
diff --git a/k8s/tests/test_k8sclient.py b/k8s/tests/test_k8sclient.py
index e985def..2511239 100644
--- a/k8s/tests/test_k8sclient.py
+++ b/k8s/tests/test_k8sclient.py
@@ -102,7 +102,7 @@ def test_parse_ports():
("9101/udp:31043", (9101, 31043, "UDP"))
]
]
-
+
bad_ports = [
"9101",
"9101:",
@@ -130,10 +130,10 @@ def test_parse_ports():
(9661,"TCP") : 19661,
(9661,"UDP") : 19661,
(8080,"TCP") : 8080
- }
+ }
for test_case in good_ports:
- container_ports, port_map = _parse_ports([test_case["in"]])
+ container_ports, port_map = _parse_ports([test_case["in"]])
(cport, hport, proto) = test_case["ex"]
assert container_ports == [(cport, proto)]
assert port_map == {(cport, proto) : hport}
@@ -153,3 +153,122 @@ def test_create_container():
assert container.ports[0].container_port == 80 and container.ports[0].protocol == "TCP"
assert container.ports[1].container_port == 53 and container.ports[1].protocol == "UDP"
+
+def test_create_probe():
+ from k8sclient.k8sclient import _create_probe
+ from kubernetes import client
+
+ http_checks = [
+ {"type" : "http", "endpoint" : "/example/health"}
+ ]
+
+ script_checks = [
+ {"type" : "docker", "script": "/opt/app/health_check.sh"}
+ ]
+
+ for hc in http_checks:
+ probe = _create_probe(hc, 13131)
+ assert probe.http_get.path == hc["endpoint"]
+ assert probe.http_get.scheme == hc["type"].upper()
+
+ for hc in script_checks:
+ probe = _create_probe(hc, 13131)
+ assert probe._exec.command[0] == hc["script"]
+
+def test_deploy(monkeypatch):
+ import k8sclient.k8sclient
+ from kubernetes import client
+
+ # We need to patch the kubernetes 'client' module
+ # Awkward because of the way it requires a function call
+ # to get an API object
+ core = client.CoreV1Api()
+ ext = client.ExtensionsV1beta1Api()
+
+ def pseudo_deploy(namespace, dep):
+ return dep
+
+ def pseudo_service(namespace, svc):
+ return svc
+
+ # patched_core returns a CoreV1Api object with the
+ # create_namespaced_service method stubbed out so that there
+ # is no attempt to call the k8s API server
+ def patched_core():
+ monkeypatch.setattr(core, "create_namespaced_service", pseudo_service)
+ return core
+
+ # patched_ext returns an ExtensionsV1beta1Api object with the
+ # create_namespaced_deployment method stubbed out so that there
+ # is no attempt to call the k8s API server
+ def patched_ext():
+ monkeypatch.setattr(ext,"create_namespaced_deployment", pseudo_deploy)
+ return ext
+
+ def pseudo_configure():
+ pass
+
+ monkeypatch.setattr(k8sclient.k8sclient,"_configure_api", pseudo_configure)
+ monkeypatch.setattr(client, "CoreV1Api", patched_core)
+ monkeypatch.setattr(client,"ExtensionsV1beta1Api", patched_ext)
+
+ k8s_test_config = {
+ "image_pull_secrets" : ["secret0", "secret1"],
+ "filebeat" : {
+ "log_path": "/var/log/onap",
+ "data_path": "/usr/share/filebeat/data",
+ "config_path": "/usr/share/filebeat/filebeat.yml",
+ "config_subpath": "filebeat.yml",
+ "image" : "filebeat-repo/filebeat:latest",
+ "config_map" : "dcae-filebeat-configmap"
+ },
+ "tls" : {
+ "cert_path": "/opt/certs",
+ "image": "tlsrepo/tls-init-container:1.2.3"
+ }
+ }
+
+ resources = {
+ "limits": {
+ "cpu" : 0.5,
+ "memory" : "2Gi"
+ },
+ "requests": {
+ "cpu" : 0.5,
+ "memory" : "2Gi"
+ }
+ }
+
+ kwargs = {
+ "volumes": [
+ {"host":{"path": "/path/on/host"}, "container":{"bind":"/path/on/container","mode":"rw"}}
+ ],
+ "ports": ["80:0", "443:0"],
+ "env": {"name0": "value0", "name1": "value1"},
+ "log_info": {"log_directory": "/path/to/container/log/directory"},
+ "tls_info": {"use_tls": True, "cert_directory": "/path/to/container/cert/directory" },
+ "readiness": {"type": "http", "endpoint" : "/ready"}
+ }
+ dep, deployment_description = k8sclient.k8sclient.deploy("k8stest","testcomponent","example.com/testcomponent:1.4.3",1,False, k8s_test_config, resources, **kwargs)
+
+ assert deployment_description["deployment"] == "dep-testcomponent"
+ assert deployment_description["namespace"] == "k8stest"
+ assert deployment_description["services"][0] == "testcomponent"
+
+ # For unit test purposes, we want to make sure that the deployment object
+ # we're passing to the k8s API is correct
+ app_container = dep.spec.template.spec.containers[0]
+ assert app_container.image == "example.com/testcomponent:1.4.3"
+ assert app_container.image_pull_policy == "IfNotPresent"
+ assert len(app_container.ports) == 2
+ assert app_container.ports[0].container_port == 80
+ assert app_container.ports[1].container_port == 443
+ assert app_container.readiness_probe.http_get.path == "/ready"
+ assert app_container.readiness_probe.http_get.scheme == "HTTP"
+ assert len(app_container.volume_mounts) == 3
+ assert app_container.volume_mounts[0].mount_path == "/path/on/container"
+ assert app_container.volume_mounts[1].mount_path == "/path/to/container/log/directory"
+ assert app_container.volume_mounts[2].mount_path == "/path/to/container/cert/directory"
+
+ # Needs to be correctly labeled so that the Service can find it
+ assert dep.spec.template.metadata.labels["app"] == "testcomponent"