add namespace to all apis

This commit is contained in:
tifayuki 2016-11-16 14:24:50 -08:00
commit 256de5d2cc
27 changed files with 248 additions and 204 deletions

View file

@ -6,7 +6,7 @@ from .base import Immutable, StreamingLog
class Action(Immutable): class Action(Immutable):
subsystem = 'audit' subsystem = 'audit'
endpoint = "/action" endpoint = "/action"
namespaced = False is_namespaced = False
@classmethod @classmethod
def _pk_key(cls): def _pk_key(cls):

View file

@ -12,6 +12,7 @@ from .http import send_request
HUB_INDEX = "https://index.docker.io/v1/" HUB_INDEX = "https://index.docker.io/v1/"
def authenticate(username, password): def authenticate(username, password):
verify_credential(username, password) verify_credential(username, password)
dockercloud.basic_auth = base64.b64encode("%s:%s" % (username, password)) dockercloud.basic_auth = base64.b64encode("%s:%s" % (username, password))
@ -55,7 +56,8 @@ def load_from_file(f="~/.docker/config.json"):
p = subprocess.Popen([cmd, 'get'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT) p = subprocess.Popen([cmd, 'get'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
out = p.communicate(input=HUB_INDEX)[0] out = p.communicate(input=HUB_INDEX)[0]
except: except:
raise dockercloud.AuthError('error getting credentials - err: exec: "%s": executable file not found in $PATH, out: ``' % cmd) raise dockercloud.AuthError(
'error getting credentials - err: exec: "%s": executable file not found in $PATH, out: ``' % cmd)
try: try:
credential = json.loads(out) credential = json.loads(out)

View file

@ -16,18 +16,19 @@ logger = logging.getLogger("python-dockercloud")
class BasicObject(object): class BasicObject(object):
_api_version = 'v1' _api_version = 'v1'
def __init__(self, **kwargs):
pass
class Restful(BasicObject): class Restful(BasicObject):
_detail_uri = None is_namespaced = True
namespaced = True
def __init__(self, **kwargs): def __init__(self, namespace="", **kwargs):
"""Simply reflect all the values in kwargs""" """Simply reflect all the values in kwargs"""
for k, v in list(kwargs.items()): for k, v in list(kwargs.items()):
setattr(self, k, v) setattr(self, k, v)
if self.is_namespaced and namespace:
self._namespace = namespace
else:
self._namespace = dockercloud.namespace
self._resource_uri = ""
def __addchanges__(self, name): def __addchanges__(self, name):
changed_attrs = self.__getchanges__() changed_attrs = self.__getchanges__()
@ -38,7 +39,7 @@ class Restful(BasicObject):
def __setattr__(self, name, value): def __setattr__(self, name, value):
"""Keeps track of what attributes have been set""" """Keeps track of what attributes have been set"""
current_value = getattr(self, name, None) current_value = getattr(self, name, None)
if value != current_value: if value != current_value and not name.startswith("_"):
self.__addchanges__(name) self.__addchanges__(name)
super(Restful, self).__setattr__(name, value) super(Restful, self).__setattr__(name, value)
@ -53,17 +54,10 @@ class Restful(BasicObject):
def _loaddict(self, dict): def _loaddict(self, dict):
"""Internal. Sets the model attributes to the dictionary values passed""" """Internal. Sets the model attributes to the dictionary values passed"""
endpoint = getattr(self, 'endpoint', None)
subsystem = getattr(self, 'subsystem', None)
assert endpoint, "Endpoint not specified for %s" % self.__class__.__name__
assert subsystem, "Subsystem not specified for %s" % self.__class__.__name__
for k, v in list(dict.items()): for k, v in list(dict.items()):
setattr(self, k, v) setattr(self, k, v)
if self.namespaced and dockercloud.namespace:
self._detail_uri = "/".join(["api", subsystem, self._api_version, dockercloud.namespace, self._resource_uri = getattr(self, "resource_uri", None)
endpoint.strip("/"), self.pk])
else:
self._detail_uri = "/".join(["api", subsystem, self._api_version, endpoint.strip("/"), self.pk])
self.__setchanges__([]) self.__setchanges__([])
@property @property
@ -93,9 +87,9 @@ class Restful(BasicObject):
def _perform_action(self, action, params=None, data={}): def _perform_action(self, action, params=None, data={}):
"""Internal. Performs the specified action on the object remotely""" """Internal. Performs the specified action on the object remotely"""
success = False success = False
if not self._detail_uri: if not self._resource_uri:
raise ApiError("You must save the object before performing this operation") raise ApiError("You must save the object before performing this operation")
path = "/".join([self._detail_uri.rstrip("/"), action.lstrip("/")]) path = "/".join([self._resource_uri.rstrip("/"), action.lstrip("/")])
json = send_request("POST", path, params=params, data=data) json = send_request("POST", path, params=params, data=data)
if json: if json:
self._loaddict(json) self._loaddict(json)
@ -104,9 +98,9 @@ class Restful(BasicObject):
def _expand_attribute(self, attribute): def _expand_attribute(self, attribute):
"""Internal. Expands the given attribute from remote information""" """Internal. Expands the given attribute from remote information"""
if not self._detail_uri: if not self._resource_uri:
raise ApiError("You must save the object before performing this operation") raise ApiError("You must save the object before performing this operation")
path = "/".join([self._detail_uri, attribute]) path = "/".join([self._resource_uri, attribute])
json = send_request("GET", path) json = send_request("GET", path)
if json: if json:
return json[attribute] return json[attribute]
@ -125,39 +119,43 @@ class Restful(BasicObject):
class Immutable(Restful): class Immutable(Restful):
@classmethod @classmethod
def fetch(cls, pk): def fetch(cls, pk, namespace=""):
instance = None
endpoint = getattr(cls, 'endpoint', None) endpoint = getattr(cls, 'endpoint', None)
subsystem = getattr(cls, 'subsystem', None) subsystem = getattr(cls, 'subsystem', None)
assert endpoint, "Endpoint not specified for %s" % cls.__name__ assert endpoint, "Endpoint not specified for %s" % cls.__name__
assert subsystem, "Subsystem not specified for %s" % cls.__name__ assert subsystem, "Subsystem not specified for %s" % cls.__name__
if cls.namespaced and dockercloud.namespace:
detail_uri = "/".join(["api", subsystem, cls._api_version, dockercloud.namespace, endpoint.strip("/"), pk]) if not namespace:
namespace = dockercloud.namespace
if cls.is_namespaced and namespace:
resource_uri = "/".join(["api", subsystem, cls._api_version, namespace, endpoint.strip("/"), pk])
else: else:
detail_uri = "/".join(["api", subsystem, cls._api_version, endpoint.strip("/"), pk]) resource_uri = "/".join(["api", subsystem, cls._api_version, endpoint.strip("/"), pk])
json = send_request('GET', detail_uri) json = send_request('GET', resource_uri)
if json: if json:
instance = cls() instance = cls()
instance._loaddict(json) instance._loaddict(json)
return instance return instance
@classmethod @classmethod
def list(cls, limit=None, **kwargs): def list(cls, limit=None, namespace="", **kwargs):
restful = [] restful = []
endpoint = getattr(cls, 'endpoint', None) endpoint = getattr(cls, 'endpoint', None)
subsystem = getattr(cls, 'subsystem', None) subsystem = getattr(cls, 'subsystem', None)
assert endpoint, "Endpoint not specified for %s" % cls.__name__ assert endpoint, "Endpoint not specified for %s" % cls.__name__
assert subsystem, "Subsystem not specified for %s" % cls.__name__ assert subsystem, "Subsystem not specified for %s" % cls.__name__
if cls.namespaced and dockercloud.namespace: if not namespace:
detail_uri = "/".join(["api", subsystem, cls._api_version, dockercloud.namespace, endpoint.strip("/")]) namespace = dockercloud.namespace
if cls.is_namespaced and namespace:
resource_uri = "/".join(["api", subsystem, cls._api_version, namespace, endpoint.strip("/")])
else: else:
detail_uri = "/".join(["api", subsystem, cls._api_version, endpoint.strip("/")]) resource_uri = "/".join(["api", subsystem, cls._api_version, endpoint.strip("/")])
objects = [] objects = []
while True: while True:
if limit and len(objects) >= limit: if limit and len(objects) >= limit:
break break
json = send_request('GET', detail_uri, params=kwargs) json = send_request('GET', resource_uri, params=kwargs)
objs = json.get('objects', []) objs = json.get('objects', [])
meta = json.get('meta', {}) meta = json.get('meta', {})
next_url = meta.get('next', '') next_url = meta.get('next', '')
@ -182,10 +180,10 @@ class Immutable(Restful):
if self.is_dirty and not force: if self.is_dirty and not force:
# We have local non-committed changes - rejecting the refresh # We have local non-committed changes - rejecting the refresh
success = False success = False
elif not self._detail_uri: elif not self._resource_uri:
raise ApiError("You must save the object before performing this operation") raise ApiError("You must save the object before performing this operation")
else: else:
json = send_request("GET", self._detail_uri) json = send_request("GET", self._resource_uri)
if json: if json:
self._loaddict(json) self._loaddict(json)
success = True success = True
@ -202,16 +200,17 @@ class Mutable(Immutable):
return cls(**kwargs) return cls(**kwargs)
def delete(self): def delete(self):
if not self._detail_uri: if not self._resource_uri:
raise ApiError("You must save the object before performing this operation") raise ApiError("You must save the object before performing this operation")
action = "DELETE" action = "DELETE"
url = self._detail_uri url = self._resource_uri
json = send_request(action, url) json = send_request(action, url)
if json: if json:
self._loaddict(json) self._loaddict(json)
self._resource_uri = None
else: else:
# Object deleted successfully and nothing came back - deleting PK reference. # Object deleted successfully and nothing came back - deleting PK reference.
self._detail_uri = None self._resource_uri = None
# setattr(self, self._pk_key(), None) -- doesn't work # setattr(self, self._pk_key(), None) -- doesn't work
self.__setchanges__([]) self.__setchanges__([])
return True return True
@ -228,15 +227,15 @@ class Mutable(Immutable):
assert endpoint, "Endpoint not specified for %s" % self.__class__.__name__ assert endpoint, "Endpoint not specified for %s" % self.__class__.__name__
assert subsystem, "Subsystem not specified for %s" % self.__class__.__name__ assert subsystem, "Subsystem not specified for %s" % self.__class__.__name__
# Figure out whether we should do a create or update # Figure out whether we should do a create or update
if not self._detail_uri: if not self._resource_uri:
action = "POST" action = "POST"
if cls.namespaced and dockercloud.namespace: if cls.is_namespaced and self._namespace:
path = "/".join(["api", subsystem, self._api_version, dockercloud.namespace, endpoint.lstrip("/")]) path = "/".join(["api", subsystem, self._api_version, self._namespace, endpoint.lstrip("/")])
else: else:
path = "/".join(["api", subsystem, self._api_version, endpoint.lstrip("/")]) path = "/".join(["api", subsystem, self._api_version, endpoint.lstrip("/")])
else: else:
action = "PATCH" action = "PATCH"
path = self._detail_uri path = self._resource_uri
# Construct the necessary params # Construct the necessary params
params = {} params = {}
for attr in self.__getchanges__(): for attr in self.__getchanges__():
@ -322,13 +321,16 @@ class StreamingAPI(BasicObject):
class StreamingLog(StreamingAPI): class StreamingLog(StreamingAPI):
def __init__(self, subsystem, resource, uuid, tail, follow): def __init__(self, subsystem, resource, uuid, tail, follow, namespace=""):
endpoint = "%s/%s/logs/?follow=%s" % (resource, uuid, str(follow).lower()) endpoint = "%s/%s/logs/?follow=%s" % (resource, uuid, str(follow).lower())
if tail: if tail:
endpoint = "%s&tail=%d" % (endpoint, tail) endpoint = "%s&tail=%d" % (endpoint, tail)
if dockercloud.namespace:
if not namespace:
namespace = dockercloud.namespace
if namespace:
url = "/".join([dockercloud.stream_host.rstrip("/"), "api", subsystem, self._api_version, url = "/".join([dockercloud.stream_host.rstrip("/"), "api", subsystem, self._api_version,
dockercloud.namespace, endpoint.lstrip("/")]) self._namespace, endpoint.lstrip("/")])
else: else:
url = "/".join([dockercloud.stream_host.rstrip("/"), "api", subsystem, self._api_version, url = "/".join([dockercloud.stream_host.rstrip("/"), "api", subsystem, self._api_version,
endpoint.lstrip("/")]) endpoint.lstrip("/")])
@ -348,11 +350,13 @@ class StreamingLog(StreamingAPI):
class Exec(StreamingAPI): class Exec(StreamingAPI):
def __init__(self, uuid, cmd='sh'): def __init__(self, uuid, cmd='sh', namespace=""):
endpoint = "container/%s/exec/?command=%s" % (uuid, urllib.quote_plus(cmd)) endpoint = "container/%s/exec/?command=%s" % (uuid, urllib.quote_plus(cmd))
if dockercloud.namespace: if not namespace:
namespace = dockercloud.namespace
if namespace:
url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "app", self._api_version, url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "app", self._api_version,
dockercloud.namespace, endpoint.lstrip("/")]) namespace, endpoint.lstrip("/")])
else: else:
url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "app", self._api_version, endpoint.lstrip("/")]) url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "app", self._api_version, endpoint.lstrip("/")])
super(self.__class__, self).__init__(url) super(self.__class__, self).__init__(url)

