Refactoring of k8s manager and tests
Changes:
- Official kubernetes python lib
- Rewrite k8s api wrapper in OOP manner
- Use api where its possible instead of cli
- Remove virtlet code because its can be replaced with pod api
- Remove unused/oudated manager code
- Remove bug workaround in k8s upgrade template
- Remove netchecker obsolete code
- Remove unfinished test_rbd_flexvolume_driver
Change-Id: I446a240123282196a6ba54f588aea84791f175ba
Related-PROD: PROD-21700
diff --git a/tcp_tests/managers/k8s/base.py b/tcp_tests/managers/k8s/base.py
index 7adb41a..6ca6a88 100644
--- a/tcp_tests/managers/k8s/base.py
+++ b/tcp_tests/managers/k8s/base.py
@@ -12,97 +12,140 @@
# License for the specific language governing permissions and limitations
-class K8sBaseResource(object):
- """docstring for K8sBaseResource"""
+import yaml
+import requests
+import os
- def __init__(self, manager, data):
+from tcp_tests import logger
+
+LOG = logger.logger
+
+
+class K8sBaseResource(object):
+ resource_type = None
+
+ def __init__(self, manager, name=None, namespace=None, data=None):
self._manager = manager
- self._add_details(data)
+ self._name = name
+ self._namespace = namespace
+ self._read_cache = None
+ if data is not None:
+ self._update_cache(data)
def __repr__(self):
- reprkeys = sorted(k
- for k in self.__dict__.keys()
- if k[0] != '_' and
- k not in ['manager'])
- info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
- return "<%s %s>" % (self.__class__.__name__, info)
+ uid = 'unknown-uid'
+ if self._read_cache is not None:
+ uid = self.uid
+ return "<{0} name='{1}' namespace='{2}' uuid='{3}'>".format(
+ self.__class__.__name__, self.name, self.namespace, uid)
@property
- def api_version(self):
- return self._data.api_version
-
- def _add_details(self, data):
- self._data = data
- for k in [k for k in dir(data)
- if not any((k.startswith('_'), k in ('to_dict', 'to_str')))]:
- try:
- setattr(self, k, getattr(data, k))
- except AttributeError:
- # In this case we already defined the attribute on the class
- pass
-
- def __eq__(self, other):
- if not isinstance(other, K8sBaseResource):
- return NotImplemented
- # two resources of different types are not equal
- if not isinstance(other, self.__class__):
- return False
- return self._info == other._info
-
-
-class K8sBaseManager(object):
-
- resource_class = None
-
- def __init__(self, api, namespace):
- self._api = api
- self._namespace = namespace
- self._raw = None
-
- @property
- def api(self):
- return self._api
+ def name(self):
+ return self._name
@property
def namespace(self):
return self._namespace
- def get(self, *args, **kwargs):
- if not hasattr(self, '_get'):
- raise NotImplementedError(
- '{} does not have {}'.format(self, '_get'))
+ @property
+ def uid(self):
+ return self.read(cached=True).metadata.uid
- return self.resource_class(self, self._get(*args, **kwargs))
+ def _update_cache(self, data):
+ self._read_cache = data
+ self._namespace = data.metadata.namespace
+ self._name = data.metadata.name
- def list(self, *args, **kwargs):
- if not hasattr(self, '_list'):
- raise NotImplementedError(
- '{} does not have {}'.format(self, '_list'))
+ def read(self, cached=False, **kwargs):
+ if not cached:
+ self._update_cache(self._read(**kwargs))
+ return self._read_cache
- lst = self._list(*args, **kwargs)
+ def create(self, body, **kwargs):
+ LOG.info("K8S API Creating {0} with body:\n{1}".format(
+ self.resource_type, body))
- return [self.resource_class(self, item) for item in lst.items]
+ self._update_cache(self._create(body, **kwargs))
+ return self
- def create(self, *args, **kwargs):
- if not hasattr(self, '_create'):
- raise NotImplementedError(
- '{} does not have {}'.format(self, '_create'))
- return self.resource_class(self, self._create(*args, **kwargs))
+ def patch(self, body, **kwargs):
- def replace(self, *args, **kwargs):
- if not hasattr(self, '_replace'):
- raise NotImplementedError(
- '{} does not have {}'.format(self, '_replace'))
- return self._replace(*args, **kwargs)
+ LOG.info("K8S API Patching {0} name={1} ns={2} with body:\n{3}".format(
+ self.resource_type, self.name, self.namespace, body))
- def delete(self, *args, **kwargs):
- if not hasattr(self, '_delete'):
- raise NotImplementedError(
- '{} does not have {}'.format(self, '_delete'))
- return self._delete(*args, **kwargs)
+ self._update_cache(self._patch(body, **kwargs))
+ return self
- def deletecollection(self, *args, **kwargs):
- if not hasattr(self, '_deletecollection'):
- raise NotImplementedError(
- '{} does not have {}'.format(self, '_deletecollection'))
- return self._deletecollection(*args, **kwargs)
+ def replace(self, body, **kwargs):
+ self._update_cache(self._replace(body, **kwargs))
+ return self
+
+ def delete(self, **kwargs):
+ self._delete(**kwargs)
+ return self
+
+ def __eq__(self, other):
+ if not isinstance(other, K8sBaseResource):
+ return NotImplemented
+
+ if not isinstance(other, self.__class__):
+ return False
+
+ return self.uid == other.uid
+
+
+class K8sBaseManager(object):
+ resource_class = None
+
+ def __init__(self, cluster):
+ self._cluster = cluster
+
+ @property
+ def resource_type(self):
+ return self.resource_class.resource_type
+
+ def get(self, name=None, namespace=None, data=None):
+ namespace = namespace or self._cluster.default_namespace
+ return self.resource_class(self, name, namespace, data)
+
+ def create(self, name=None, namespace=None, body=None, **kwargs):
+ return self.get(name=name, namespace=namespace).create(body, **kwargs)
+
+ def __resource_from_data(self, data):
+ return self.resource_class(self, data=data)
+
+ def __list_filter(self, items, name_prefix=None):
+ if name_prefix is not None:
+ items = [item for item in items if
+ item.metadata.name.startswith(name_prefix)]
+ return items
+
+ def __list_to_resource(self, items):
+ return [self.__resource_from_data(item) for item in items]
+
+ def list(self, namespace=None, name_prefix=None, **kwargs):
+ namespace = namespace or self._cluster.default_namespace
+ items = self._list(namespace=namespace, **kwargs).items
+ items = self.__list_filter(items, name_prefix=name_prefix)
+ return self.__list_to_resource(items)
+
+ def list_all(self, name_prefix=None, **kwargs):
+ items = self._list_all(**kwargs).items
+ items = self.__list_filter(items, name_prefix=name_prefix)
+ return self.__list_to_resource(items)
+
+
+def read_yaml_str(yaml_str):
+ """ load yaml from string helper """
+ return yaml.safe_load(yaml_str)
+
+
+def read_yaml_file(file_path, *args):
+ """ load yaml from joined file_path and *args helper """
+ with open(os.path.join(file_path, *args)) as f:
+ return yaml.safe_load(f)
+
+
+def read_yaml_url(yaml_file_url):
+ """ load yaml from url helper """
+ return yaml.safe_load(requests.get(yaml_file_url).text)