You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/12/27 08:36:40 UTC
libcloud git commit: Allow Passing in Full API URL to Rancher Driver
Repository: libcloud
Updated Branches:
refs/heads/trunk 5e153d03c -> 88a59541e
Allow Passing in Full API URL to Rancher Driver
The scheme (secure) and port no longer need to be explicitly specified.
Closes #958
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/88a59541
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/88a59541
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/88a59541
Branch: refs/heads/trunk
Commit: 88a59541e28e11a01941fdac2acf1fedb0f45594
Parents: 5e153d0
Author: Matthew Ellison <ma...@arroyonetworks.com>
Authored: Mon Dec 12 19:27:21 2016 -0500
Committer: Anthony Shaw <an...@apache.org>
Committed: Tue Dec 27 19:36:22 2016 +1100
----------------------------------------------------------------------
libcloud/container/drivers/rancher.py | 71 +++++----
libcloud/test/container/test_rancher.py | 218 +++++++++++++++++----------
2 files changed, 181 insertions(+), 108 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/88a59541/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index eda0058..9bd87e6 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -20,7 +20,7 @@ try:
except:
import json
-from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import httplib, urlparse
from libcloud.utils.py3 import b
from libcloud.common.base import JsonResponse, ConnectionUserAndKey
@@ -85,22 +85,13 @@ class RancherConnection(ConnectionUserAndKey):
class RancherContainerDriver(ContainerDriver):
+ """
+ Driver for Rancher by Rancher Labs.
- type = Provider.RANCHER
- name = 'Rancher'
- website = 'http://rancher.com'
- connectionCls = RancherConnection
- # Holding off on cluster support for now.
- # Only Environment API interaction enabled.
- supports_clusters = False
- # As in the /v1/
- version = '1'
-
- def __init__(self, key, secret, secure=True, host='localhost', port=443):
- """
- Rancher Container driver class.
+ This driver is capable of interacting with the Version 1 API of Rancher.
+ It currently does NOT support the Version 2 API.
- Example:
+ Example:
>>> from libcloud.container.providers import get_driver
>>> from libcloud.container.types import Provider
@@ -114,6 +105,24 @@ class RancherContainerDriver(ContainerDriver):
>>> newcontainer = connection.deploy_container("myawesomepastebin",
image, environment={"STORAGE_TYPE": "file"})
+ :ivar baseuri: The URL base path to the API.
+ :type baseuri: ``str``
+ """
+
+ type = Provider.RANCHER
+ name = 'Rancher'
+ website = 'http://rancher.com'
+ connectionCls = RancherConnection
+ # Holding off on cluster support for now.
+ # Only Environment API interaction enabled.
+ supports_clusters = False
+ # As in the /v1/
+ version = '1'
+
+ def __init__(self, key, secret, secure=True, host='localhost', port=443):
+ """
+ Creates a new Rancher Container driver.
+
:param key: API key or username to used (required)
:type key: ``str``
@@ -123,32 +132,30 @@ class RancherContainerDriver(ContainerDriver):
:param secure: Whether to use HTTPS or HTTP.
:type secure: ``bool``
- :param host: Override hostname used for connections.
+ :param host: Override hostname used for connections. This can also
+ be a full URL string, including scheme, port, and base path.
:type host: ``str``
:param port: Override port used for connections.
:type port: ``int``
-
- :return: ``None``
+ :return: A newly initialized driver instance.
"""
- if host.startswith('http://'):
- secure = False
-
- super(RancherContainerDriver, self).__init__(key=key, secret=secret,
- secure=secure, host=host,
- port=port)
+ # Parse the Given Host
+ if '://' not in host and not host.startswith("//"):
+ host = '//' + host
+ parsed = urlparse.urlparse(host)
- # strip the prefix
- prefixes = ['http://', 'https://']
- for prefix in prefixes:
- if host.startswith(prefix):
- host = host.strip(prefix)
+ super(RancherContainerDriver, self).__init__(
+ key=key,
+ secret=secret,
+ secure=False if parsed.scheme == 'http' else secure,
+ host=parsed.hostname,
+ port=parsed.port if parsed.port else port
+ )
- # We only support environment api keys, meaning none of this:
- # self.baseuri = "/v%s/projects/%s" % (self.version, project_id)
- self.baseuri = "/v%s" % self.version
+ self.baseuri = parsed.path if parsed.path else "/v%s" % self.version
def ex_list_stacks(self):
"""
http://git-wip-us.apache.org/repos/asf/libcloud/blob/88a59541/libcloud/test/container/test_rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_rancher.py b/libcloud/test/container/test_rancher.py
index eb23ddf..a2997e4 100644
--- a/libcloud/test/container/test_rancher.py
+++ b/libcloud/test/container/test_rancher.py
@@ -26,13 +26,151 @@ from libcloud.test.file_fixtures import ContainerFileFixtures
from libcloud.test import MockHttp
+# --------------------------------------------------------------------------- #
+# Mock Classes
+
+class RancherMockHttp(MockHttp):
+ fixtures = ContainerFileFixtures('rancher')
+
+ def _v1_environments(self, method, url, body, headers):
+ if method == 'GET':
+ return (httplib.OK, self.fixtures.load('ex_list_stacks.json'), {},
+ httplib.responses[httplib.OK])
+ else:
+ return (httplib.OK, self.fixtures.load('ex_deploy_stack.json'), {},
+ httplib.responses[httplib.OK])
+
+ def _v1_environments_1e9(self, method, url, body, headers):
+ return (httplib.OK, self.fixtures.load('ex_deploy_stack.json'), {},
+ httplib.responses[httplib.OK])
+
+ def _v1_environments_1e10(self, method, url, body, headers):
+ return (httplib.OK, self.fixtures.load('ex_destroy_stack.json'), {},
+ httplib.responses[httplib.OK])
+
+ def _v1_environments_1e1(self, method, url, body, headers):
+ return (httplib.OK, self.fixtures.load('ex_activate_stack.json'), {},
+ httplib.responses[httplib.OK])
+
+ def _v1_services(self, method, url, body, headers):
+ if '?healthState=healthy' in url:
+ return (httplib.OK, self.fixtures.load('ex_search_services.json'),
+ {}, httplib.responses[httplib.OK])
+ elif method == 'GET':
+ return (httplib.OK, self.fixtures.load('ex_list_services.json'),
+ {}, httplib.responses[httplib.OK])
+ else:
+ return (httplib.OK, self.fixtures.load('ex_deploy_service.json'),
+ {}, httplib.responses[httplib.OK])
+
+ def _v1_services_1s13(self, method, url, body, headers):
+ if method == 'GET':
+ return (httplib.OK, self.fixtures.load('ex_deploy_service.json'),
+ {}, httplib.responses[httplib.OK])
+ elif method == 'DELETE':
+ return (httplib.OK, self.fixtures.load('ex_destroy_service.json'),
+ {}, httplib.responses[httplib.OK])
+
+ def _v1_services_1s6(self, method, url, body, headers):
+ return (httplib.OK, self.fixtures.load('ex_activate_service.json'), {},
+ httplib.responses[httplib.OK])
+
+ def _v1_containers(self, method, url, body, headers):
+ if '?state=running' in url:
+ return (httplib.OK,
+ self.fixtures.load('ex_search_containers.json'), {},
+ httplib.responses[httplib.OK])
+ elif method == 'POST':
+ return (httplib.OK, self.fixtures.load('deploy_container.json'),
+ {}, httplib.responses[httplib.OK])
+ return (httplib.OK, self.fixtures.load('list_containers.json'), {},
+ httplib.responses[httplib.OK])
+
+ def _v1_containers_1i31(self, method, url, body, headers):
+ if method == 'GET':
+ return (httplib.OK, self.fixtures.load('deploy_container.json'),
+ {}, httplib.responses[httplib.OK])
+ elif method == 'DELETE' or '?action=stop' in url:
+ return (httplib.OK, self.fixtures.load('stop_container.json'), {},
+ httplib.responses[httplib.OK])
+ elif '?action=start' in url:
+ return (httplib.OK, self.fixtures.load('start_container.json'), {},
+ httplib.responses[httplib.OK])
+ else:
+ return (httplib.OK, self.fixtures.load('deploy_container.json'),
+ {}, httplib.responses[httplib.OK])
+
+
+RancherContainerDriver.connectionCls.conn_classes = (
+ RancherMockHttp, RancherMockHttp
+)
+RancherMockHttp.type = None
+RancherMockHttp.use_param = 'a'
+
+
+# --------------------------------------------------------------------------- #
+# Test Cases
+
+
+class RancherContainerDriverInitTestCase(unittest.TestCase):
+ """
+ Tests for testing the different permutations of the driver initialization
+ string.
+ """
+
+ def test_full_url_string(self):
+ """
+ Test a 'full' URL string, which contains a scheme, port, and base path.
+ """
+ path = "http://myhostname:1234/base"
+ driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path)
+
+ self.assertEqual(driver.secure, False)
+ self.assertEqual(driver.connection.host, "myhostname")
+ self.assertEqual(driver.connection.port, 1234)
+ self.assertEqual(driver.baseuri, "/base")
+
+ def test_url_string_no_port(self):
+ """
+ Test a partial URL string, which contains a scheme, and base path.
+ """
+ path = "http://myhostname/base"
+ driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path,
+ port=1234)
+
+ self.assertEqual(driver.secure, False)
+ self.assertEqual(driver.connection.host, "myhostname")
+ self.assertEqual(driver.connection.port, 1234)
+ self.assertEqual(driver.baseuri, "/base")
+
+ def test_url_string_no_scheme(self):
+ """
+ Test a partial URL string, which contains a port, and base path.
+ """
+ path = "myhostname:1234/base"
+ driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path)
+
+ self.assertEqual(driver.secure, True)
+ self.assertEqual(driver.connection.host, "myhostname")
+ self.assertEqual(driver.connection.port, 1234)
+ self.assertEqual(driver.baseuri, "/base")
+
+ def test_url_string_no_base_path(self):
+ """
+ Test a partial URL string, which contains a scheme, and a port.
+ """
+ path = "http://myhostname:1234"
+ driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER, host=path)
+
+ self.assertEqual(driver.secure, False)
+ self.assertEqual(driver.connection.host, "myhostname")
+ self.assertEqual(driver.connection.port, 1234)
+ self.assertEqual(driver.baseuri, "/v%s" % driver.version)
+
+
class RancherContainerDriverTestCase(unittest.TestCase):
def setUp(self):
- RancherContainerDriver.connectionCls.conn_classes = (
- RancherMockHttp, RancherMockHttp)
- RancherMockHttp.type = None
- RancherMockHttp.use_param = 'a'
self.driver = RancherContainerDriver(*CONTAINER_PARAMS_RANCHER)
# Stacks
@@ -186,77 +324,5 @@ class RancherContainerDriverTestCase(unittest.TestCase):
self.assertEqual(destroyed.extra['state'], "stopping")
-class RancherMockHttp(MockHttp):
- fixtures = ContainerFileFixtures('rancher')
-
- def _v1_environments(self, method, url, body, headers):
- if method == 'GET':
- return (httplib.OK, self.fixtures.load('ex_list_stacks.json'), {},
- httplib.responses[httplib.OK])
- else:
- return (httplib.OK, self.fixtures.load('ex_deploy_stack.json'), {},
- httplib.responses[httplib.OK])
-
- def _v1_environments_1e9(self, method, url, body, headers):
- return (httplib.OK, self.fixtures.load('ex_deploy_stack.json'), {},
- httplib.responses[httplib.OK])
-
- def _v1_environments_1e10(self, method, url, body, headers):
- return (httplib.OK, self.fixtures.load('ex_destroy_stack.json'), {},
- httplib.responses[httplib.OK])
-
- def _v1_environments_1e1(self, method, url, body, headers):
- return (httplib.OK, self.fixtures.load('ex_activate_stack.json'), {},
- httplib.responses[httplib.OK])
-
- def _v1_services(self, method, url, body, headers):
- if '?healthState=healthy' in url:
- return (httplib.OK, self.fixtures.load('ex_search_services.json'),
- {}, httplib.responses[httplib.OK])
- elif method == 'GET':
- return (httplib.OK, self.fixtures.load('ex_list_services.json'),
- {}, httplib.responses[httplib.OK])
- else:
- return (httplib.OK, self.fixtures.load('ex_deploy_service.json'),
- {}, httplib.responses[httplib.OK])
-
- def _v1_services_1s13(self, method, url, body, headers):
- if method == 'GET':
- return (httplib.OK, self.fixtures.load('ex_deploy_service.json'),
- {}, httplib.responses[httplib.OK])
- elif method == 'DELETE':
- return (httplib.OK, self.fixtures.load('ex_destroy_service.json'),
- {}, httplib.responses[httplib.OK])
-
- def _v1_services_1s6(self, method, url, body, headers):
- return (httplib.OK, self.fixtures.load('ex_activate_service.json'), {},
- httplib.responses[httplib.OK])
-
- def _v1_containers(self, method, url, body, headers):
- if '?state=running' in url:
- return (httplib.OK,
- self.fixtures.load('ex_search_containers.json'), {},
- httplib.responses[httplib.OK])
- elif method == 'POST':
- return (httplib.OK, self.fixtures.load('deploy_container.json'),
- {}, httplib.responses[httplib.OK])
- return (httplib.OK, self.fixtures.load('list_containers.json'), {},
- httplib.responses[httplib.OK])
-
- def _v1_containers_1i31(self, method, url, body, headers):
- if method == 'GET':
- return (httplib.OK, self.fixtures.load('deploy_container.json'),
- {}, httplib.responses[httplib.OK])
- elif method == 'DELETE' or '?action=stop' in url:
- return (httplib.OK, self.fixtures.load('stop_container.json'), {},
- httplib.responses[httplib.OK])
- elif '?action=start' in url:
- return (httplib.OK, self.fixtures.load('start_container.json'), {},
- httplib.responses[httplib.OK])
- else:
- return (httplib.OK, self.fixtures.load('deploy_container.json'),
- {}, httplib.responses[httplib.OK])
-
-
if __name__ == '__main__':
sys.exit(unittest.main())