View file

@ -13,11 +13,14 @@ logger = logging.getLogger("python-dockercloud")
class Events(StreamingAPI): class Events(StreamingAPI):
def __init__(self): def __init__(self, namespace=""):
endpoint = "events" endpoint = "events"
if dockercloud.namespace:
if not namespace:
namespace = dockercloud.namespace
if namespace:
url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "audit", self._api_version, url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "audit", self._api_version,
dockercloud.namespace, endpoint.lstrip("/")]) namespace, endpoint.lstrip("/")])
else: else:
url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "audit", self._api_version, url = "/".join([dockercloud.stream_host.rstrip("/"), "api", "audit", self._api_version,
endpoint.lstrip("/")]) endpoint.lstrip("/")])

View file

@ -8,7 +8,7 @@ class Node(Mutable, Taggable):
endpoint = "/node" endpoint = "/node"
def save(self): def save(self):
if not self._detail_uri: if not self.resource_uri:
raise AttributeError("Adding a new node is not supported via 'save' method") raise AttributeError("Adding a new node is not supported via 'save' method")
super(Node, self).save() super(Node, self).save()

View file

@ -6,7 +6,7 @@ from .base import Immutable
class AZ(Immutable): class AZ(Immutable):
subsystem = "infra" subsystem = "infra"
endpoint = "/az" endpoint = "/az"
namespaced = False is_namespaced = False
@classmethod @classmethod
def _pk_key(cls): def _pk_key(cls):

