fix(kubernetes): temporary solution for updated k8s python client
This commit is contained in:
parent
07d6fe7442
commit
9129813244
1478 changed files with 422354 additions and 2 deletions
13
kubernetes/e2e_test/__init__.py
Normal file
13
kubernetes/e2e_test/__init__.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
46
kubernetes/e2e_test/base.py
Normal file
46
kubernetes/e2e_test/base.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
# 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 os
|
||||
import unittest
|
||||
import urllib3
|
||||
|
||||
from kubernetes.client.configuration import Configuration
|
||||
from kubernetes.config import kube_config
|
||||
|
||||
DEFAULT_E2E_HOST = '127.0.0.1'
|
||||
|
||||
|
||||
def get_e2e_configuration():
|
||||
config = Configuration()
|
||||
config.host = None
|
||||
if os.path.exists(
|
||||
os.path.expanduser(kube_config.KUBE_CONFIG_DEFAULT_LOCATION)):
|
||||
kube_config.load_kube_config(client_configuration=config)
|
||||
else:
|
||||
print('Unable to load config from %s' %
|
||||
kube_config.KUBE_CONFIG_DEFAULT_LOCATION)
|
||||
for url in ['https://%s:8443' % DEFAULT_E2E_HOST,
|
||||
'http://%s:8080' % DEFAULT_E2E_HOST]:
|
||||
try:
|
||||
urllib3.PoolManager().request('GET', url)
|
||||
config.host = url
|
||||
config.verify_ssl = False
|
||||
urllib3.disable_warnings()
|
||||
break
|
||||
except urllib3.exceptions.HTTPError:
|
||||
pass
|
||||
if config.host is None:
|
||||
raise unittest.SkipTest('Unable to find a running Kubernetes instance')
|
||||
print('Running test against : %s' % config.host)
|
||||
config.assert_hostname = False
|
||||
return config
|
39
kubernetes/e2e_test/port_server.py
Normal file
39
kubernetes/e2e_test/port_server.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
import select
|
||||
import socketserver
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
class PortServer:
|
||||
def __init__(self, port):
|
||||
self.port = port
|
||||
self.server = socketserver.ThreadingTCPServer(('0.0.0.0', port), self.handler)
|
||||
self.server.daemon_threads = True
|
||||
self.thread = threading.Thread(target=self.server.serve_forever,
|
||||
name='Port %s Server' % port)
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
|
||||
|
||||
def handler(self, request, address, server):
|
||||
threading.current_thread().name = 'Port %s Handler' % self.port
|
||||
rlist = [request]
|
||||
echo = b''
|
||||
while True:
|
||||
r, w, _x = select.select(rlist, [request] if echo else [], [])
|
||||
if r:
|
||||
data = request.recv(1024)
|
||||
if not data:
|
||||
break
|
||||
print(f"{self.port}: {data}\n", end='', flush=True)
|
||||
echo += data
|
||||
if w:
|
||||
echo = echo[request.send(echo):]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ports = []
|
||||
for port in sys.argv[1:]:
|
||||
ports.append(PortServer(int(port)))
|
||||
time.sleep(10 * 60)
|
112
kubernetes/e2e_test/test_apps.py
Normal file
112
kubernetes/e2e_test/test_apps.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 unittest
|
||||
import uuid
|
||||
import yaml
|
||||
|
||||
from kubernetes.client import api_client
|
||||
from kubernetes.client.api import apps_v1_api
|
||||
from kubernetes.client.models import v1_delete_options
|
||||
from kubernetes.e2e_test import base
|
||||
|
||||
|
||||
class TestClientApps(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.config = base.get_e2e_configuration()
|
||||
|
||||
def test_create_deployment(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = apps_v1_api.AppsV1Api(client)
|
||||
name = 'nginx-deployment-' + str(uuid.uuid4())
|
||||
deployment = '''apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: %s
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
||||
'''
|
||||
api.create_namespaced_deployment(
|
||||
body=yaml.safe_load(deployment % name),
|
||||
namespace="default")
|
||||
resp = api.read_namespaced_deployment(name, 'default')
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(resp.metadata.name, name)
|
||||
self.assertEqual(resp.spec.replicas, 3)
|
||||
self.assertEqual(resp.spec.selector.match_labels['app'], 'nginx')
|
||||
self.assertEqual(resp.spec.template.metadata.labels['app'], 'nginx')
|
||||
self.assertEqual(resp.spec.template.spec.containers[0].name, 'nginx')
|
||||
self.assertEqual(resp.spec.template.spec.containers[0].image, 'nginx:1.15.4')
|
||||
self.assertEqual(resp.spec.template.spec.containers[0].ports[0].container_port, 80)
|
||||
|
||||
options = v1_delete_options.V1DeleteOptions()
|
||||
api.delete_namespaced_deployment(name, 'default', body=options)
|
||||
|
||||
def test_create_daemonset(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = apps_v1_api.AppsV1Api(client)
|
||||
name = 'nginx-app-' + str(uuid.uuid4())
|
||||
daemonset = {
|
||||
'apiVersion': 'apps/v1',
|
||||
'kind': 'DaemonSet',
|
||||
'metadata': {
|
||||
'labels': {'app': 'nginx'},
|
||||
'name': '%s' % name,
|
||||
},
|
||||
'spec': {
|
||||
'selector': {
|
||||
'matchLabels': {'app': 'nginx'},
|
||||
},
|
||||
'template': {
|
||||
'metadata': {
|
||||
'labels': {'app': 'nginx'},
|
||||
'name': name},
|
||||
'spec': {
|
||||
'containers': [
|
||||
{'name': 'nginx-app',
|
||||
'image': 'nginx:1.15.4'},
|
||||
],
|
||||
},
|
||||
},
|
||||
'updateStrategy': {
|
||||
'type': 'RollingUpdate',
|
||||
},
|
||||
}
|
||||
}
|
||||
api.create_namespaced_daemon_set('default', body=daemonset)
|
||||
resp = api.read_namespaced_daemon_set(name, 'default')
|
||||
self.assertIsNotNone(resp)
|
||||
self.assertEqual(resp.metadata.name, name)
|
||||
self.assertEqual(resp.spec.selector.match_labels['app'], 'nginx')
|
||||
self.assertEqual(resp.spec.template.metadata.labels['app'], 'nginx')
|
||||
self.assertEqual(resp.spec.template.spec.containers[0].name, 'nginx-app')
|
||||
self.assertEqual(resp.spec.template.spec.containers[0].image, 'nginx:1.15.4')
|
||||
|
||||
options = v1_delete_options.V1DeleteOptions()
|
||||
api.delete_namespaced_daemon_set(name, 'default', body=options)
|
64
kubernetes/e2e_test/test_batch.py
Normal file
64
kubernetes/e2e_test/test_batch.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 unittest
|
||||
import uuid
|
||||
|
||||
from kubernetes.client import api_client
|
||||
from kubernetes.client.api import batch_v1_api
|
||||
from kubernetes.e2e_test import base
|
||||
|
||||
|
||||
class TestClientBatch(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.config = base.get_e2e_configuration()
|
||||
|
||||
def test_job_apis(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = batch_v1_api.BatchV1Api(client)
|
||||
|
||||
name = 'test-job-' + str(uuid.uuid4())
|
||||
job_manifest = {
|
||||
'kind': 'Job',
|
||||
'spec': {
|
||||
'template':
|
||||
{'spec':
|
||||
{'containers': [
|
||||
{'image': 'busybox',
|
||||
'name': name,
|
||||
'command': ["sh", "-c", "sleep 5"]
|
||||
}],
|
||||
'restartPolicy': 'Never'},
|
||||
'metadata': {'name': name}}},
|
||||
'apiVersion': 'batch/v1',
|
||||
'metadata': {'name': name}}
|
||||
|
||||
create_job_resp = api.create_namespaced_job(
|
||||
body=job_manifest, namespace='default')
|
||||
self.assertEqual(name, create_job_resp.metadata.name)
|
||||
|
||||
resp = api.read_namespaced_job(
|
||||
name=name, namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertEqual(name, resp.spec.template.spec.containers[0].name)
|
||||
self.assertEqual('busybox', resp.spec.template.spec.containers[0].image)
|
||||
self.assertEqual('sh', resp.spec.template.spec.containers[0].command[0])
|
||||
self.assertEqual('-c', resp.spec.template.spec.containers[0].command[1])
|
||||
self.assertEqual('sleep 5', resp.spec.template.spec.containers[0].command[2])
|
||||
self.assertEqual('Never', resp.spec.template.spec.restart_policy)
|
||||
|
||||
api.delete_namespaced_job(
|
||||
name=name, namespace='default', propagation_policy='Background')
|
607
kubernetes/e2e_test/test_client.py
Normal file
607
kubernetes/e2e_test/test_client.py
Normal file
|
@ -0,0 +1,607 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 json
|
||||
import os
|
||||
import select
|
||||
import socket
|
||||
import time
|
||||
import unittest
|
||||
import uuid
|
||||
import six
|
||||
import io
|
||||
import gzip
|
||||
|
||||
from kubernetes.client import api_client
|
||||
from kubernetes.client.api import core_v1_api
|
||||
from kubernetes.e2e_test import base
|
||||
from kubernetes.stream import stream, portforward
|
||||
from kubernetes.stream.ws_client import ERROR_CHANNEL
|
||||
from kubernetes.client.rest import ApiException
|
||||
|
||||
import six.moves.urllib.request as urllib_request
|
||||
|
||||
if six.PY3:
|
||||
from http import HTTPStatus
|
||||
else:
|
||||
import httplib
|
||||
|
||||
|
||||
def short_uuid():
|
||||
id = str(uuid.uuid4())
|
||||
return id[-12:]
|
||||
|
||||
|
||||
def manifest_with_command(name, command):
|
||||
return {
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'Pod',
|
||||
'metadata': {
|
||||
'name': name
|
||||
},
|
||||
'spec': {
|
||||
'containers': [{
|
||||
'image': 'busybox',
|
||||
'name': 'sleep',
|
||||
"args": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
command
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestClient(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.config = base.get_e2e_configuration()
|
||||
|
||||
def test_pod_apis(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
name = 'busybox-test-' + short_uuid()
|
||||
pod_manifest = manifest_with_command(
|
||||
name, "while true;do date;sleep 5; done")
|
||||
|
||||
# wait for the default service account to be created
|
||||
timeout = time.time() + 30
|
||||
while True:
|
||||
if time.time() > timeout:
|
||||
print('timeout waiting for default service account creation')
|
||||
break
|
||||
try:
|
||||
resp = api.read_namespaced_service_account(name='default',
|
||||
namespace='default')
|
||||
except ApiException as e:
|
||||
if (six.PY3 and e.status != HTTPStatus.NOT_FOUND) or (
|
||||
six.PY3 is False and e.status != httplib.NOT_FOUND):
|
||||
print('error: %s' % e)
|
||||
self.fail(
|
||||
msg="unexpected error getting default service account")
|
||||
print('default service not found yet: %s' % e)
|
||||
time.sleep(1)
|
||||
continue
|
||||
self.assertEqual('default', resp.metadata.name)
|
||||
break
|
||||
|
||||
resp = api.create_namespaced_pod(body=pod_manifest,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status.phase)
|
||||
|
||||
while True:
|
||||
resp = api.read_namespaced_pod(name=name,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status.phase)
|
||||
if resp.status.phase != 'Pending':
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
exec_command = ['/bin/sh',
|
||||
'-c',
|
||||
'for i in $(seq 1 3); do date; done']
|
||||
resp = stream(api.connect_get_namespaced_pod_exec, name, 'default',
|
||||
command=exec_command,
|
||||
stderr=False, stdin=False,
|
||||
stdout=True, tty=False)
|
||||
print('EXEC response : %s (%s)' % (repr(resp), type(resp)))
|
||||
self.assertIsInstance(resp, str)
|
||||
self.assertEqual(3, len(resp.splitlines()))
|
||||
|
||||
exec_command = ['/bin/sh',
|
||||
'-c',
|
||||
'echo -n "This is a test string" | gzip']
|
||||
resp = stream(api.connect_get_namespaced_pod_exec, name, 'default',
|
||||
command=exec_command,
|
||||
stderr=False, stdin=False,
|
||||
stdout=True, tty=False,
|
||||
binary=True)
|
||||
print('EXEC response : %s (%s)' % (repr(resp), type(resp)))
|
||||
self.assertIsInstance(resp, bytes)
|
||||
self.assertEqual("This is a test string", gzip.decompress(resp).decode('utf-8'))
|
||||
|
||||
exec_command = 'uptime'
|
||||
resp = stream(api.connect_post_namespaced_pod_exec, name, 'default',
|
||||
command=exec_command,
|
||||
stderr=False, stdin=False,
|
||||
stdout=True, tty=False)
|
||||
print('EXEC response : %s' % repr(resp))
|
||||
self.assertEqual(1, len(resp.splitlines()))
|
||||
|
||||
resp = stream(api.connect_post_namespaced_pod_exec, name, 'default',
|
||||
command='/bin/sh',
|
||||
stderr=True, stdin=True,
|
||||
stdout=True, tty=False,
|
||||
_preload_content=False)
|
||||
resp.write_stdin("echo test string 1\n")
|
||||
line = resp.readline_stdout(timeout=5)
|
||||
self.assertFalse(resp.peek_stderr())
|
||||
self.assertEqual("test string 1", line)
|
||||
resp.write_stdin("echo test string 2 >&2\n")
|
||||
line = resp.readline_stderr(timeout=5)
|
||||
self.assertFalse(resp.peek_stdout())
|
||||
self.assertEqual("test string 2", line)
|
||||
resp.write_stdin("exit\n")
|
||||
resp.update(timeout=5)
|
||||
while True:
|
||||
line = resp.read_channel(ERROR_CHANNEL)
|
||||
if line != '':
|
||||
break
|
||||
time.sleep(1)
|
||||
status = json.loads(line)
|
||||
self.assertEqual(status['status'], 'Success')
|
||||
resp.update(timeout=5)
|
||||
self.assertFalse(resp.is_open())
|
||||
|
||||
resp = stream(api.connect_post_namespaced_pod_exec, name, 'default',
|
||||
command='/bin/sh',
|
||||
stderr=True, stdin=True,
|
||||
stdout=True, tty=False,
|
||||
binary=True,
|
||||
_preload_content=False)
|
||||
resp.write_stdin(b"echo test string 1\n")
|
||||
line = resp.readline_stdout(timeout=5)
|
||||
self.assertFalse(resp.peek_stderr())
|
||||
self.assertEqual(b"test string 1", line)
|
||||
resp.write_stdin(b"echo test string 2 >&2\n")
|
||||
line = resp.readline_stderr(timeout=5)
|
||||
self.assertFalse(resp.peek_stdout())
|
||||
self.assertEqual(b"test string 2", line)
|
||||
resp.write_stdin(b"exit\n")
|
||||
resp.update(timeout=5)
|
||||
while True:
|
||||
line = resp.read_channel(ERROR_CHANNEL)
|
||||
if len(line) != 0:
|
||||
break
|
||||
time.sleep(1)
|
||||
status = json.loads(line)
|
||||
self.assertEqual(status['status'], 'Success')
|
||||
resp.update(timeout=5)
|
||||
self.assertFalse(resp.is_open())
|
||||
|
||||
number_of_pods = len(api.list_pod_for_all_namespaces().items)
|
||||
self.assertTrue(number_of_pods > 0)
|
||||
|
||||
resp = api.delete_namespaced_pod(name=name, body={},
|
||||
namespace='default')
|
||||
|
||||
def test_exit_code(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
name = 'busybox-test-' + short_uuid()
|
||||
pod_manifest = manifest_with_command(
|
||||
name, "while true;do date;sleep 5; done")
|
||||
|
||||
# wait for the default service account to be created
|
||||
timeout = time.time() + 30
|
||||
while True:
|
||||
if time.time() > timeout:
|
||||
print('timeout waiting for default service account creation')
|
||||
break
|
||||
|
||||
try:
|
||||
resp = api.read_namespaced_service_account(name='default',
|
||||
namespace='default')
|
||||
except ApiException as e:
|
||||
if (six.PY3 and e.status != HTTPStatus.NOT_FOUND) or (
|
||||
six.PY3 is False and e.status != httplib.NOT_FOUND):
|
||||
print('error: %s' % e)
|
||||
self.fail(
|
||||
msg="unexpected error getting default service account")
|
||||
print('default service not found yet: %s' % e)
|
||||
time.sleep(1)
|
||||
continue
|
||||
self.assertEqual('default', resp.metadata.name)
|
||||
break
|
||||
|
||||
resp = api.create_namespaced_pod(body=pod_manifest,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status.phase)
|
||||
|
||||
while True:
|
||||
resp = api.read_namespaced_pod(name=name,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status.phase)
|
||||
if resp.status.phase == 'Running':
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
commands_expected_values = (
|
||||
(["false", 1]),
|
||||
(["/bin/sh", "-c", "sleep 1; exit 3"], 3),
|
||||
(["true", 0]),
|
||||
(["/bin/sh", "-c", "ls /"], 0)
|
||||
)
|
||||
for command, value in commands_expected_values:
|
||||
client = stream(
|
||||
api.connect_get_namespaced_pod_exec,
|
||||
name,
|
||||
'default',
|
||||
command=command,
|
||||
stderr=True,
|
||||
stdin=False,
|
||||
stdout=True,
|
||||
tty=False,
|
||||
_preload_content=False)
|
||||
|
||||
self.assertIsNone(client.returncode)
|
||||
client.run_forever(timeout=10)
|
||||
self.assertEqual(client.returncode, value)
|
||||
self.assertEqual(client.returncode, value) # check idempotence
|
||||
|
||||
resp = api.delete_namespaced_pod(name=name, body={},
|
||||
namespace='default')
|
||||
|
||||
def test_portforward_raw(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
with open(os.path.join(os.path.dirname(__file__), 'port_server.py')) as fh:
|
||||
port_server_py = fh.read()
|
||||
name = 'portforward-raw-' + short_uuid()
|
||||
resp = api.create_namespaced_config_map(
|
||||
body={
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'ConfigMap',
|
||||
'metadata': {
|
||||
'name': name,
|
||||
},
|
||||
'data': {
|
||||
'port-server.py': port_server_py,
|
||||
}
|
||||
},
|
||||
namespace='default',
|
||||
)
|
||||
resp = api.create_namespaced_pod(
|
||||
body={
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'Pod',
|
||||
'metadata': {
|
||||
'name': name
|
||||
},
|
||||
'spec': {
|
||||
'containers': [
|
||||
{
|
||||
'name': 'port-server',
|
||||
'image': 'python',
|
||||
'command': [
|
||||
'python', '-u', '/opt/port-server.py', '1234', '1235',
|
||||
],
|
||||
'volumeMounts': [
|
||||
{
|
||||
'name': 'port-server',
|
||||
'mountPath': '/opt',
|
||||
'readOnly': True,
|
||||
},
|
||||
],
|
||||
'startupProbe': {
|
||||
'tcpSocket': {
|
||||
'port': 1235,
|
||||
},
|
||||
'periodSeconds': 1,
|
||||
'failureThreshold': 30,
|
||||
},
|
||||
},
|
||||
],
|
||||
'restartPolicy': 'Never',
|
||||
'volumes': [
|
||||
{
|
||||
'name': 'port-server',
|
||||
'configMap': {
|
||||
'name': name,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
namespace='default',
|
||||
)
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status.phase)
|
||||
|
||||
timeout = time.time() + 60
|
||||
while True:
|
||||
resp = api.read_namespaced_pod(name=name,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
if resp.status.phase == 'Running':
|
||||
if resp.status.container_statuses[0].ready:
|
||||
break
|
||||
else:
|
||||
self.assertEqual(resp.status.phase, 'Pending')
|
||||
self.assertTrue(time.time() < timeout)
|
||||
time.sleep(1)
|
||||
|
||||
for ix in range(10):
|
||||
ix = str(ix + 1).encode()
|
||||
pf = portforward(api.connect_get_namespaced_pod_portforward,
|
||||
name, 'default',
|
||||
ports='1234,1235,1236')
|
||||
self.assertTrue(pf.connected)
|
||||
sock1234 = pf.socket(1234)
|
||||
sock1235 = pf.socket(1235)
|
||||
sock1234.setblocking(True)
|
||||
sock1235.setblocking(True)
|
||||
sent1234 = b'Test ' + ix + b' port 1234 forwarding'
|
||||
sent1235 = b'Test ' + ix + b' port 1235 forwarding'
|
||||
sock1234.sendall(sent1234)
|
||||
sock1235.sendall(sent1235)
|
||||
reply1234 = b''
|
||||
reply1235 = b''
|
||||
timeout = time.time() + 60
|
||||
while reply1234 != sent1234 or reply1235 != sent1235:
|
||||
self.assertNotEqual(sock1234.fileno(), -1)
|
||||
self.assertNotEqual(sock1235.fileno(), -1)
|
||||
self.assertTrue(time.time() < timeout)
|
||||
r, _w, _x = select.select([sock1234, sock1235], [], [], 1)
|
||||
if sock1234 in r:
|
||||
data = sock1234.recv(1024)
|
||||
self.assertNotEqual(data, b'', 'Unexpected socket close')
|
||||
reply1234 += data
|
||||
self.assertTrue(sent1234.startswith(reply1234))
|
||||
if sock1235 in r:
|
||||
data = sock1235.recv(1024)
|
||||
self.assertNotEqual(data, b'', 'Unexpected socket close')
|
||||
reply1235 += data
|
||||
self.assertTrue(sent1235.startswith(reply1235))
|
||||
self.assertTrue(pf.connected)
|
||||
|
||||
sock = pf.socket(1236)
|
||||
sock.setblocking(True)
|
||||
self.assertEqual(sock.recv(1024), b'')
|
||||
self.assertIsNotNone(pf.error(1236))
|
||||
sock.close()
|
||||
|
||||
for sock in (sock1234, sock1235):
|
||||
self.assertTrue(pf.connected)
|
||||
sent = b'Another test ' + ix + b' using fileno ' + str(sock.fileno()).encode()
|
||||
sock.sendall(sent)
|
||||
reply = b''
|
||||
timeout = time.time() + 60
|
||||
while reply != sent:
|
||||
self.assertNotEqual(sock.fileno(), -1)
|
||||
self.assertTrue(time.time() < timeout)
|
||||
r, _w, _x = select.select([sock], [], [], 1)
|
||||
if r:
|
||||
data = sock.recv(1024)
|
||||
self.assertNotEqual(data, b'', 'Unexpected socket close')
|
||||
reply += data
|
||||
self.assertTrue(sent.startswith(reply))
|
||||
sock.close()
|
||||
time.sleep(1)
|
||||
self.assertFalse(pf.connected)
|
||||
self.assertIsNone(pf.error(1234))
|
||||
self.assertIsNone(pf.error(1235))
|
||||
|
||||
resp = api.delete_namespaced_pod(name=name, namespace='default')
|
||||
resp = api.delete_namespaced_config_map(name=name, namespace='default')
|
||||
|
||||
def test_portforward_http(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
name = 'portforward-http-' + short_uuid()
|
||||
pod_manifest = {
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'Pod',
|
||||
'metadata': {
|
||||
'name': name
|
||||
},
|
||||
'spec': {
|
||||
'containers': [{
|
||||
'name': 'nginx',
|
||||
'image': 'nginx',
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
resp = api.create_namespaced_pod(body=pod_manifest,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status.phase)
|
||||
|
||||
while True:
|
||||
resp = api.read_namespaced_pod(name=name,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status.phase)
|
||||
if resp.status.phase != 'Pending':
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
def kubernetes_create_connection(address, *args, **kwargs):
|
||||
dns_name = address[0]
|
||||
if isinstance(dns_name, bytes):
|
||||
dns_name = dns_name.decode()
|
||||
dns_name = dns_name.split(".")
|
||||
if len(dns_name) != 3 or dns_name[2] != "kubernetes":
|
||||
return socket_create_connection(address, *args, **kwargs)
|
||||
pf = portforward(api.connect_get_namespaced_pod_portforward,
|
||||
dns_name[0], dns_name[1], ports=str(address[1]))
|
||||
return pf.socket(address[1])
|
||||
|
||||
socket_create_connection = socket.create_connection
|
||||
try:
|
||||
socket.create_connection = kubernetes_create_connection
|
||||
response = urllib_request.urlopen(
|
||||
'http://%s.default.kubernetes/' % name)
|
||||
html = response.read().decode('utf-8')
|
||||
finally:
|
||||
socket.create_connection = socket_create_connection
|
||||
|
||||
self.assertEqual(response.code, 200)
|
||||
self.assertTrue('<h1>Welcome to nginx!</h1>' in html)
|
||||
|
||||
resp = api.delete_namespaced_pod(name=name, body={},
|
||||
namespace='default')
|
||||
|
||||
def test_service_apis(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
name = 'frontend-' + short_uuid()
|
||||
service_manifest = {'apiVersion': 'v1',
|
||||
'kind': 'Service',
|
||||
'metadata': {'labels': {'name': name},
|
||||
'name': name,
|
||||
'resourceversion': 'v1'},
|
||||
'spec': {'ports': [{'name': 'port',
|
||||
'port': 80,
|
||||
'protocol': 'TCP',
|
||||
'targetPort': 80}],
|
||||
'selector': {'name': name}}}
|
||||
|
||||
resp = api.create_namespaced_service(body=service_manifest,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status)
|
||||
|
||||
resp = api.read_namespaced_service(name=name,
|
||||
namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertTrue(resp.status)
|
||||
|
||||
service_manifest['spec']['ports'] = [{'name': 'new',
|
||||
'port': 8080,
|
||||
'protocol': 'TCP',
|
||||
'targetPort': 8080}]
|
||||
resp = api.patch_namespaced_service(body=service_manifest,
|
||||
name=name,
|
||||
namespace='default')
|
||||
self.assertEqual(2, len(resp.spec.ports))
|
||||
self.assertTrue(resp.status)
|
||||
|
||||
resp = api.delete_namespaced_service(name=name, body={},
|
||||
namespace='default')
|
||||
|
||||
def test_replication_controller_apis(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
name = 'frontend-' + short_uuid()
|
||||
rc_manifest = {
|
||||
'apiVersion': 'v1',
|
||||
'kind': 'ReplicationController',
|
||||
'metadata': {'labels': {'name': name},
|
||||
'name': name},
|
||||
'spec': {'replicas': 2,
|
||||
'selector': {'name': name},
|
||||
'template': {'metadata': {
|
||||
'labels': {'name': name}},
|
||||
'spec': {'containers': [{
|
||||
'image': 'nginx',
|
||||
'name': 'nginx',
|
||||
'ports': [{'containerPort': 80,
|
||||
'protocol': 'TCP'}]}]}}}}
|
||||
|
||||
resp = api.create_namespaced_replication_controller(
|
||||
body=rc_manifest, namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertEqual(2, resp.spec.replicas)
|
||||
|
||||
resp = api.read_namespaced_replication_controller(
|
||||
name=name, namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
self.assertEqual(2, resp.spec.replicas)
|
||||
|
||||
resp = api.delete_namespaced_replication_controller(
|
||||
name=name, namespace='default', propagation_policy='Background')
|
||||
|
||||
def test_configmap_apis(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
name = 'test-configmap-' + short_uuid()
|
||||
test_configmap = {
|
||||
"kind": "ConfigMap",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": name,
|
||||
"labels": {"e2e-tests": "true"},
|
||||
},
|
||||
"data": {
|
||||
"config.json": "{\"command\":\"/usr/bin/mysqld_safe\"}",
|
||||
"frontend.cnf": "[mysqld]\nbind-address = 10.0.0.3\nport = 3306\n"
|
||||
}
|
||||
}
|
||||
|
||||
resp = api.create_namespaced_config_map(
|
||||
body=test_configmap, namespace='default'
|
||||
)
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
|
||||
resp = api.read_namespaced_config_map(
|
||||
name=name, namespace='default')
|
||||
self.assertEqual(name, resp.metadata.name)
|
||||
|
||||
json_patch_name = "json_patch_name"
|
||||
json_patch_body = [{"op": "replace", "path": "/data",
|
||||
"value": {"new_value": json_patch_name}}]
|
||||
resp = api.patch_namespaced_config_map(
|
||||
name=name, namespace='default', body=json_patch_body)
|
||||
self.assertEqual(json_patch_name, resp.data["new_value"])
|
||||
self.assertEqual(None, resp.data.get("config.json"))
|
||||
self.assertEqual(None, resp.data.get("frontend.cnf"))
|
||||
|
||||
merge_patch_name = "merge_patch_name"
|
||||
merge_patch_body = {"data": {"new_value": merge_patch_name}}
|
||||
resp = api.patch_namespaced_config_map(
|
||||
name=name, namespace='default', body=merge_patch_body)
|
||||
self.assertEqual(merge_patch_name, resp.data["new_value"])
|
||||
self.assertEqual(None, resp.data.get("config.json"))
|
||||
self.assertEqual(None, resp.data.get("frontend.cnf"))
|
||||
|
||||
resp = api.delete_namespaced_config_map(
|
||||
name=name, body={}, namespace='default')
|
||||
|
||||
resp = api.list_namespaced_config_map(
|
||||
'default', pretty=True, label_selector="e2e-tests=true")
|
||||
self.assertEqual([], resp.items)
|
||||
|
||||
def test_node_apis(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
for item in api.list_node().items:
|
||||
node = api.read_node(name=item.metadata.name)
|
||||
self.assertTrue(len(node.metadata.labels) > 0)
|
||||
self.assertTrue(isinstance(node.metadata.labels, dict))
|
607
kubernetes/e2e_test/test_utils.py
Normal file
607
kubernetes/e2e_test/test_utils.py
Normal file
|
@ -0,0 +1,607 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 unittest
|
||||
from os import path
|
||||
|
||||
import yaml
|
||||
|
||||
from kubernetes import utils, client
|
||||
from kubernetes.client.rest import ApiException
|
||||
from kubernetes.e2e_test import base
|
||||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.config = base.get_e2e_configuration()
|
||||
cls.path_prefix = "kubernetes/e2e_test/test_yaml/"
|
||||
cls.test_namespace = "e2e-test-utils"
|
||||
k8s_client = client.api_client.ApiClient(configuration=cls.config)
|
||||
core_v1 = client.CoreV1Api(api_client=k8s_client)
|
||||
body = client.V1Namespace(
|
||||
metadata=client.V1ObjectMeta(
|
||||
name=cls.test_namespace))
|
||||
core_v1.create_namespace(body=body)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
k8s_client = client.api_client.ApiClient(configuration=cls.config)
|
||||
core_v1 = client.CoreV1Api(api_client=k8s_client)
|
||||
core_v1.delete_namespace(name=cls.test_namespace)
|
||||
|
||||
# Tests for creating individual API objects
|
||||
|
||||
def test_create_apps_deployment_from_yaml(self):
|
||||
"""
|
||||
Should be able to create an apps/v1 deployment.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "apps-deployment.yaml")
|
||||
app_api = client.AppsV1Api(k8s_client)
|
||||
dep = app_api.read_namespaced_deployment(name="nginx-app",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
self.assertEqual("nginx-app", dep.metadata.name)
|
||||
self.assertEqual("nginx:1.15.4", dep.spec.template.spec.containers[0].image)
|
||||
self.assertEqual(80, dep.spec.template.spec.containers[0].ports[0].container_port)
|
||||
self.assertEqual("nginx", dep.spec.template.spec.containers[0].name)
|
||||
self.assertEqual("nginx", dep.spec.template.metadata.labels["app"])
|
||||
self.assertEqual(3, dep.spec.replicas)
|
||||
|
||||
while True:
|
||||
try:
|
||||
app_api.delete_namespaced_deployment(
|
||||
name="nginx-app", namespace="default",
|
||||
body={})
|
||||
break
|
||||
except ApiException:
|
||||
continue
|
||||
|
||||
def test_create_apps_deployment_from_yaml_with_apply_is_idempotent(self):
|
||||
"""
|
||||
Should be able to create an apps/v1 deployment.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
try:
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "apps-deployment.yaml")
|
||||
app_api = client.AppsV1Api(k8s_client)
|
||||
dep = app_api.read_namespaced_deployment(name="nginx-app",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
self.assertEqual("nginx-app", dep.metadata.name)
|
||||
self.assertEqual("nginx:1.15.4", dep.spec.template.spec.containers[0].image)
|
||||
self.assertEqual(80, dep.spec.template.spec.containers[0].ports[0].container_port)
|
||||
self.assertEqual("nginx", dep.spec.template.spec.containers[0].name)
|
||||
self.assertEqual("nginx", dep.spec.template.metadata.labels["app"])
|
||||
self.assertEqual(3, dep.spec.replicas)
|
||||
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "apps-deployment.yaml", apply=True)
|
||||
dep = app_api.read_namespaced_deployment(name="nginx-app",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
self.assertEqual("nginx-app", dep.metadata.name)
|
||||
self.assertEqual("nginx:1.15.4", dep.spec.template.spec.containers[0].image)
|
||||
self.assertEqual(80, dep.spec.template.spec.containers[0].ports[0].container_port)
|
||||
self.assertEqual("nginx", dep.spec.template.spec.containers[0].name)
|
||||
self.assertEqual("nginx", dep.spec.template.metadata.labels["app"])
|
||||
self.assertEqual(3, dep.spec.replicas)
|
||||
except Exception as e:
|
||||
self.fail(e)
|
||||
finally:
|
||||
while True:
|
||||
try:
|
||||
app_api.delete_namespaced_deployment(
|
||||
name="nginx-app", namespace="default",
|
||||
body={})
|
||||
break
|
||||
except ApiException:
|
||||
continue
|
||||
|
||||
def test_create_apps_deployment_from_yaml_object(self):
|
||||
"""
|
||||
Should be able to pass YAML objects directly to helper function.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
_path = self.path_prefix + "apps-deployment.yaml"
|
||||
with open(path.abspath(_path)) as f:
|
||||
yaml_objects = yaml.safe_load_all(f)
|
||||
utils.create_from_yaml(
|
||||
k8s_client,
|
||||
yaml_objects=yaml_objects,
|
||||
)
|
||||
app_api = client.AppsV1Api(k8s_client)
|
||||
dep = app_api.read_namespaced_deployment(name="nginx-app",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
self.assertEqual("nginx-app", dep.metadata.name)
|
||||
self.assertEqual("nginx:1.15.4", dep.spec.template.spec.containers[0].image)
|
||||
self.assertEqual(80, dep.spec.template.spec.containers[0].ports[0].container_port)
|
||||
self.assertEqual("nginx", dep.spec.template.spec.containers[0].name)
|
||||
self.assertEqual("nginx", dep.spec.template.metadata.labels["app"])
|
||||
self.assertEqual(3, dep.spec.replicas)
|
||||
|
||||
while True:
|
||||
try:
|
||||
app_api.delete_namespaced_deployment(
|
||||
name="nginx-app", namespace="default",
|
||||
body={})
|
||||
break
|
||||
except ApiException:
|
||||
continue
|
||||
|
||||
def test_create_apps_deployment_from_yaml_obj(self):
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
with open(self.path_prefix + "apps-deployment.yaml") as f:
|
||||
yml_obj = yaml.safe_load(f)
|
||||
|
||||
yml_obj["metadata"]["name"] = "nginx-app-3"
|
||||
|
||||
utils.create_from_dict(k8s_client, yml_obj)
|
||||
|
||||
app_api = client.AppsV1Api(k8s_client)
|
||||
dep = app_api.read_namespaced_deployment(name="nginx-app-3",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
self.assertEqual("nginx-app-3", dep.metadata.name)
|
||||
self.assertEqual("nginx:1.15.4", dep.spec.template.spec.containers[0].image)
|
||||
self.assertEqual(80, dep.spec.template.spec.containers[0].ports[0].container_port)
|
||||
self.assertEqual("nginx", dep.spec.template.spec.containers[0].name)
|
||||
self.assertEqual("nginx", dep.spec.template.metadata.labels["app"])
|
||||
self.assertEqual(3, dep.spec.replicas)
|
||||
|
||||
app_api.delete_namespaced_deployment(
|
||||
name="nginx-app-3", namespace="default",
|
||||
body={})
|
||||
|
||||
def test_create_pod_from_yaml(self):
|
||||
"""
|
||||
Should be able to create a pod.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "core-pod.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
pod = core_api.read_namespaced_pod(name="myapp-pod",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(pod)
|
||||
self.assertEqual("myapp-pod", pod.metadata.name)
|
||||
self.assertEqual("busybox", pod.spec.containers[0].image)
|
||||
self.assertEqual("myapp-container", pod.spec.containers[0].name)
|
||||
|
||||
core_api.delete_namespaced_pod(
|
||||
name="myapp-pod", namespace="default",
|
||||
body={})
|
||||
|
||||
def test_create_service_from_yaml(self):
|
||||
"""
|
||||
Should be able to create a service.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "core-service.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
svc = core_api.read_namespaced_service(name="my-service",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(svc)
|
||||
self.assertEqual("my-service", svc.metadata.name)
|
||||
self.assertEqual("MyApp", svc.spec.selector["app"])
|
||||
|
||||
core_api.delete_namespaced_service(
|
||||
name="my-service", namespace="default",
|
||||
body={})
|
||||
|
||||
def test_create_namespace_from_yaml(self):
|
||||
"""
|
||||
Should be able to create a namespace.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "core-namespace.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
nmsp = core_api.read_namespace(name="development")
|
||||
|
||||
self.assertIsNotNone(nmsp)
|
||||
self.assertEqual("development", nmsp.metadata.name)
|
||||
|
||||
core_api.delete_namespace(name="development", body={})
|
||||
|
||||
def test_create_rbac_role_from_yaml(self):
|
||||
"""
|
||||
Should be able to create a rbac role.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "rbac-role.yaml")
|
||||
rbac_api = client.RbacAuthorizationV1Api(k8s_client)
|
||||
rbac_role = rbac_api.read_namespaced_role(
|
||||
name="pod-reader", namespace="default")
|
||||
self.assertIsNotNone(rbac_role)
|
||||
self.assertEqual("pod-reader", rbac_role.metadata.name)
|
||||
self.assertEqual("pods", rbac_role.rules[0].resources[0])
|
||||
|
||||
rbac_api.delete_namespaced_role(
|
||||
name="pod-reader", namespace="default", body={})
|
||||
|
||||
def test_create_rbac_role_from_yaml_with_verbose_enabled(self):
|
||||
"""
|
||||
Should be able to create a rbac role with verbose enabled.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "rbac-role.yaml", verbose=True)
|
||||
rbac_api = client.RbacAuthorizationV1Api(k8s_client)
|
||||
rbac_role = rbac_api.read_namespaced_role(
|
||||
name="pod-reader", namespace="default")
|
||||
self.assertIsNotNone(rbac_role)
|
||||
self.assertEqual("pod-reader", rbac_role.metadata.name)
|
||||
self.assertEqual("pods", rbac_role.rules[0].resources[0])
|
||||
|
||||
rbac_api.delete_namespaced_role(
|
||||
name="pod-reader", namespace="default", body={})
|
||||
|
||||
def test_create_deployment_non_default_namespace_from_yaml(self):
|
||||
"""
|
||||
Should be able to create a namespace "dep",
|
||||
and then create a deployment in the just-created namespace.
|
||||
"""
|
||||
k8s_client = client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "dep-namespace.yaml")
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "dep-deployment.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
ext_api = client.AppsV1Api(k8s_client)
|
||||
nmsp = core_api.read_namespace(name="dep")
|
||||
self.assertIsNotNone(nmsp)
|
||||
self.assertEqual("dep", nmsp.metadata.name)
|
||||
|
||||
dep = ext_api.read_namespaced_deployment(name="nginx-deployment",
|
||||
namespace="dep")
|
||||
self.assertIsNotNone(dep)
|
||||
ext_api.delete_namespaced_deployment(
|
||||
name="nginx-deployment", namespace="dep",
|
||||
body={})
|
||||
core_api.delete_namespace(name="dep", body={})
|
||||
|
||||
def test_create_apiservice_from_yaml_with_conflict(self):
|
||||
"""
|
||||
Should be able to create an API service.
|
||||
Should verify that creating the same API service should
|
||||
fail due to conflict.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "api-service.yaml")
|
||||
reg_api = client.ApiregistrationV1Api(k8s_client)
|
||||
svc = reg_api.read_api_service(
|
||||
name="v1alpha1.wardle.k8s.io")
|
||||
self.assertIsNotNone(svc)
|
||||
self.assertEqual("v1alpha1.wardle.k8s.io", svc.metadata.name)
|
||||
self.assertEqual("wardle.k8s.io", svc.spec.group)
|
||||
self.assertEqual("v1alpha1", svc.spec.version)
|
||||
|
||||
with self.assertRaises(utils.FailToCreateError) as cm:
|
||||
utils.create_from_yaml(
|
||||
k8s_client, "kubernetes/e2e_test/test_yaml/api-service.yaml")
|
||||
exp_error = ('Error from server (Conflict): '
|
||||
'{"kind":"Status","apiVersion":"v1","metadata":{},'
|
||||
'"status":"Failure",'
|
||||
'"message":"apiservices.apiregistration.k8s.io '
|
||||
'\\"v1alpha1.wardle.k8s.io\\" already exists",'
|
||||
'"reason":"AlreadyExists",'
|
||||
'"details":{"name":"v1alpha1.wardle.k8s.io",'
|
||||
'"group":"apiregistration.k8s.io","kind":"apiservices"},'
|
||||
'"code":409}\n'
|
||||
)
|
||||
self.assertEqual(exp_error, str(cm.exception))
|
||||
reg_api.delete_api_service(
|
||||
name="v1alpha1.wardle.k8s.io", body={})
|
||||
|
||||
# Tests for creating API objects from lists
|
||||
|
||||
def test_create_general_list_from_yaml(self):
|
||||
"""
|
||||
Should be able to create a service and a deployment
|
||||
from a kind: List yaml file
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "list.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
ext_api = client.AppsV1Api(k8s_client)
|
||||
svc = core_api.read_namespaced_service(name="list-service-test",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(svc)
|
||||
self.assertEqual("list-service-test", svc.metadata.name)
|
||||
self.assertEqual("list-deployment-test", svc.spec.selector["app"])
|
||||
|
||||
dep = ext_api.read_namespaced_deployment(name="list-deployment-test",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
self.assertEqual("list-deployment-test", dep.metadata.name)
|
||||
self.assertEqual("nginx:1.15.4", dep.spec.template.spec.containers[0].image)
|
||||
self.assertEqual(1, dep.spec.replicas)
|
||||
|
||||
core_api.delete_namespaced_service(name="list-service-test",
|
||||
namespace="default", body={})
|
||||
ext_api.delete_namespaced_deployment(name="list-deployment-test",
|
||||
namespace="default", body={})
|
||||
|
||||
def test_create_namespace_list_from_yaml(self):
|
||||
"""
|
||||
Should be able to create two namespaces
|
||||
from a kind: NamespaceList yaml file
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "namespace-list.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
nmsp_1 = core_api.read_namespace(name="mock-1")
|
||||
self.assertIsNotNone(nmsp_1)
|
||||
self.assertEqual("mock-1", nmsp_1.metadata.name)
|
||||
self.assertEqual("mock-1", nmsp_1.metadata.labels["name"])
|
||||
|
||||
nmsp_2 = core_api.read_namespace(name="mock-2")
|
||||
self.assertIsNotNone(nmsp_2)
|
||||
self.assertEqual("mock-2", nmsp_2.metadata.name)
|
||||
self.assertEqual("mock-2", nmsp_2.metadata.labels["name"])
|
||||
|
||||
core_api.delete_namespace(name="mock-1", body={})
|
||||
core_api.delete_namespace(name="mock-2", body={})
|
||||
|
||||
def test_create_implicit_service_list_from_yaml_with_conflict(self):
|
||||
"""
|
||||
Should be able to create two services from a kind: ServiceList
|
||||
json file that implicitly indicates the kind of individual objects
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
with self.assertRaises(utils.FailToCreateError):
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "implicit-svclist.json")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
svc_3 = core_api.read_namespaced_service(name="mock-3",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(svc_3)
|
||||
self.assertEqual("mock-3", svc_3.metadata.name)
|
||||
self.assertEqual("mock-3", svc_3.metadata.labels["app"])
|
||||
|
||||
svc_4 = core_api.read_namespaced_service(name="mock-4",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(svc_4)
|
||||
self.assertEqual("mock-4", svc_4.metadata.name)
|
||||
self.assertEqual("mock-4", svc_4.metadata.labels["app"])
|
||||
|
||||
core_api.delete_namespaced_service(name="mock-3",
|
||||
namespace="default", body={})
|
||||
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)
|
||||
self.assertEqual("mock", svc.metadata.name)
|
||||
self.assertEqual("mock", svc.metadata.labels["app"])
|
||||
self.assertEqual("mock", svc.spec.selector["app"])
|
||||
|
||||
ctr = core_api.read_namespaced_replication_controller(
|
||||
name="mock", namespace="default")
|
||||
self.assertIsNotNone(ctr)
|
||||
self.assertEqual("mock", ctr.metadata.name)
|
||||
self.assertEqual("mock", ctr.spec.template.metadata.labels["app"])
|
||||
self.assertEqual("mock", ctr.spec.selector["app"])
|
||||
self.assertEqual(1, ctr.spec.replicas)
|
||||
self.assertEqual("k8s.gcr.io/pause:2.0", ctr.spec.template.spec.containers[0].image)
|
||||
self.assertEqual("mock-container", ctr.spec.template.spec.containers[0].name)
|
||||
|
||||
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):
|
||||
"""
|
||||
Should be able to create a service and a replication controller
|
||||
from a multi-resource yaml file
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "multi-resource.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
svc = core_api.read_namespaced_service(name="mock",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(svc)
|
||||
self.assertEqual("mock", svc.metadata.name)
|
||||
self.assertEqual("mock", svc.metadata.labels["app"])
|
||||
self.assertEqual("mock", svc.spec.selector["app"])
|
||||
|
||||
ctr = core_api.read_namespaced_replication_controller(
|
||||
name="mock", namespace="default")
|
||||
self.assertIsNotNone(ctr)
|
||||
self.assertEqual("mock", ctr.metadata.name)
|
||||
self.assertEqual("mock", ctr.spec.template.metadata.labels["app"])
|
||||
self.assertEqual("mock", ctr.spec.selector["app"])
|
||||
self.assertEqual(1, ctr.spec.replicas)
|
||||
self.assertEqual("k8s.gcr.io/pause:2.0", ctr.spec.template.spec.containers[0].image)
|
||||
self.assertEqual("mock-container", ctr.spec.template.spec.containers[0].name)
|
||||
|
||||
core_api.delete_namespaced_replication_controller(
|
||||
name="mock", namespace="default", propagation_policy="Background")
|
||||
core_api.delete_namespaced_service(name="mock",
|
||||
namespace="default", body={})
|
||||
|
||||
def test_create_from_list_in_multi_resource_yaml(self):
|
||||
"""
|
||||
Should be able to create the items in the PodList and a deployment
|
||||
specified in the multi-resource file
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "multi-resource-with-list.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
app_api = client.AppsV1Api(k8s_client)
|
||||
pod_0 = core_api.read_namespaced_pod(
|
||||
name="mock-pod-0", namespace="default")
|
||||
self.assertIsNotNone(pod_0)
|
||||
self.assertEqual("mock-pod-0", pod_0.metadata.name)
|
||||
self.assertEqual("mock-pod-0", pod_0.metadata.labels["app"])
|
||||
self.assertEqual("mock-pod-0", pod_0.spec.containers[0].name)
|
||||
self.assertEqual("busybox", pod_0.spec.containers[0].image)
|
||||
|
||||
pod_1 = core_api.read_namespaced_pod(
|
||||
name="mock-pod-1", namespace="default")
|
||||
self.assertIsNotNone(pod_1)
|
||||
self.assertEqual("mock-pod-1", pod_1.metadata.name)
|
||||
self.assertEqual("mock-pod-1", pod_1.metadata.labels["app"])
|
||||
self.assertEqual("mock-pod-1", pod_1.spec.containers[0].name)
|
||||
self.assertEqual("busybox", pod_1.spec.containers[0].image)
|
||||
|
||||
dep = app_api.read_namespaced_deployment(
|
||||
name="mock", namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
self.assertEqual("mock", dep.metadata.name)
|
||||
self.assertEqual("mock", dep.spec.template.metadata.labels["app"])
|
||||
self.assertEqual(3, dep.spec.replicas)
|
||||
|
||||
core_api.delete_namespaced_pod(
|
||||
name="mock-pod-0", namespace="default", body={})
|
||||
core_api.delete_namespaced_pod(
|
||||
name="mock-pod-1", namespace="default", body={})
|
||||
app_api.delete_namespaced_deployment(
|
||||
name="mock", namespace="default", body={})
|
||||
|
||||
def test_create_from_multi_resource_yaml_with_conflict(self):
|
||||
"""
|
||||
Should be able to create a service from the first yaml file.
|
||||
Should fail to create the same service from the second yaml file
|
||||
and create a replication controller.
|
||||
Should raise an exception for failure to create the same service twice.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "yaml-conflict-first.yaml")
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
svc = core_api.read_namespaced_service(name="mock-2",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(svc)
|
||||
self.assertEqual("mock-2", svc.metadata.name)
|
||||
self.assertEqual("mock-2", svc.metadata.labels["app"])
|
||||
self.assertEqual("mock-2", svc.spec.selector["app"])
|
||||
self.assertEqual(99, svc.spec.ports[0].port)
|
||||
|
||||
with self.assertRaises(utils.FailToCreateError) as cm:
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "yaml-conflict-multi.yaml")
|
||||
exp_error = ('Error from server (Conflict): {"kind":"Status",'
|
||||
'"apiVersion":"v1","metadata":{},"status":"Failure",'
|
||||
'"message":"services \\"mock-2\\" already exists",'
|
||||
'"reason":"AlreadyExists","details":{"name":"mock-2",'
|
||||
'"kind":"services"},"code":409}\n'
|
||||
)
|
||||
self.assertEqual(exp_error, str(cm.exception))
|
||||
ctr = core_api.read_namespaced_replication_controller(
|
||||
name="mock-2", namespace="default")
|
||||
self.assertIsNotNone(ctr)
|
||||
core_api.delete_namespaced_replication_controller(
|
||||
name="mock-2", namespace="default", propagation_policy="Background")
|
||||
core_api.delete_namespaced_service(name="mock-2",
|
||||
namespace="default", body={})
|
||||
|
||||
def test_create_from_multi_resource_yaml_with_multi_conflicts(self):
|
||||
"""
|
||||
Should create an apps/v1 deployment
|
||||
and fail to create the same deployment twice.
|
||||
Should raise an exception that contains two error messages.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
with self.assertRaises(utils.FailToCreateError) as cm:
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "triple-nginx.yaml")
|
||||
exp_error = ('Error from server (Conflict): {"kind":"Status",'
|
||||
'"apiVersion":"v1","metadata":{},"status":"Failure",'
|
||||
'"message":"deployments.apps \\"triple-nginx\\" '
|
||||
'already exists","reason":"AlreadyExists",'
|
||||
'"details":{"name":"triple-nginx","group":"apps",'
|
||||
'"kind":"deployments"},"code":409}\n'
|
||||
)
|
||||
exp_error += exp_error
|
||||
self.assertEqual(exp_error, str(cm.exception))
|
||||
ext_api = client.AppsV1Api(k8s_client)
|
||||
dep = ext_api.read_namespaced_deployment(name="triple-nginx",
|
||||
namespace="default")
|
||||
self.assertIsNotNone(dep)
|
||||
ext_api.delete_namespaced_deployment(
|
||||
name="triple-nginx", namespace="default",
|
||||
body={})
|
||||
|
||||
def test_create_namespaced_apps_deployment_from_yaml(self):
|
||||
"""
|
||||
Should be able to create an apps/v1beta1 deployment
|
||||
in a test namespace.
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "apps-deployment.yaml",
|
||||
namespace=self.test_namespace)
|
||||
app_api = client.AppsV1Api(k8s_client)
|
||||
dep = app_api.read_namespaced_deployment(name="nginx-app",
|
||||
namespace=self.test_namespace)
|
||||
self.assertIsNotNone(dep)
|
||||
app_api.delete_namespaced_deployment(
|
||||
name="nginx-app", namespace=self.test_namespace,
|
||||
body={})
|
||||
|
||||
def test_create_from_list_in_multi_resource_yaml_namespaced(self):
|
||||
"""
|
||||
Should be able to create the items in the PodList and a deployment
|
||||
specified in the multi-resource file in a test namespace
|
||||
"""
|
||||
k8s_client = client.api_client.ApiClient(configuration=self.config)
|
||||
utils.create_from_yaml(
|
||||
k8s_client, self.path_prefix + "multi-resource-with-list.yaml",
|
||||
namespace=self.test_namespace)
|
||||
core_api = client.CoreV1Api(k8s_client)
|
||||
app_api = client.AppsV1Api(k8s_client)
|
||||
pod_0 = core_api.read_namespaced_pod(
|
||||
name="mock-pod-0", namespace=self.test_namespace)
|
||||
self.assertIsNotNone(pod_0)
|
||||
pod_1 = core_api.read_namespaced_pod(
|
||||
name="mock-pod-1", namespace=self.test_namespace)
|
||||
self.assertIsNotNone(pod_1)
|
||||
dep = app_api.read_namespaced_deployment(
|
||||
name="mock", namespace=self.test_namespace)
|
||||
self.assertIsNotNone(dep)
|
||||
core_api.delete_namespaced_pod(
|
||||
name="mock-pod-0", namespace=self.test_namespace, body={})
|
||||
core_api.delete_namespaced_pod(
|
||||
name="mock-pod-1", namespace=self.test_namespace, body={})
|
||||
app_api.delete_namespaced_deployment(
|
||||
name="mock", namespace=self.test_namespace, body={})
|
96
kubernetes/e2e_test/test_watch.py
Normal file
96
kubernetes/e2e_test/test_watch.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 unittest
|
||||
import uuid
|
||||
|
||||
from kubernetes import watch
|
||||
from kubernetes.client import api_client
|
||||
from kubernetes.client.api import core_v1_api
|
||||
from kubernetes.e2e_test import base
|
||||
|
||||
|
||||
def short_uuid():
|
||||
id = str(uuid.uuid4())
|
||||
return id[-12:]
|
||||
|
||||
|
||||
def config_map_with_value(name, value):
|
||||
return {
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
"metadata": {
|
||||
"name": name,
|
||||
"labels": {"e2e-tests": "true"},
|
||||
},
|
||||
"data": {
|
||||
"key": value,
|
||||
"config": "dummy",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestClient(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.config = base.get_e2e_configuration()
|
||||
|
||||
def test_watch_configmaps(self):
|
||||
client = api_client.ApiClient(configuration=self.config)
|
||||
api = core_v1_api.CoreV1Api(client)
|
||||
|
||||
# create a configmap
|
||||
name_a = 'configmap-a-' + short_uuid()
|
||||
configmap_a = config_map_with_value(name_a, "a")
|
||||
api.create_namespaced_config_map(
|
||||
body=configmap_a, namespace='default')
|
||||
|
||||
# list all configmaps and extract the resource version
|
||||
resp = api.list_namespaced_config_map('default', label_selector="e2e-tests=true")
|
||||
rv = resp.metadata.resource_version
|
||||
|
||||
# create another configmap
|
||||
name_b = 'configmap-b-' + short_uuid()
|
||||
configmap_b = config_map_with_value(name_b, "b")
|
||||
api.create_namespaced_config_map(
|
||||
body=configmap_b, namespace='default')
|
||||
|
||||
# patch configmap b
|
||||
configmap_b['data']['config'] = "{}"
|
||||
api.patch_namespaced_config_map(
|
||||
name=name_b, namespace='default', body=configmap_b)
|
||||
|
||||
# delete all configmaps
|
||||
api.delete_collection_namespaced_config_map(
|
||||
namespace='default', label_selector="e2e-tests=true")
|
||||
|
||||
w = watch.Watch()
|
||||
# expect to observe all events happened after the initial LIST
|
||||
expect = ['ADDED', 'MODIFIED', 'DELETED', 'DELETED']
|
||||
i = 0
|
||||
# start watching with the resource version we got from the LIST
|
||||
for event in w.stream(api.list_namespaced_config_map,
|
||||
namespace='default',
|
||||
resource_version=rv,
|
||||
timeout_seconds=5,
|
||||
label_selector="e2e-tests=true"):
|
||||
self.assertEqual(event['type'], expect[i])
|
||||
# Kubernetes doesn't guarantee the order of the two objects
|
||||
# being deleted
|
||||
if i < 2:
|
||||
self.assertEqual(event['object'].metadata.name, name_b)
|
||||
i = i + 1
|
||||
|
||||
self.assertEqual(i, 4)
|
13
kubernetes/e2e_test/test_yaml/api-service.yaml
Normal file
13
kubernetes/e2e_test/test_yaml/api-service.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
metadata:
|
||||
name: v1alpha1.wardle.k8s.io
|
||||
spec:
|
||||
insecureSkipTLSVerify: true
|
||||
group: wardle.k8s.io
|
||||
groupPriorityMinimum: 1000
|
||||
versionPriority: 15
|
||||
service:
|
||||
name: api
|
||||
namespace: wardle
|
||||
version: v1alpha1
|
21
kubernetes/e2e_test/test_yaml/apps-deployment-2.yaml
Normal file
21
kubernetes/e2e_test/test_yaml/apps-deployment-2.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
apiVersion: apps/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-app-2
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
21
kubernetes/e2e_test/test_yaml/apps-deployment.yaml
Normal file
21
kubernetes/e2e_test/test_yaml/apps-deployment.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-app
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
6
kubernetes/e2e_test/test_yaml/core-namespace.yaml
Normal file
6
kubernetes/e2e_test/test_yaml/core-namespace.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: development
|
||||
labels:
|
||||
name: development
|
11
kubernetes/e2e_test/test_yaml/core-pod.yaml
Normal file
11
kubernetes/e2e_test/test_yaml/core-pod.yaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-container
|
||||
image: busybox
|
||||
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
|
11
kubernetes/e2e_test/test_yaml/core-service.yaml
Normal file
11
kubernetes/e2e_test/test_yaml/core-service.yaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: my-service
|
||||
spec:
|
||||
selector:
|
||||
app: MyApp
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
20
kubernetes/e2e_test/test_yaml/dep-deployment.yaml
Normal file
20
kubernetes/e2e_test/test_yaml/dep-deployment.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
namespace: dep
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
6
kubernetes/e2e_test/test_yaml/dep-namespace.yaml
Normal file
6
kubernetes/e2e_test/test_yaml/dep-namespace.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: dep
|
||||
labels:
|
||||
name: dep
|
60
kubernetes/e2e_test/test_yaml/implicit-svclist.json
Normal file
60
kubernetes/e2e_test/test_yaml/implicit-svclist.json
Normal file
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"kind":"ServiceList",
|
||||
"apiVersion":"v1",
|
||||
"items":[
|
||||
{
|
||||
"metadata":{
|
||||
"name":"mock-3",
|
||||
"labels":{
|
||||
"app":"mock-3"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"ports": [{
|
||||
"protocol": "TCP",
|
||||
"port": 99,
|
||||
"targetPort": 9949
|
||||
}],
|
||||
"selector":{
|
||||
"app":"mock-3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"metadata":{
|
||||
"name":"mock-3",
|
||||
"labels":{
|
||||
"app":"mock-3"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"ports": [{
|
||||
"protocol": "TCP",
|
||||
"port": 99,
|
||||
"targetPort": 9949
|
||||
}],
|
||||
"selector":{
|
||||
"app":"mock-3"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"metadata":{
|
||||
"name":"mock-4",
|
||||
"labels":{
|
||||
"app":"mock-4"
|
||||
}
|
||||
},
|
||||
"spec":{
|
||||
"ports": [{
|
||||
"protocol": "TCP",
|
||||
"port": 99,
|
||||
"targetPort": 9949
|
||||
}],
|
||||
"selector":{
|
||||
"app":"mock-4"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
32
kubernetes/e2e_test/test_yaml/list.yaml
Normal file
32
kubernetes/e2e_test/test_yaml/list.yaml
Normal file
|
@ -0,0 +1,32 @@
|
|||
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: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: list-deployment-test
|
||||
labels:
|
||||
app: list-deployment-test
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: list-deployment-test
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: list-deployment-test
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
47
kubernetes/e2e_test/test_yaml/multi-resource-with-list.yaml
Normal file
47
kubernetes/e2e_test/test_yaml/multi-resource-with-list.yaml
Normal file
|
@ -0,0 +1,47 @@
|
|||
apiVersion: v1
|
||||
kind: PodList
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mock-pod-0
|
||||
labels:
|
||||
app: mock-pod-0
|
||||
spec:
|
||||
containers:
|
||||
- name: mock-pod-0
|
||||
image: busybox
|
||||
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
|
||||
- apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mock-pod-1
|
||||
labels:
|
||||
app: mock-pod-1
|
||||
spec:
|
||||
containers:
|
||||
- name: mock-pod-1
|
||||
image: busybox
|
||||
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mock
|
||||
labels:
|
||||
app: mock
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mock
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mock
|
||||
spec:
|
||||
containers:
|
||||
- name: mock
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
33
kubernetes/e2e_test/test_yaml/multi-resource.yaml
Normal file
33
kubernetes/e2e_test/test_yaml/multi-resource.yaml
Normal file
|
@ -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
|
|
@ -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
|
|
@ -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
|
15
kubernetes/e2e_test/test_yaml/namespace-list.yaml
Normal file
15
kubernetes/e2e_test/test_yaml/namespace-list.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: NamespaceList
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: mock-1
|
||||
labels:
|
||||
name: mock-1
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: mock-2
|
||||
labels:
|
||||
name: mock-2
|
9
kubernetes/e2e_test/test_yaml/rbac-role.yaml
Normal file
9
kubernetes/e2e_test/test_yaml/rbac-role.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
namespace: default
|
||||
name: pod-reader
|
||||
rules:
|
||||
- apiGroups: [""] # "" indicates the core API group
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "watch", "list"]
|
59
kubernetes/e2e_test/test_yaml/triple-nginx.yaml
Normal file
59
kubernetes/e2e_test/test_yaml/triple-nginx.yaml
Normal file
|
@ -0,0 +1,59 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: triple-nginx
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: triple-nginx
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: triple-nginx
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.4
|
||||
ports:
|
||||
- containerPort: 80
|
13
kubernetes/e2e_test/test_yaml/yaml-conflict-first.yaml
Normal file
13
kubernetes/e2e_test/test_yaml/yaml-conflict-first.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mock-2
|
||||
labels:
|
||||
app: mock-2
|
||||
spec:
|
||||
ports:
|
||||
- port: 99
|
||||
protocol: TCP
|
||||
targetPort: 9949
|
||||
selector:
|
||||
app: mock-2
|
33
kubernetes/e2e_test/test_yaml/yaml-conflict-multi.yaml
Normal file
33
kubernetes/e2e_test/test_yaml/yaml-conflict-multi.yaml
Normal file
|
@ -0,0 +1,33 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mock-2
|
||||
labels:
|
||||
app: mock-2
|
||||
spec:
|
||||
ports:
|
||||
- port: 99
|
||||
protocol: TCP
|
||||
targetPort: 9949
|
||||
selector:
|
||||
app: mock-2
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ReplicationController
|
||||
metadata:
|
||||
name: mock-2
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
app: mock-2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mock-2
|
||||
spec:
|
||||
containers:
|
||||
- name: mock-container
|
||||
image: k8s.gcr.io/pause:2.0
|
||||
ports:
|
||||
- containerPort: 9949
|
||||
protocol: TCP
|
Reference in a new issue