2017-08-16 12:51:16 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
'''
|
|
|
|
:codeauthor: :email:`Jochen Breuer <jbreuer@suse.de>`
|
|
|
|
'''
|
|
|
|
|
|
|
|
# Import Python Libs
|
|
|
|
from __future__ import absolute_import
|
|
|
|
|
2017-10-22 00:18:14 +00:00
|
|
|
from contextlib import contextmanager
|
|
|
|
|
2017-08-16 12:51:16 +00:00
|
|
|
# Import Salt Testing Libs
|
2017-08-28 07:34:51 +00:00
|
|
|
from tests.support.mixins import LoaderModuleMockMixin
|
2017-08-18 13:15:20 +00:00
|
|
|
from tests.support.unit import TestCase, skipIf
|
|
|
|
from tests.support.mock import (
|
2017-08-16 12:51:16 +00:00
|
|
|
Mock,
|
|
|
|
patch,
|
|
|
|
NO_MOCK,
|
|
|
|
NO_MOCK_REASON
|
|
|
|
)
|
|
|
|
|
2017-08-29 15:12:25 +00:00
|
|
|
try:
|
|
|
|
from salt.modules import kubernetes
|
|
|
|
except ImportError:
|
|
|
|
kubernetes = False
|
2017-09-11 12:37:38 +00:00
|
|
|
if not kubernetes.HAS_LIBS:
|
|
|
|
kubernetes = False
|
2017-08-16 12:51:16 +00:00
|
|
|
|
|
|
|
|
2017-10-22 00:18:14 +00:00
|
|
|
@contextmanager
|
|
|
|
def mock_kubernetes_library():
|
|
|
|
"""
|
|
|
|
After fixing the bug in 1c821c0e77de58892c77d8e55386fac25e518c31,
|
|
|
|
it caused kubernetes._cleanup() to get called for virtually every
|
|
|
|
test, which blows up. This prevents that specific blow-up once
|
|
|
|
"""
|
|
|
|
with patch('salt.modules.kubernetes.kubernetes') as mock_kubernetes_lib:
|
|
|
|
mock_kubernetes_lib.client.configuration.ssl_ca_cert = ''
|
|
|
|
mock_kubernetes_lib.client.configuration.cert_file = ''
|
|
|
|
mock_kubernetes_lib.client.configuration.key_file = ''
|
|
|
|
yield mock_kubernetes_lib
|
|
|
|
|
|
|
|
|
2017-08-16 12:51:16 +00:00
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
2017-08-29 15:12:25 +00:00
|
|
|
@skipIf(kubernetes is False, "Probably Kubernetes client lib is not installed. \
|
|
|
|
Skipping test_kubernetes.py")
|
2017-08-28 07:34:51 +00:00
|
|
|
class KubernetesTestCase(TestCase, LoaderModuleMockMixin):
|
2017-08-16 12:51:16 +00:00
|
|
|
'''
|
|
|
|
Test cases for salt.modules.kubernetes
|
|
|
|
'''
|
2017-08-28 07:34:51 +00:00
|
|
|
|
|
|
|
def setup_loader_modules(self):
|
|
|
|
return {
|
|
|
|
kubernetes: {
|
|
|
|
'__salt__': {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-16 12:51:16 +00:00
|
|
|
def test_nodes(self):
|
|
|
|
'''
|
|
|
|
Test node listing.
|
|
|
|
:return:
|
|
|
|
'''
|
2017-10-22 00:18:14 +00:00
|
|
|
with mock_kubernetes_library() as mock_kubernetes_lib:
|
2017-08-16 12:51:16 +00:00
|
|
|
with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}):
|
|
|
|
mock_kubernetes_lib.client.CoreV1Api.return_value = Mock(
|
|
|
|
**{"list_node.return_value.to_dict.return_value":
|
|
|
|
{'items': [{'metadata': {'name': 'mock_node_name'}}]}}
|
|
|
|
)
|
|
|
|
self.assertEqual(kubernetes.nodes(), ['mock_node_name'])
|
|
|
|
self.assertTrue(kubernetes.kubernetes.client.CoreV1Api().list_node().to_dict.called)
|
|
|
|
|
|
|
|
def test_deployments(self):
|
|
|
|
'''
|
|
|
|
Tests deployment listing.
|
|
|
|
:return:
|
|
|
|
'''
|
2017-10-22 00:18:14 +00:00
|
|
|
with mock_kubernetes_library() as mock_kubernetes_lib:
|
2017-08-16 12:51:16 +00:00
|
|
|
with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}):
|
|
|
|
mock_kubernetes_lib.client.ExtensionsV1beta1Api.return_value = Mock(
|
|
|
|
**{"list_namespaced_deployment.return_value.to_dict.return_value":
|
|
|
|
{'items': [{'metadata': {'name': 'mock_deployment_name'}}]}}
|
|
|
|
)
|
|
|
|
self.assertEqual(kubernetes.deployments(), ['mock_deployment_name'])
|
|
|
|
self.assertTrue(
|
|
|
|
kubernetes.kubernetes.client.ExtensionsV1beta1Api().list_namespaced_deployment().to_dict.called)
|
|
|
|
|
|
|
|
def test_services(self):
|
|
|
|
'''
|
|
|
|
Tests services listing.
|
|
|
|
:return:
|
|
|
|
'''
|
2017-10-22 00:18:14 +00:00
|
|
|
with mock_kubernetes_library() as mock_kubernetes_lib:
|
2017-08-16 12:51:16 +00:00
|
|
|
with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}):
|
|
|
|
mock_kubernetes_lib.client.CoreV1Api.return_value = Mock(
|
|
|
|
**{"list_namespaced_service.return_value.to_dict.return_value":
|
|
|
|
{'items': [{'metadata': {'name': 'mock_service_name'}}]}}
|
|
|
|
)
|
|
|
|
self.assertEqual(kubernetes.services(), ['mock_service_name'])
|
|
|
|
self.assertTrue(kubernetes.kubernetes.client.CoreV1Api().list_namespaced_service().to_dict.called)
|
|
|
|
|
|
|
|
def test_pods(self):
|
|
|
|
'''
|
|
|
|
Tests pods listing.
|
|
|
|
:return:
|
|
|
|
'''
|
2017-10-22 00:18:14 +00:00
|
|
|
with mock_kubernetes_library() as mock_kubernetes_lib:
|
2017-08-16 12:51:16 +00:00
|
|
|
with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}):
|
|
|
|
mock_kubernetes_lib.client.CoreV1Api.return_value = Mock(
|
|
|
|
**{"list_namespaced_pod.return_value.to_dict.return_value":
|
|
|
|
{'items': [{'metadata': {'name': 'mock_pod_name'}}]}}
|
|
|
|
)
|
|
|
|
self.assertEqual(kubernetes.pods(), ['mock_pod_name'])
|
2017-08-28 07:34:51 +00:00
|
|
|
self.assertTrue(kubernetes.kubernetes.client.CoreV1Api().
|
|
|
|
list_namespaced_pod().to_dict.called)
|
2017-08-16 12:51:16 +00:00
|
|
|
|
|
|
|
def test_delete_deployments(self):
|
|
|
|
'''
|
2017-09-25 15:29:27 +00:00
|
|
|
Tests deployment deletion
|
2017-08-16 12:51:16 +00:00
|
|
|
:return:
|
|
|
|
'''
|
2017-10-22 00:18:14 +00:00
|
|
|
with mock_kubernetes_library() as mock_kubernetes_lib:
|
2017-09-25 15:29:27 +00:00
|
|
|
with patch('salt.modules.kubernetes.show_deployment', Mock(return_value=None)):
|
|
|
|
with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}):
|
|
|
|
mock_kubernetes_lib.client.V1DeleteOptions = Mock(return_value="")
|
|
|
|
mock_kubernetes_lib.client.ExtensionsV1beta1Api.return_value = Mock(
|
|
|
|
**{"delete_namespaced_deployment.return_value.to_dict.return_value": {'code': ''}}
|
|
|
|
)
|
|
|
|
self.assertEqual(kubernetes.delete_deployment("test"), {'code': 200})
|
|
|
|
self.assertTrue(
|
|
|
|
kubernetes.kubernetes.client.ExtensionsV1beta1Api().
|
|
|
|
delete_namespaced_deployment().to_dict.called)
|
2017-08-16 12:51:16 +00:00
|
|
|
|
|
|
|
def test_create_deployments(self):
|
|
|
|
'''
|
|
|
|
Tests deployment creation.
|
|
|
|
:return:
|
|
|
|
'''
|
2017-10-22 00:18:14 +00:00
|
|
|
with mock_kubernetes_library() as mock_kubernetes_lib:
|
2017-08-16 12:51:16 +00:00
|
|
|
with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}):
|
|
|
|
mock_kubernetes_lib.client.ExtensionsV1beta1Api.return_value = Mock(
|
|
|
|
**{"create_namespaced_deployment.return_value.to_dict.return_value": {}}
|
|
|
|
)
|
2017-08-28 07:34:51 +00:00
|
|
|
self.assertEqual(kubernetes.create_deployment("test", "default", {}, {},
|
|
|
|
None, None, None), {})
|
2017-08-16 12:51:16 +00:00
|
|
|
self.assertTrue(
|
2017-08-28 07:34:51 +00:00
|
|
|
kubernetes.kubernetes.client.ExtensionsV1beta1Api().
|
|
|
|
create_namespaced_deployment().to_dict.called)
|
2017-10-21 19:49:37 +00:00
|
|
|
|
|
|
|
def test_setup_client_key_file(self):
|
|
|
|
'''
|
|
|
|
Test that the `kubernetes.client-key-file` configuration isn't overwritten
|
|
|
|
:return:
|
|
|
|
'''
|
|
|
|
def settings(name, value=None):
|
|
|
|
data = {
|
|
|
|
'kubernetes.client-key-file': '/home/testuser/.minikube/client.key',
|
|
|
|
}
|
|
|
|
return data.get(name, value)
|
|
|
|
|
|
|
|
with patch.dict(kubernetes.__salt__, {'config.option': Mock(side_effect=settings)}):
|
|
|
|
config = kubernetes._setup_conn()
|
|
|
|
self.assertEqual(
|
|
|
|
settings('kubernetes.client-key-file'),
|
|
|
|
config['key_file'],
|
|
|
|
)
|
2017-10-21 21:33:50 +00:00
|
|
|
|
|
|
|
def test_node_labels(self):
|
|
|
|
'''
|
|
|
|
Test kubernetes.node_labels
|
|
|
|
:return:
|
|
|
|
'''
|
|
|
|
with patch('salt.modules.kubernetes.node') as mock_node:
|
|
|
|
mock_node.return_value = {
|
|
|
|
'metadata': {
|
|
|
|
'labels': {
|
|
|
|
u'kubernetes.io/hostname': 'minikube',
|
|
|
|
u'kubernetes.io/os': 'linux',
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.assertEqual(
|
|
|
|
kubernetes.node_labels('minikube'),
|
|
|
|
{u'kubernetes.io/hostname': 'minikube', u'kubernetes.io/os': 'linux'},
|
|
|
|
)
|
2017-10-21 23:23:42 +00:00
|
|
|
|
|
|
|
def test_adding_change_cause_annotation(self):
|
|
|
|
'''
|
|
|
|
Tests adding a `kubernetes.io/change-cause` annotation just like
|
|
|
|
kubectl [apply|create|replace] --record does
|
|
|
|
:return:
|
|
|
|
'''
|
|
|
|
with patch('salt.modules.kubernetes.sys.argv', ['/usr/bin/salt-call', 'state.apply']) as mock_sys:
|
|
|
|
func = getattr(kubernetes, '__dict_to_object_meta')
|
|
|
|
data = func(name='test-pod', namespace='test', metadata={})
|
|
|
|
|
|
|
|
self.assertEqual(data.name, 'test-pod')
|
|
|
|
self.assertEqual(data.namespace, 'test')
|
|
|
|
self.assertEqual(
|
|
|
|
data.annotations,
|
|
|
|
{'kubernetes.io/change-cause': '/usr/bin/salt-call state.apply'}
|
|
|
|
)
|
|
|
|
|
|
|
|
# Ensure any specified annotations aren't overwritten
|
|
|
|
test_metadata = {'annotations': {'kubernetes.io/change-cause': 'NOPE'}}
|
|
|
|
data = func(name='test-pod', namespace='test', metadata=test_metadata)
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
data.annotations,
|
|
|
|
{'kubernetes.io/change-cause': 'NOPE'}
|
|
|
|
)
|