View file

@ -16,7 +16,7 @@ class NodeCluster(Mutable, Taggable):
def create(cls, **kwargs): def create(cls, **kwargs):
for key, value in kwargs.items(): for key, value in kwargs.items():
if key == "node_type" and isinstance(value, NodeType): if key == "node_type" and isinstance(value, NodeType):
kwargs[key] = getattr(value, "resource_uri", "") kwargs[key] = getattr(value, "_resource_uri", "")
if key == "region" and isinstance(value, Region): if key == "region" and isinstance(value, Region):
kwargs[key] = getattr(value, "resource_uri", "") kwargs[key] = getattr(value, "_resource_uri", "")
return cls(**kwargs) return cls(**kwargs)

View file

@ -6,7 +6,7 @@ from .base import Immutable
class Provider(Immutable): class Provider(Immutable):
subsystem = "infra" subsystem = "infra"
endpoint = "/provider" endpoint = "/provider"
namespaced = False is_namespaced = False
@classmethod @classmethod
def _pk_key(cls): def _pk_key(cls):

View file

@ -6,7 +6,7 @@ from .base import Immutable
class Region(Immutable): class Region(Immutable):
subsystem = "infra" subsystem = "infra"
endpoint = "/region" endpoint = "/region"
namespaced = False is_namespaced = False
@classmethod @classmethod
def _pk_key(cls): def _pk_key(cls):

