Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add kubernetes api_client parameter to kubetest client #144

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 96 additions & 28 deletions kubetest/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,20 @@ def __init__(self, namespace):
self.namespace = namespace
self.pre_registered = []

self._api_client = None

@property
def api_client(self):
""""""
return self._api_client

@api_client.setter
def api_client(self, value):
self._api_client = value

# ****** Manifest Loaders ******

@staticmethod
def load_clusterrolebinding(path):
def load_clusterrolebinding(self, path):
"""Load a manifest YAML into a ClusterRoleBinding object.

Args:
Expand All @@ -45,6 +55,10 @@ def load_clusterrolebinding(path):
"""
log.info('loading clusterrolebinding from path: %s', path)
clusterrolebinding = objects.ClusterRoleBinding.load(path)

# Use the api_client defined for the test client for the object
# wrapper it creates.
clusterrolebinding._client = self.api_client
return clusterrolebinding

def load_configmap(self, path, set_namespace=True):
Expand All @@ -66,6 +80,10 @@ def load_configmap(self, path, set_namespace=True):
configmap = objects.ConfigMap.load(path)
if set_namespace:
configmap.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
configmap._client = self.api_client
return configmap

def load_deployment(self, path, set_namespace=True):
Expand All @@ -87,6 +105,10 @@ def load_deployment(self, path, set_namespace=True):
deployment = objects.Deployment.load(path)
if set_namespace:
deployment.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
deployment._client = self.api_client
return deployment

def load_statefulset(self, path, set_namespace=True):
Expand All @@ -108,6 +130,10 @@ def load_statefulset(self, path, set_namespace=True):
statefulset = objects.StatefulSet.load(path)
if set_namespace:
statefulset.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
statefulset._client = self.api_client
return statefulset

def load_daemonset(self, path, set_namespace=True):
Expand All @@ -129,6 +155,10 @@ def load_daemonset(self, path, set_namespace=True):
daemonset = objects.DaemonSet.load(path)
if set_namespace:
daemonset.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
daemonset._client = self.api_client
return daemonset

def load_pod(self, path, set_namespace=True):
Expand All @@ -150,6 +180,10 @@ def load_pod(self, path, set_namespace=True):
pod = objects.Pod.load(path)
if set_namespace:
pod.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
pod._client = self.api_client
return pod

def load_rolebinding(self, path, set_namespace=True):
Expand All @@ -171,6 +205,10 @@ def load_rolebinding(self, path, set_namespace=True):
rolebinding = objects.RoleBinding.load(path)
if set_namespace:
rolebinding.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
rolebinding._client = self.api_client
return rolebinding

def load_secret(self, path, set_namespace=True):
Expand All @@ -192,6 +230,10 @@ def load_secret(self, path, set_namespace=True):
secret = objects.Secret.load(path)
if set_namespace:
secret.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
secret._client = self.api_client
return secret

def load_service(self, path, set_namespace=True):
Expand All @@ -213,6 +255,10 @@ def load_service(self, path, set_namespace=True):
service = objects.Service.load(path)
if set_namespace:
service.namespace = self.namespace

# Use the api_client defined for the test client for the object
# wrapper it creates.
service._client = self.api_client
return service

# ****** Generic Helpers on ApiObjects ******
Expand All @@ -229,6 +275,14 @@ def create(self, obj):
if obj.namespace is None:
obj.namespace = self.namespace

# If the object which the TestClient is trying to create does not
# have its api client set, use the TestClient's api_client. This requires
# setting the client to None so it can be rebuilt with the TestClient's
# api_client.
if obj._client is None:
obj._api_client = None
obj._client = self.api_client

obj.create()

def delete(self, obj, options=None):
Expand All @@ -247,15 +301,30 @@ def delete(self, obj, options=None):
if options is None:
options = client.V1DeleteOptions()

# If the object which the TestClient is trying to create does not
# have its api client set, use the TestClient's api_client. This requires
# setting the client to None so it can be rebuilt with the TestClient's
# api_client.
if obj._client is None:
obj._api_client = None
obj._client = self.api_client

obj.delete(options=options)

@staticmethod
def refresh(obj):
def refresh(self, obj):
"""Refresh the underlying Kubernetes resource status and state.

Args:
obj (objects.ApiObject): A kubetest API Object wrapper.
"""
# If the object which the TestClient is trying to create does not
# have its api client set, use the TestClient's api_client. This requires
# setting the client to None so it can be rebuilt with the TestClient's
# api_client.
if obj._client is None:
obj._api_client = None
obj._client = self.api_client

obj.refresh()

