Skip to content
This repository has been archived by the owner on Oct 3, 2020. It is now read-only.

Commit

Permalink
Merge 87910a3 into b313fae
Browse files Browse the repository at this point in the history
  • Loading branch information
hjacobs committed Mar 14, 2019
2 parents b313fae + 87910a3 commit 729d635
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 10 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ clean:
test:
pipenv run flake8
pipenv run coverage run --source=pykube -m py.test
pipenv run coverage html
pipenv run coverage report

apidocs:
Expand Down
4 changes: 2 additions & 2 deletions pykube/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pykube import exceptions


class KubeConfig(object):
class KubeConfig:
"""
Main configuration class.
"""
Expand Down Expand Up @@ -216,7 +216,7 @@ def reload(self):
delattr(self, "_clusters")


class BytesOrFile(object):
class BytesOrFile:
"""
Implements the same interface for files and byte input.
"""
Expand Down
2 changes: 1 addition & 1 deletion pykube/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def send(self, request, **kwargs):
return response


class HTTPClient(object):
class HTTPClient:
"""
Client for interfacing with the Kubernetes API.
"""
Expand Down
4 changes: 2 additions & 2 deletions pykube/mixins.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import time


class ReplicatedMixin(object):
class ReplicatedMixin:

scalable_attr = "replicas"

Expand All @@ -14,7 +14,7 @@ def replicas(self, value):
self.obj["spec"]["replicas"] = value


class ScalableMixin(object):
class ScalableMixin:

@property
def scalable(self):
Expand Down
5 changes: 3 additions & 2 deletions pykube/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .utils import obj_merge


class ObjectManager(object):
class ObjectManager:
def __call__(self, api, namespace=None):
if namespace is None and NamespacedAPIObject in getmro(self.api_obj_class):
namespace = api.config.namespace
Expand All @@ -22,7 +22,7 @@ def __get__(self, obj, api_obj_class):
return self


class APIObject(object):
class APIObject:
'''
Baseclass for all Kubernetes API objects
'''
Expand Down Expand Up @@ -180,6 +180,7 @@ def object_factory(api, api_version, kind):
It is planned to fix this, but in the mean time pass it as you would normally.
"""
resource_list = api.resource_list(api_version)
print(resource_list)
resource = next((resource for resource in resource_list["resources"] if resource["kind"] == kind), None)
base = NamespacedAPIObject if resource["namespaced"] else APIObject
return type(kind, (base,), {
Expand Down
2 changes: 1 addition & 1 deletion pykube/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
now = object()


class BaseQuery(object):
class BaseQuery:

def __init__(self, api, api_obj_class, namespace=None):
self.api = api
Expand Down
41 changes: 40 additions & 1 deletion tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import responses

import pykube
from pykube import KubeConfig, HTTPClient, Deployment
from pykube import KubeConfig, HTTPClient, Deployment, ObjectDoesNotExist


@pytest.fixture
Expand Down Expand Up @@ -191,3 +191,42 @@ def test_list_and_update_deployments(api, requests_mock):
assert len(rsps.calls) == 2

assert json.loads(rsps.calls[-1].request.body) == {"metadata": {"name": "deploy-1"}, "spec": {"replicas": 2}}


def test_pod_exists(api, requests_mock):
with requests_mock as rsps:
obj = {
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "my-pod"
},
"spec": {
"containers": []
}
}
pod = pykube.Pod(api, obj)

rsps.add(responses.GET, 'https://localhost:9443/api/v1/namespaces/default/pods/my-pod',
status=404)
assert not pod.exists()

with pytest.raises(ObjectDoesNotExist):
pod.exists(ensure=True)

rsps.replace(responses.GET, 'https://localhost:9443/api/v1/namespaces/default/pods/my-pod',
json={})
assert pod.exists()


def test_reload(api, requests_mock):
with requests_mock as rsps:
rsps.add(responses.GET, 'https://localhost:9443/api/v1/namespaces/default/pods/my-pod',
json={'metadata': {'name': 'my-pod', 'labels': {'a': 'foo'}}})
pod = pykube.Pod.objects(api).get_by_name('my-pod')
assert pod.labels['a'] == 'foo'

rsps.replace(responses.GET, 'https://localhost:9443/api/v1/namespaces/default/pods/my-pod',
json={'metadata': {'name': 'my-pod', 'labels': {'a': 'bar'}}})
pod.reload()
assert pod.labels['a'] == 'bar'
16 changes: 15 additions & 1 deletion tests/test_objects.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
from unittest.mock import MagicMock

import pykube

from pykube.objects import Pod, NamespacedAPIObject


def test_api_object():
pod = pykube.Pod(None, {'metadata': {'name': 'myname'}})
pod = Pod(None, {'metadata': {'name': 'myname'}})
assert repr(pod) == '<Pod myname>'
assert str(pod) == 'myname'
assert pod.metadata == {'name': 'myname'}
assert pod.labels == {}
assert pod.annotations == {}


def test_object_factory():
api = MagicMock()
api.resource_list.return_value = {'resources': [{'kind': 'ExampleObject', 'namespaced': True, 'name': 'exampleobjects'}]}
ExampleObject = pykube.object_factory(api, 'example.org/v1', 'ExampleObject')
assert ExampleObject.kind == 'ExampleObject'
assert ExampleObject.endpoint == 'exampleobjects'
assert ExampleObject.version == 'example.org/v1'
assert NamespacedAPIObject in ExampleObject.mro()
26 changes: 26 additions & 0 deletions tests/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ def test_get(api):
Query(api, Pod).get(namespace='myns')


def test_get_one_object(api):
response = MagicMock()
response.json.return_value = {'items': [{'metadata': {'name': 'pod1'}}]}
api.get.return_value = response
pod = Query(api, Pod).get(namespace='myns')
assert pod.name == 'pod1'


def test_get_more_than_one_object(api):
response = MagicMock()
response.json.return_value = {'items': [{'metadata': {'name': 'pod1'}}, {'metadata': {'name': 'pod2'}}]}
api.get.return_value = response
with pytest.raises(ValueError):
Query(api, Pod).get(namespace='myns')


def test_filter_by_namespace(api):
Query(api, Pod).filter(namespace='myns').execute()
api.get.assert_called_once_with(namespace='myns', url='pods', version='v1')
Expand All @@ -40,3 +56,13 @@ def test_filter_by_labels_in(api):
def test_filter_by_labels_notin(api):
Query(api, Pod).filter(selector={'application__notin': ['foo', 'bar']}).execute()
api.get.assert_called_once_with(url='pods?labelSelector=application+notin+%28bar%2Cfoo%29', version='v1')


def test_filter_invalid_selector(api):
with pytest.raises(ValueError):
Query(api, Pod).filter(selector={'application__x': 'foo'}).execute()


def test_filter_selector_string(api):
Query(api, Pod).filter(selector='application=foo').execute()
api.get.assert_called_once_with(url='pods?labelSelector=application%3Dfoo', version='v1')

0 comments on commit 729d635

Please sign in to comment.