View file

@ -6,7 +6,7 @@ from .base import Immutable
class NodeType(Immutable): class NodeType(Immutable):
subsystem = "infra" subsystem = "infra"
endpoint = "/nodetype" endpoint = "/nodetype"
namespaced = False is_namespaced = False
@classmethod @classmethod
def _pk_key(cls): def _pk_key(cls):

View file

@ -20,7 +20,7 @@ class Stack(Mutable):
return self._perform_action("redeploy", params=params) return self._perform_action("redeploy", params=params)
def export(self): def export(self):
if not self._detail_uri: if not self.resource_uri:
raise ApiError("You must save the object before performing this operation") raise ApiError("You must save the object before performing this operation")
url = "/".join([self._detail_uri, "export"]) url = "/".join([self.resource_uri, "export"])
return send_request("GET", url, inject_header=False) return send_request("GET", url, inject_header=False)

View file

@ -57,7 +57,7 @@ class Tag(BasicObject):
def fetch(cls, taggable): def fetch(cls, taggable):
if not isinstance(taggable, Taggable): if not isinstance(taggable, Taggable):
raise ApiError("The object does not support tag") raise ApiError("The object does not support tag")
if not taggable._detail_uri: if not taggable.resource_uri:
raise ApiError("You must save the taggable object before performing this operation") raise ApiError("You must save the taggable object before performing this operation")
tag = cls() tag = cls()

View file