# ****** General Helpers ******
Expand All @@ -277,13 +346,13 @@ def get_namespaces(self, fields=None, labels=None):
"""
selectors = utils.selector_kwargs(fields, labels)

namespace_list = client.CoreV1Api().list_namespace(
namespace_list = client.CoreV1Api(api_client=self.api_client).list_namespace(
**selectors,
)

namespaces = {}
for obj in namespace_list.items:
namespace = objects.Namespace(obj)
namespace = objects.Namespace(obj, client=self.api_client)
namespaces[namespace.name] = namespace

return namespaces
Expand Down Expand Up @@ -311,14 +380,14 @@ def get_deployments(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

deployment_list = client.AppsV1Api().list_namespaced_deployment(
deployment_list = client.AppsV1Api(api_client=self.api_client).list_namespaced_deployment(
namespace=namespace,
**selectors,
)

deployments = {}
for obj in deployment_list.items:
deployment = objects.Deployment(obj)
deployment = objects.Deployment(obj, client=self.api_client)
deployments[deployment.name] = deployment

return deployments
Expand Down Expand Up @@ -346,14 +415,14 @@ def get_statefulsets(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

statefulset_list = client.AppsV1Api().list_namespaced_stateful_set(
statefulset_list = client.AppsV1Api(api_client=self.api_client).list_namespaced_stateful_set(
namespace=namespace,
**selectors,
)

statefulsets = {}
for obj in statefulset_list.items:
statefulset = objects.StatefulSet(obj)
statefulset = objects.StatefulSet(obj, client=self.api_client)
statefulsets[statefulset.name] = statefulset

return statefulsets
Expand Down Expand Up @@ -381,14 +450,14 @@ def get_daemonsets(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

daemonset_list = client.AppsV1Api().list_namespaced_daemon_set(
daemonset_list = client.AppsV1Api(api_client=self.api_client).list_namespaced_daemon_set(
namespace=namespace,
**selectors,
)

daemonsets = {}
for obj in daemonset_list.items:
daemonset = objects.DaemonSet(obj)
daemonset = objects.DaemonSet(obj, client=self.api_client)
daemonsets[daemonset.name] = daemonset

return daemonsets
Expand Down Expand Up @@ -416,14 +485,14 @@ def get_endpoints(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

endpoints_list = client.CoreV1Api().list_namespaced_endpoints(
endpoints_list = client.CoreV1Api(api_client=self.api_client).list_namespaced_endpoints(
namespace=namespace,
**selectors,
)

endpoints = {}
for obj in endpoints_list.items:
endpoint = objects.Endpoints(obj)
endpoint = objects.Endpoints(obj, client=self.api_client)
endpoints[endpoint.name] = endpoint

return endpoints
Expand Down Expand Up @@ -451,14 +520,14 @@ def get_secrets(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

secret_list = client.CoreV1Api().list_namespaced_secret(
secret_list = client.CoreV1Api(api_client=self.api_client).list_namespaced_secret(
namespace=namespace,
**selectors,
)

secrets = {}
for obj in secret_list.items:
secret = objects.Secret(obj)
secret = objects.Secret(obj, client=self.api_client)
secrets[secret.name] = secret

return secrets
Expand Down Expand Up @@ -486,14 +555,14 @@ def get_configmaps(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

configmap_list = client.CoreV1Api().list_namespaced_config_map(
configmap_list = client.CoreV1Api(api_client=self.api_client).list_namespaced_config_map(
namespace=namespace,
**selectors,
)

configmaps = {}
for obj in configmap_list.items:
cm = objects.ConfigMap(obj)
cm = objects.ConfigMap(obj, client=self.api_client)
configmaps[cm.name] = cm

return configmaps
Expand Down Expand Up @@ -521,14 +590,14 @@ def get_pods(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

pod_list = client.CoreV1Api().list_namespaced_pod(
pod_list = client.CoreV1Api(api_client=self.api_client).list_namespaced_pod(
namespace=namespace,
**selectors,
)

pods = {}
for obj in pod_list.items:
pod = objects.Pod(obj)
pod = objects.Pod(obj, client=self.api_client)
pods[pod.name] = pod

return pods
Expand Down Expand Up @@ -556,20 +625,19 @@ def get_services(self, namespace=None, fields=None, labels=None):

selectors = utils.selector_kwargs(fields, labels)

service_list = client.CoreV1Api().list_namespaced_service(
service_list = client.CoreV1Api(api_client=self.api_client).list_namespaced_service(
namespace=namespace,
**selectors,
)

services = {}
for obj in service_list.items:
service = objects.Service(obj)
service = objects.Service(obj, client=self.api_client)
services[service.name] = service

return services

@staticmethod
def get_nodes(fields=None, labels=None):
def get_nodes(self, fields=None, labels=None):
"""Get the Nodes that make up the cluster.

Args:
Expand All @@ -586,13 +654,13 @@ def get_nodes(fields=None, labels=None):
"""
selectors = utils.selector_kwargs(fields, labels)

node_list = client.CoreV1Api().list_node(
node_list = client.CoreV1Api(api_client=self.api_client).list_node(
**selectors,
)

nodes = {}
for obj in node_list.items:
node = objects.Node(obj)
node = objects.Node(obj, client=self.api_client)
nodes[node.name] = node

return nodes
Expand All @@ -617,11 +685,11 @@ def get_events(self, fields=None, labels=None, all_namespaces=False):
selectors = utils.selector_kwargs(fields, labels)

if all_namespaces:
event_list = client.CoreV1Api().list_event_for_all_namespaces(
event_list = client.CoreV1Api(api_client=self.api_client).list_event_for_all_namespaces(
**selectors
)
else:
event_list = client.CoreV1Api().list_namespaced_event(
event_list = client.CoreV1Api(api_client=self.api_client).list_namespaced_event(
namespace=self.namespace,
**selectors
)
Expand Down
11 changes: 9 additions & 2 deletions kubetest/objects/api_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,21 @@ class ApiObject(abc.ABC):
is not specified for the resource.
'''

def __init__(self, api_object):
def __init__(self, api_object, client=None):
# The underlying Kubernetes Api Object
self.obj = api_object

# The api client for the object. This will be determined
# by the apiVersion of the object's manifest.
self._api_client = None

# The underlying client which is used by the api client, above.
# The naming of this is a bit confusing, but here the "api_client"
# can be thought of as the Kubernetes versioned client (e.g. AppsV1Api)
# whereas this "client" is the generic ApiClient which underlays the
# versioned client.
self._client = client

@property
def version(self):
"""str: The API version of the Kubernetes object (`obj.apiVersion``)."""
Expand Down Expand Up @@ -111,7 +118,7 @@ def api_client(self):
'defined for resource ({})'.format(self.version)
)
# If we did find it, initialize that client version.
self._api_client = c()
self._api_client = c(api_client=self._client)
return self._api_client

def wait_until_ready(self, timeout=None, interval=1, fail_on_api_error=False):
Expand Down
Loading