@ -8,6 +8,7 @@ from .http import send_request
class Trigger(BasicObject): class Trigger(BasicObject):
def __init__(self): def __init__(self):
self.trigger = None self.trigger = None
self.resource_uri = None
def add(self, name=None, operation=None): def add(self, name=None, operation=None):
@ -30,11 +31,11 @@ class Trigger(BasicObject):
return cls(**kwargs) return cls(**kwargs)
def delete(self, uuid): def delete(self, uuid):
if not self.endpoint: if not self.resource_uri:
raise ApiError("You must initialize the Trigger object before performing this operation") raise ApiError("You must initialize the Trigger object before performing this operation")
action = "DELETE" action = "DELETE"
url = "/".join([self.endpoint, uuid]) url = "/".join([self.resource_uri, uuid])
send_request(action, url) send_request(action, url)
return True return True
@ -43,11 +44,11 @@ class Trigger(BasicObject):
if not isinstance(triggerable, Triggerable): if not isinstance(triggerable, Triggerable):
raise ApiError("The object does not support trigger") raise ApiError("The object does not support trigger")
if not triggerable._detail_uri: if not triggerable.resource_uri:
raise ApiError("You must save the triggerable object before performing this operation") raise ApiError("You must save the triggerable object before performing this operation")
trigger = cls() trigger = cls()
trigger.endpoint = "/".join([triggerable._detail_uri, "trigger"]) trigger.resource_uri = "/".join([triggerable.resource_uri, "trigger"])
handlers = [] handlers = []
for t in trigger.list(): for t in trigger.list():
triggername = t.get("name", "") triggername = t.get("name", "")
@ -56,12 +57,12 @@ class Trigger(BasicObject):
return trigger return trigger
def list(self, **kwargs): def list(self, **kwargs):
if not self.endpoint: if not self.resource_uri:
raise ApiError("You must initialize the Trigger object before performing this operation") raise ApiError("You must initialize the Trigger object before performing this operation")
objects = [] objects = []
while True: while True:
json = send_request('GET', self.endpoint, params=kwargs) json = send_request('GET', self.resource_uri, params=kwargs)
objs = json.get('objects', []) objs = json.get('objects', [])
meta = json.get('meta', {}) meta = json.get('meta', {})
next_url = meta.get('next', '') next_url = meta.get('next', '')
@ -77,23 +78,23 @@ class Trigger(BasicObject):
return objects return objects
def save(self): def save(self):
if not self.endpoint: if not self.resource_uri:
raise ApiError("You must initialize the Trigger object before performing this operation") raise ApiError("You must initialize the Trigger object before performing this operation")
if self.trigger is None: if self.trigger is None:
return True return True
json = send_request("POST", self.endpoint, data=json_parser.dumps(self.trigger)) json = send_request("POST", self.resource_uri, data=json_parser.dumps(self.trigger))
if json: if json:
self.clear() self.clear()
self.clear() self.clear()
return True return True
def call(self, uuid): def call(self, uuid):
if not self.endpoint: if not self.resource_uri:
raise ApiError("You must initialize the Trigger object before performing this operation") raise ApiError("You must initialize the Trigger object before performing this operation")
json = send_request("POST", "/".join([self.endpoint, uuid + "/call"])) json = send_request("POST", "/".join([self.resource_uri, uuid + "/call"]))
if json: if json:
return True return True
return False return False

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -4,6 +4,9 @@ import os
import tempfile import tempfile
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud
@ -75,7 +78,6 @@ class AuthTestCase(unittest.TestCase):
dockercloud.basic_auth = FAKE_BASIC_AUTH dockercloud.basic_auth = FAKE_BASIC_AUTH
self.assertEqual({'Authorization': FAKE_DOCKERCLOUD_AUTH}, dockercloud.auth.get_auth_header()) self.assertEqual({'Authorization': FAKE_DOCKERCLOUD_AUTH}, dockercloud.auth.get_auth_header())
print "===================="
dockercloud.dockercloud_auth = None dockercloud.dockercloud_auth = None
dockercloud.basic_auth = FAKE_BASIC_AUTH dockercloud.basic_auth = FAKE_BASIC_AUTH
self.assertEqual({'Authorization': 'Basic %s' % (FAKE_BASIC_AUTH)}, dockercloud.auth.get_auth_header()) self.assertEqual({'Authorization': 'Basic %s' % (FAKE_BASIC_AUTH)}, dockercloud.auth.get_auth_header())

View file

@ -3,6 +3,9 @@ from __future__ import absolute_import
import json import json
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud
@ -54,14 +57,12 @@ class RestfulTestCase(unittest.TestCase):
def test_restful_loaddict(self): def test_restful_loaddict(self):
model = Restful() model = Restful()
self.assertRaises(AssertionError, model._loaddict, {'key': 'value'}) model.endpoint = 'resource_uri'
model.endpoint = 'endpoint'
model.subsystem = "subsystem" model.subsystem = "subsystem"
model._loaddict({'key': 'value'}) resource_uri = "/".join(["api", model.subsystem, model._api_version, model.endpoint.lstrip("/"), model.pk])
model._loaddict({'key': 'value', "resource_uri": resource_uri})
self.assertEqual('value', model.key) self.assertEqual('value', model.key)
self.assertEqual("/".join(["api", model.subsystem, model._api_version, model.endpoint.lstrip("/"), model.pk]), self.assertEqual(resource_uri, model._resource_uri)
model._detail_uri)
self.assertEqual([], model.__getchanges__()) self.assertEqual([], model.__getchanges__())
def test_restful_pk(self): def test_restful_pk(self):
@ -77,32 +78,29 @@ class RestfulTestCase(unittest.TestCase):
@mock.patch('dockercloud.api.base.send_request') @mock.patch('dockercloud.api.base.send_request')
def test_restful_perform_action(self, mock_send_request): def test_restful_perform_action(self, mock_send_request):
try:
model = Restful() model = Restful()
self.assertRaises(dockercloud.ApiError, model._perform_action, 'action') self.assertRaises(dockercloud.ApiError, model._perform_action, 'action')
model.endpoint = 'fake' model.endpoint = 'fake'
model.subsystem = "subsystem" model.subsystem = "subsystem"
model._detail_uri = "/".join( model.resource_uri = "/".join(
["api", model.subsystem, model._api_version, model.endpoint.lstrip("/"), model.pk]) ["api", model.subsystem, model._api_version, model.endpoint.lstrip("/"), model.pk])
model._resource_uri = model.resource_uri
mock_send_request.side_effect = [{'key': 'value'}, None] mock_send_request.side_effect = [{'key': 'value'}, None]
self.assertTrue(model._perform_action('action', params={'k': 'v'}, data={'key': 'value'})) self.assertTrue(model._perform_action('action', params={'k': 'v'}, data={'key': 'value'}))
self.assertEqual('value', model.key) self.assertEqual('value', model.key)
mock_send_request.assert_called_with('POST', "/".join([model._detail_uri, "action"]), data={'key': 'value'}, mock_send_request.assert_called_with('POST', "/".join([model._resource_uri, "action"]), data={'key': 'value'},
params={'k': 'v'}) params={'k': 'v'})
self.assertFalse(model._perform_action('action', {'key': 'value'})) self.assertFalse(model._perform_action('action', {'key': 'value'}))
finally:
if hasattr(Restful, 'endpoint'):
delattr(Restful, 'endpoint')
@mock.patch('dockercloud.api.base.send_request') @mock.patch('dockercloud.api.base.send_request')
def test_restful_expand_attribute(self, mock_send_request): def test_restful_expand_attribute(self, mock_send_request):
model = Restful() model = Restful()
self.assertRaises(dockercloud.ApiError, model._expand_attribute, 'attribute') self.assertRaises(dockercloud.ApiError, model._expand_attribute, 'attribute')
model._detail_uri = 'fake/uuid' model._resource_uri = 'fake/uuid'
mock_send_request.side_effect = [{'key': 'value'}, None] mock_send_request.side_effect = [{'key': 'value'}, None]
self.assertEqual('value', model._expand_attribute('key')) self.assertEqual('value', model._expand_attribute('key'))
@ -124,30 +122,37 @@ class ImmutableTestCase(unittest.TestCase):
@mock.patch('dockercloud.api.base.send_request') @mock.patch('dockercloud.api.base.send_request')
def test_immutable_fetch(self, mock_send_request): def test_immutable_fetch(self, mock_send_request):
try:
delattr(Immutable, 'endpoint')
delattr(Immutable, 'subsystem')
except:
pass
self.assertRaises(AssertionError, Immutable.fetch, 'uuid') self.assertRaises(AssertionError, Immutable.fetch, 'uuid')
try:
ret_json = {"key": "value"} ret_json = {"key": "value"}
mock_send_request.return_value = ret_json mock_send_request.return_value = ret_json
Immutable.endpoint = 'endpoint' Immutable.endpoint = 'resource_uri'
Immutable.subsystem = "subsystem" Immutable.subsystem = "subsystem"
model = Immutable.fetch('uuid') model = Immutable.fetch('uuid')
mock_send_request.assert_called_with('GET', 'api/subsystem/%s/endpoint/uuid' % Immutable._api_version) mock_send_request.assert_called_with('GET', 'api/subsystem/%s/resource_uri/uuid' % Immutable._api_version)
self.assertIsInstance(model, Immutable) self.assertIsInstance(model, Immutable)
self.assertEqual('value', model.key) self.assertEqual('value', model.key)
finally:
if hasattr(Immutable, 'endpoint'):
delattr(Immutable, 'endpoint')
@mock.patch('dockercloud.api.base.send_request') @mock.patch('dockercloud.api.base.send_request')
def test_immutable_list(self, mock_send_request): def test_immutable_list(self, mock_send_request):
self.assertRaises(AssertionError, Immutable.list)
try: try:
delattr(Immutable, 'endpoint')
delattr(Immutable, 'subsystem')
except:
pass
self.assertRaises(AssertionError, Immutable.list)
kwargs = {'key': 'value'} kwargs = {'key': 'value'}
ret_json = {"meta": {"limit": 25, "next": None, "offset": 0, "previous": None, "total_count": 1}, ret_json = {"meta": {"limit": 25, "next": None, "offset": 0, "previous": None, "total_count": 1},
"objects": [{"key": "value1"}, {"key": "value2"}]} "objects": [{"key": "value1"}, {"key": "value2"}]}
mock_send_request.return_value = ret_json mock_send_request.return_value = ret_json
Immutable.endpoint = 'fake' Immutable.endpoint = 'fake'
Immutable.subsystem = "subsystem"
models = Immutable.list(**kwargs) models = Immutable.list(**kwargs)
mock_send_request.assert_called_with('GET', 'api/subsystem/%s/fake' % Immutable._api_version, params=kwargs) mock_send_request.assert_called_with('GET', 'api/subsystem/%s/fake' % Immutable._api_version, params=kwargs)
self.assertEqual(2, len(models)) self.assertEqual(2, len(models))
@ -155,32 +160,27 @@ class ImmutableTestCase(unittest.TestCase):
self.assertEqual('value1', models[0].key) self.assertEqual('value1', models[0].key)
self.assertIsInstance(models[1], Immutable) self.assertIsInstance(models[1], Immutable)
self.assertEqual('value2', models[1].key) self.assertEqual('value2', models[1].key)
finally:
if hasattr(Immutable, 'endpoint'):
delattr(Immutable, 'endpoint')
@mock.patch('dockercloud.api.base.send_request') @mock.patch('dockercloud.api.base.send_request')
def test_immutable_refresh(self, mock_send_request): def test_immutable_refresh(self, mock_send_request):
try:
model = Immutable() model = Immutable()
model.key = 'value' model.key = 'value'
self.assertFalse(model.refresh(force=False)) self.assertFalse(model.refresh(force=False))
self.assertRaises(dockercloud.ApiError, model.refresh, force=True) self.assertRaises(dockercloud.ApiError, model.refresh, force=True)
Immutable.endpoint = 'endpoint' Immutable.endpoint = 'resource_uri'
Immutable.subsystem = 'subsystem' Immutable.subsystem = 'subsystem'
model._detail_uri = 'api/subsystem/%s/endpoint/uuid' % Immutable._api_version model.resource_uri = 'api/subsystem/%s/resource_uri/uuid' % Immutable._api_version
model._resource_uri = model.resource_uri
mock_send_request.side_effect = [{'newkey': 'newvalue'}, None] mock_send_request.side_effect = [{'newkey': 'newvalue'}, None]
self.assertTrue(model.refresh(force=True)) self.assertTrue(model.refresh(force=True))
self.assertEqual('newvalue', model.newkey) self.assertEqual('newvalue', model.newkey)
mock_send_request.assert_called_with('GET', model._detail_uri) mock_send_request.assert_called_with('GET', model._resource_uri)
self.assertFalse(model.refresh(force=True)) self.assertFalse(model.refresh(force=True))
mock_send_request.assert_called_with('GET', model._detail_uri) mock_send_request.assert_called_with('GET', model._resource_uri)
finally:
if hasattr(Immutable, 'endpoint'):
delattr(Immutable, 'endpoint')
class MutableTestCase(unittest.TestCase): class MutableTestCase(unittest.TestCase):
@ -196,57 +196,56 @@ class MutableTestCase(unittest.TestCase):
@mock.patch('dockercloud.api.base.send_request') @mock.patch('dockercloud.api.base.send_request')
def test_mutable_delete(self, mock_send_request): def test_mutable_delete(self, mock_send_request):
try:
model = Mutable() model = Mutable()
self.assertRaises(dockercloud.ApiError, model.delete) self.assertRaises(dockercloud.ApiError, model.delete)
Mutable.endpoint = 'fake' Mutable.endpoint = 'fake'
model._detail_uri = 'fake/uuid' model._resource_uri = 'fake/uuid'
mock_send_request.side_effect = [{'key': 'value'}, None] mock_send_request.side_effect = [{'key': 'value'}, None]
self.assertTrue(model.delete()) self.assertTrue(model.delete())
self.assertEqual('value', model.key) self.assertEqual('value', model.key)
mock_send_request.assert_called_with('DELETE', 'fake/uuid') mock_send_request.assert_called_with('DELETE', 'fake/uuid')
model = Mutable()
model._resource_uri = 'fake/uuid'
self.assertTrue(model.delete()) self.assertTrue(model.delete())
self.assertIsNone(model._detail_uri) self.assertIsNone(model._resource_uri)
self.assertFalse(model.is_dirty) self.assertFalse(model.is_dirty)
finally:
if hasattr(Mutable, 'endpoint'):
delattr(Mutable, 'endpoint')
@mock.patch('dockercloud.api.base.send_request') @mock.patch('dockercloud.api.base.send_request')
def test_mutable_save(self, mock_send_request): def test_mutable_save(self, mock_send_request):
try:
self.assertTrue(Mutable().save()) self.assertTrue(Mutable().save())
model = Mutable() model = Mutable()
model.key = 'value' model.key = 'value'
try:
delattr(Immutable, 'endpoint')
delattr(Immutable, 'subsystem')
except:
pass
self.assertRaises(AssertionError, model.save) self.assertRaises(AssertionError, model.save)
Mutable.endpoint = 'endpoint' Mutable.endpoint = 'resource_uri'
Mutable.subsystem = 'subsystem' Mutable.subsystem = 'subsystem'
mock_send_request.return_value = None mock_send_request.return_value = None
result = model.save() result = model.save()
mock_send_request.assert_called_with('POST', 'api/subsystem/%s/endpoint' % Mutable._api_version, mock_send_request.assert_called_with('POST', 'api/subsystem/%s/resource_uri' % Mutable._api_version,
data=json.dumps({'key': 'value'})) data=json.dumps({'key': 'value'}))
self.assertFalse(result) self.assertFalse(result)
mock_send_request.return_value = {'newkey': 'newvalue'} mock_send_request.return_value = {'newkey': 'newvalue'}
result = model.save() result = model.save()
mock_send_request.assert_called_with('POST', 'api/subsystem/%s/endpoint' % Mutable._api_version, mock_send_request.assert_called_with('POST', 'api/subsystem/%s/resource_uri' % Mutable._api_version,
data=json.dumps({'key': 'value'})) data=json.dumps({'key': 'value'}))
self.assertTrue(result) self.assertTrue(result)
self.assertEqual('newvalue', model.newkey) self.assertEqual('newvalue', model.newkey)
model.key = 'another value' model.key = 'another value'
mock_send_request.return_value = {'newkey2': 'newvalue2'} mock_send_request.return_value = {'newkey2': 'newvalue2'}
model._detail_uri = 'api/subsystem/%s/endpoint/uuid' % Immutable._api_version model._resource_uri = 'api/subsystem/%s/resource_uri/uuid' % Immutable._api_version
result = model.save() result = model.save()
mock_send_request.assert_called_with('PATCH', 'api/subsystem/%s/endpoint/uuid' % Mutable._api_version, mock_send_request.assert_called_with('PATCH', 'api/subsystem/%s/resource_uri/uuid' % Mutable._api_version,
data=json.dumps({'key': 'another value'})) data=json.dumps({'key': 'another value'}))
self.assertTrue(result) self.assertTrue(result)
self.assertEqual('another value', model.key) self.assertEqual('another value', model.key)
self.assertEqual('newvalue2', model.newkey2) self.assertEqual('newvalue2', model.newkey2)
finally:
if hasattr(Mutable, 'endpoint'):
delattr(Mutable, 'endpoint')

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -1,8 +1,11 @@
from __future__ import absolute_import from __future__ import absolute_import
import requests
import unittest import unittest
import requests try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -2,6 +2,9 @@ from __future__ import absolute_import
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud

View file

@ -1,5 +1,8 @@
import unittest import unittest
try:
import mock
except ImportError:
import unittest.mock as mock import unittest.mock as mock
import dockercloud import dockercloud