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/10/08 02:30:32 UTC

[01/27] libcloud git commit: flake and doc fixes

Repository: libcloud
Updated Branches:
  refs/heads/trunk a37a02a80 -> 1a8361482


flake and doc fixes


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/87c95010
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/87c95010
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/87c95010

Branch: refs/heads/trunk
Commit: 87c950102cee8b7738aad80082058c76af767533
Parents: 4f8a3e6
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Oct 7 21:52:08 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 docs/container/drivers/rancher.rst      | 7 -------
 libcloud/test/container/test_rancher.py | 6 +++---
 2 files changed, 3 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/87c95010/docs/container/drivers/rancher.rst
----------------------------------------------------------------------
diff --git a/docs/container/drivers/rancher.rst b/docs/container/drivers/rancher.rst
index 63cc8ea..c118397 100644
--- a/docs/container/drivers/rancher.rst
+++ b/docs/container/drivers/rancher.rst
@@ -21,13 +21,6 @@ Here are some notes around this driver:
 - ``launchConfig`` options for ``ex_deploy_service`` can all be defined at the
   top level then get slipstreamed appropriately.
 - Passing your own cert/key of any sort for SSL/TLS is not presently supported.
-- For SSL/TLS (https) support with newer versions of OpenSSL, the following
-  is necessary (in your own code):
-
-  .. code::
-    import ssl
-    import libcloud.security
-    libcloud.security.SSL_VERSION = ssl.PROTOCOL_TLSv1_2
 
 To enable API access, obtain an Environment API Key from your Rancher Server
 for the specific environment you want to control.

http://git-wip-us.apache.org/repos/asf/libcloud/blob/87c95010/libcloud/test/container/test_rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_rancher.py b/libcloud/test/container/test_rancher.py
index 743c2d3..f9ddc83 100644
--- a/libcloud/test/container/test_rancher.py
+++ b/libcloud/test/container/test_rancher.py
@@ -218,9 +218,9 @@ class RancherMockHttp(MockHttp):
 
     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]
-                    )
+            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])


[12/27] libcloud git commit: move _build_payload to bottom near other helper functions

Posted by an...@apache.org.
move _build_payload to bottom near other helper functions


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/6a1d03d6
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/6a1d03d6
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/6a1d03d6

Branch: refs/heads/trunk
Commit: 6a1d03d6bfffcf5b69c35f52f95add492aac00c0
Parents: 12cdf36
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Sep 29 11:53:55 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 466 ++++++++++++++---------------
 1 file changed, 233 insertions(+), 233 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/6a1d03d6/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 63c1aeb..1e8e18b 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -287,239 +287,6 @@ class RancherContainerDriver(ContainerDriver):
         )
         return result.status in VALID_RESPONSE_CODES
 
-    def _build_payload(self, image, start=True, name=None, image_type="docker",
-                       blkiodeviceoptions=None, build=None,
-                       capadd=None,
-                       capdrop=None, command=None,
-                       count=None, cpuset=None, cpushares=None,
-                       datavolumemounts=None, datavolumes=None,
-                       datavolumesfrom=None, description=None, devices=None,
-                       dns=None, dnssearch=None, domainname=None,
-                       entrypoint=None, environment=None, expose=None,
-                       extrahosts=None, healthcheck=None, hostname=None,
-                       instancelinks=None, labels=None, logconfig=None,
-                       lxcconf=None, memory=None, memoryswap=None,
-                       networkcontainerrid=None, networkids=None,
-                       networkmode=None, pidmode=None, ports=None,
-                       privileged=None, publishallports=None,
-                       readonly=None, registrycredentialid=None,
-                       requestedhostid=None, restartpolicy=None,
-                       securityopt=None,
-                       stdinopen=None, tty=None, user=None,
-                       volumedriver=None, workingdir=None):
-        """
-
-        :param image: The Image object to deploy.
-        :type image: :class:`libcloud.container.base.ContainerImage`
-
-        :param start: Whether to start the container on creation.
-        :type start: ``bool``
-
-        :param name: The desired name of the container.
-        :type name: ``str``
-
-        :param image_type: The image format of the desired image to deploy.
-        :type image_type: ``str``
-
-        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
-        :type blkiodeviceoptions: ``dict``
-
-        :param build: Build details for the container.
-        :type build: ``dict``
-
-        :param capadd: Linux Capabilities to enable for this container.
-        :type capadd: ``list``
-
-        :param capdrop: Linux capabilities to disable for this container.
-        :type capdrop: ``list``
-
-        :param command: The command to execute when this container is run.
-        :type command: ``list``
-
-        :param count: The number of containers of this nature to launch.
-        :type count: ``int``
-
-        :param cpuset: Memory nodes in which to allow execution.
-        :type cpuset: ``str``
-
-        :param cpushares: Relative weight cpu shares to allow.
-        :type cpushares: ``int``
-
-        :param datavolumemounts: Data volume mountes this container should have
-        :type datavolumemounts: ``dict``
-
-        :param datavolumes: Data volumes to associate with this container.
-        :type datavolumes: ``list``
-
-        :param datavolumesfrom: Data volumes to inherit.
-        :type datavolumesfrom: ``list``
-
-        :param description: Description for this container.
-        :type description: ``str``
-
-        :param devices: Devices inside the container without privliged mode.
-        :type devices: ``list``
-
-        :param dns: DNS servers the container should utilize.
-        :type dns: ``list``
-
-        :param dnssearch: DNS search domains the container should utilize.
-        :type dnssearch: ``list``
-
-        :param domainname: The domain name the container should have.
-        :type domainname: ``str``
-
-        :param entrypoint: The entrypoint the container should have.
-        :type entrypoint: ``list``
-
-        :param environment: Environment variables the container should have.
-        :type environment: ``dict``
-
-        :param expose: Ports which should be exposed in the container.
-        :type expose: ``list``
-
-        :param extrahosts: Extra hosts file entries this container should have.
-        :type extrahosts: ``list``
-
-        :param healthcheck: Health check parameters for this container.
-        :type healthcheck: ``dict``
-
-        :param hostname: The hostname this container should have.
-        :type hostname: ``str``
-
-        :param instancelinks: Instance links the container should have.
-        :type instancelinks: ``dict``
-
-        :param labels: Labels to associate with this container.
-        :type labels: ``dict``
-
-        :param logconfig: Log configuration for this container.
-        :type logconfig: ``dict``
-
-        :param lxcconf: lxcConf specific to this container.
-        :type lxcconf: ``dict``
-
-        :param memory: The memory limit for this container.
-        :type memory: ``int``
-
-        :param memoryswap: Total memory limit for this container.
-        :type memoryswap: ``int``
-
-        :param networkcontainerrid: A Network container Id for this container.
-        :type networkcontainerrid: ``dict``
-
-        :param networkids: NetworkIds this container should contain.
-        :type networkids: ``list``
-
-        :param networkmode: The networkMode to enable for this container.
-        :type networkmode: ``str``
-
-        :param pidmode: The pidMode for this container.
-        :type pidmode: ``str``
-
-        :param ports: The ports to publicize for this container.
-        :type ports: ``list``
-
-        :param privileged: Whether to enable privileged mode for this container
-        :type privileged: ``bool``
-
-        :param publishallports: Publish all ports in container.
-        :type publishallports: ``bool``
-
-        :param readonly: Whether this container should be readOnly.
-        :type readonly: ``bool``
-
-        :param registrycredentialid: Registry credentials to use.
-        :type registrycredentialid: ``dict``
-
-        :param requestedhostid: Id of the requested host to run this container.
-        :type requestedhostid: ``dict``
-
-        :param restartpolicy: The container restart policy.
-        :type restartpolicy: ``dict``
-
-        :param securityopt: Security options to provide for this container.
-        :type securityopt: ``list``
-
-        :param stdinopen: Whether to keep stdin open.
-        :type stdinopen: ``bool``
-
-        :param tty: Enable a tty for this container.
-        :type tty: ``bool``
-
-        :param user: User this container should be tied to.
-        :type user: ``str``
-
-        :param volumedriver: The volume driver to use for this container.
-        :type volumedriver: ``str``
-
-        :param workingdir: The workingDir this container should start in.
-        :type workingdir: ``str``
-
-        :return:
-        """
-
-        if command is not None:
-            command = shlex.split(str(command))
-
-        if image.version is not None:
-            imageuuid = image_type + ':' + image.path + ':' + image.version
-        else:
-            imageuuid = image_type + ':' + image.path
-
-        payload = {
-            "blkioDeviceOptions": blkiodeviceoptions,
-            "build": build,
-            "capAdd": capadd,
-            "capDrop": capdrop,
-            "command": command,
-            "count": count,
-            "cpuSet": cpuset,
-            "cpuShares": cpushares,
-            "dataVolumeMounts": datavolumemounts,
-            "dataVolumes": datavolumes,
-            "dataVolumesFrom": datavolumesfrom,
-            "description": description,
-            "devices": devices,
-            "dns": dns,
-            "dnsSearch": dnssearch,
-            "domainName": domainname,
-            "entryPoint": entrypoint,
-            "environment": environment,
-            "expose": expose,
-            "extraHosts": extrahosts,
-            "healthCheck": healthcheck,
-            "hostname": hostname,
-            "imageUuid": imageuuid,
-            "instanceLinks": instancelinks,
-            "labels": labels,
-            "logConfig": logconfig,
-            "lxcConf": lxcconf,
-            "memory": memory,
-            "memorySwap": memoryswap,
-            "name": name,
-            "networkContainerId": networkcontainerrid,
-            "networkIds": networkids,
-            "networkMode": networkmode,
-            "pidMode": pidmode,
-            "ports": ports,
-            "privileged": privileged,
-            "publishAllPorts": publishallports,
-            "readOnly": readonly,
-            "registryCredentialId": registrycredentialid,
-            "requestedHostId": requestedhostid,
-            "restartPolicy": restartpolicy,
-            "securityOpt": securityopt,
-            "startOnCreate": start,
-            "stdinOpen": stdinopen,
-            "tty": tty,
-            "user": user,
-            "volumeDriver": volumedriver,
-            "workingdir": workingdir
-        }
-
-        return payload
-
     def ex_list_services(self):
         """
         List all Rancher Services
@@ -1186,3 +953,236 @@ class RancherContainerDriver(ContainerDriver):
             state=state,
             driver=self.connection.driver,
             extra=extra)
+
+    def _build_payload(self, image, start=True, name=None, image_type="docker",
+                       blkiodeviceoptions=None, build=None,
+                       capadd=None,
+                       capdrop=None, command=None,
+                       count=None, cpuset=None, cpushares=None,
+                       datavolumemounts=None, datavolumes=None,
+                       datavolumesfrom=None, description=None, devices=None,
+                       dns=None, dnssearch=None, domainname=None,
+                       entrypoint=None, environment=None, expose=None,
+                       extrahosts=None, healthcheck=None, hostname=None,
+                       instancelinks=None, labels=None, logconfig=None,
+                       lxcconf=None, memory=None, memoryswap=None,
+                       networkcontainerrid=None, networkids=None,
+                       networkmode=None, pidmode=None, ports=None,
+                       privileged=None, publishallports=None,
+                       readonly=None, registrycredentialid=None,
+                       requestedhostid=None, restartpolicy=None,
+                       securityopt=None,
+                       stdinopen=None, tty=None, user=None,
+                       volumedriver=None, workingdir=None):
+        """
+
+        :param image: The Image object to deploy.
+        :type image: :class:`libcloud.container.base.ContainerImage`
+
+        :param start: Whether to start the container on creation.
+        :type start: ``bool``
+
+        :param name: The desired name of the container.
+        :type name: ``str``
+
+        :param image_type: The image format of the desired image to deploy.
+        :type image_type: ``str``
+
+        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
+        :type blkiodeviceoptions: ``dict``
+
+        :param build: Build details for the container.
+        :type build: ``dict``
+
+        :param capadd: Linux Capabilities to enable for this container.
+        :type capadd: ``list``
+
+        :param capdrop: Linux capabilities to disable for this container.
+        :type capdrop: ``list``
+
+        :param command: The command to execute when this container is run.
+        :type command: ``list``
+
+        :param count: The number of containers of this nature to launch.
+        :type count: ``int``
+
+        :param cpuset: Memory nodes in which to allow execution.
+        :type cpuset: ``str``
+
+        :param cpushares: Relative weight cpu shares to allow.
+        :type cpushares: ``int``
+
+        :param datavolumemounts: Data volume mountes this container should have
+        :type datavolumemounts: ``dict``
+
+        :param datavolumes: Data volumes to associate with this container.
+        :type datavolumes: ``list``
+
+        :param datavolumesfrom: Data volumes to inherit.
+        :type datavolumesfrom: ``list``
+
+        :param description: Description for this container.
+        :type description: ``str``
+
+        :param devices: Devices inside the container without privliged mode.
+        :type devices: ``list``
+
+        :param dns: DNS servers the container should utilize.
+        :type dns: ``list``
+
+        :param dnssearch: DNS search domains the container should utilize.
+        :type dnssearch: ``list``
+
+        :param domainname: The domain name the container should have.
+        :type domainname: ``str``
+
+        :param entrypoint: The entrypoint the container should have.
+        :type entrypoint: ``list``
+
+        :param environment: Environment variables the container should have.
+        :type environment: ``dict``
+
+        :param expose: Ports which should be exposed in the container.
+        :type expose: ``list``
+
+        :param extrahosts: Extra hosts file entries this container should have.
+        :type extrahosts: ``list``
+
+        :param healthcheck: Health check parameters for this container.
+        :type healthcheck: ``dict``
+
+        :param hostname: The hostname this container should have.
+        :type hostname: ``str``
+
+        :param instancelinks: Instance links the container should have.
+        :type instancelinks: ``dict``
+
+        :param labels: Labels to associate with this container.
+        :type labels: ``dict``
+
+        :param logconfig: Log configuration for this container.
+        :type logconfig: ``dict``
+
+        :param lxcconf: lxcConf specific to this container.
+        :type lxcconf: ``dict``
+
+        :param memory: The memory limit for this container.
+        :type memory: ``int``
+
+        :param memoryswap: Total memory limit for this container.
+        :type memoryswap: ``int``
+
+        :param networkcontainerrid: A Network container Id for this container.
+        :type networkcontainerrid: ``dict``
+
+        :param networkids: NetworkIds this container should contain.
+        :type networkids: ``list``
+
+        :param networkmode: The networkMode to enable for this container.
+        :type networkmode: ``str``
+
+        :param pidmode: The pidMode for this container.
+        :type pidmode: ``str``
+
+        :param ports: The ports to publicize for this container.
+        :type ports: ``list``
+
+        :param privileged: Whether to enable privileged mode for this container
+        :type privileged: ``bool``
+
+        :param publishallports: Publish all ports in container.
+        :type publishallports: ``bool``
+
+        :param readonly: Whether this container should be readOnly.
+        :type readonly: ``bool``
+
+        :param registrycredentialid: Registry credentials to use.
+        :type registrycredentialid: ``dict``
+
+        :param requestedhostid: Id of the requested host to run this container.
+        :type requestedhostid: ``dict``
+
+        :param restartpolicy: The container restart policy.
+        :type restartpolicy: ``dict``
+
+        :param securityopt: Security options to provide for this container.
+        :type securityopt: ``list``
+
+        :param stdinopen: Whether to keep stdin open.
+        :type stdinopen: ``bool``
+
+        :param tty: Enable a tty for this container.
+        :type tty: ``bool``
+
+        :param user: User this container should be tied to.
+        :type user: ``str``
+
+        :param volumedriver: The volume driver to use for this container.
+        :type volumedriver: ``str``
+
+        :param workingdir: The workingDir this container should start in.
+        :type workingdir: ``str``
+
+        :return:
+        """
+
+        if command is not None:
+            command = shlex.split(str(command))
+
+        if image.version is not None:
+            imageuuid = image_type + ':' + image.path + ':' + image.version
+        else:
+            imageuuid = image_type + ':' + image.path
+
+        payload = {
+            "blkioDeviceOptions": blkiodeviceoptions,
+            "build": build,
+            "capAdd": capadd,
+            "capDrop": capdrop,
+            "command": command,
+            "count": count,
+            "cpuSet": cpuset,
+            "cpuShares": cpushares,
+            "dataVolumeMounts": datavolumemounts,
+            "dataVolumes": datavolumes,
+            "dataVolumesFrom": datavolumesfrom,
+            "description": description,
+            "devices": devices,
+            "dns": dns,
+            "dnsSearch": dnssearch,
+            "domainName": domainname,
+            "entryPoint": entrypoint,
+            "environment": environment,
+            "expose": expose,
+            "extraHosts": extrahosts,
+            "healthCheck": healthcheck,
+            "hostname": hostname,
+            "imageUuid": imageuuid,
+            "instanceLinks": instancelinks,
+            "labels": labels,
+            "logConfig": logconfig,
+            "lxcConf": lxcconf,
+            "memory": memory,
+            "memorySwap": memoryswap,
+            "name": name,
+            "networkContainerId": networkcontainerrid,
+            "networkIds": networkids,
+            "networkMode": networkmode,
+            "pidMode": pidmode,
+            "ports": ports,
+            "privileged": privileged,
+            "publishAllPorts": publishallports,
+            "readOnly": readonly,
+            "registryCredentialId": registrycredentialid,
+            "requestedHostId": requestedhostid,
+            "restartPolicy": restartpolicy,
+            "securityOpt": securityopt,
+            "startOnCreate": start,
+            "stdinOpen": stdinopen,
+            "tty": tty,
+            "user": user,
+            "volumeDriver": volumedriver,
+            "workingdir": workingdir
+        }
+
+        return payload


[08/27] libcloud git commit: and container search ;)

Posted by an...@apache.org.
and container search ;)


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/ce9073d4
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/ce9073d4
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/ce9073d4

Branch: refs/heads/trunk
Commit: ce9073d43a0e7426f9e444e2b47a638aac61ccbf
Parents: a58452c
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Tue Oct 4 22:06:46 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/ce9073d4/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index c064317..ae4d7c1 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -579,6 +579,26 @@ class RancherContainerDriver(ContainerDriver):
         else:
             raise RancherException(result.status, 'failed to stop container')
 
+    def ex_search_containers(self, search_params):
+        """
+        Search for containers matching certain filters
+
+        i.e. ``{ "imageUuid": "docker:mysql", "state": "running"}``
+
+        :param search_params: A collection of search parameters to use.
+        :type search_params: ``dict``
+
+        :rtype: ``list``
+        """
+        search_list = []
+        for f, v in search_params.items():
+            search_list.append(f + '=' + v)
+        search_items = '&'.join(search_list)
+        result = self.connection.request("%s/containers?%s" % (
+            self.baseuri, search_items)).object
+
+        return result['data']
+
     def destroy_container(self, container):
         """
         Remove a container


[16/27] libcloud git commit: docs written

Posted by an...@apache.org.
docs written


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/062e3871
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/062e3871
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/062e3871

Branch: refs/heads/trunk
Commit: 062e38718c11b8f06aa23437828f0d114d06c878
Parents: 5cd5f9d
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Oct 6 18:19:36 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 docs/_static/images/provider_logos/rancher.png  | Bin 0 -> 9386 bytes
 docs/container/drivers/rancher.rst              |  79 +++++++++++++++++++
 .../container/rancher/deploy_container.py       |  13 +++
 .../container/rancher/deploy_service.py         |  17 ++++
 docs/examples/container/rancher/deploy_stack.py |  13 +++
 .../container/rancher/instantiate_driver.py     |   9 +++
 .../container/rancher/search_containers.py      |  12 +++
 7 files changed, 143 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/062e3871/docs/_static/images/provider_logos/rancher.png
----------------------------------------------------------------------
diff --git a/docs/_static/images/provider_logos/rancher.png b/docs/_static/images/provider_logos/rancher.png
new file mode 100644
index 0000000..82dde39
Binary files /dev/null and b/docs/_static/images/provider_logos/rancher.png differ

http://git-wip-us.apache.org/repos/asf/libcloud/blob/062e3871/docs/container/drivers/rancher.rst
----------------------------------------------------------------------
diff --git a/docs/container/drivers/rancher.rst b/docs/container/drivers/rancher.rst
new file mode 100644
index 0000000..63cc8ea
--- /dev/null
+++ b/docs/container/drivers/rancher.rst
@@ -0,0 +1,79 @@
+Rancher Container Service Documentation
+=======================================
+
+Rancher is a container orchestration platform.
+
+.. figure:: /_static/images/provider_logos/rancher.png
+    :align: center
+    :width: 300
+    :target: http://rancher.com/
+
+This driver supports the main top-level interactions for handling containers,
+services, and stacks in a Rancher Environment.
+
+Here are some notes around this driver:
+
+- Does not support user based API credentials, only Environment API
+  credentials (one env, no cluster support)
+- Does not support images other than docker formatted images. ``docker:``
+  prefix is forced!
+- Images follow a standardized format. See deploy_container docstring!
+- ``launchConfig`` options for ``ex_deploy_service`` can all be defined at the
+  top level then get slipstreamed appropriately.
+- Passing your own cert/key of any sort for SSL/TLS is not presently supported.
+- For SSL/TLS (https) support with newer versions of OpenSSL, the following
+  is necessary (in your own code):
+
+  .. code::
+    import ssl
+    import libcloud.security
+    libcloud.security.SSL_VERSION = ssl.PROTOCOL_TLSv1_2
+
+To enable API access, obtain an Environment API Key from your Rancher Server
+for the specific environment you want to control.
+
+Instantiating the driver
+------------------------
+
+.. literalinclude:: /examples/container/rancher/instantiate_driver.py
+   :language: python
+
+Deploying a container
+---------------------
+
+.. literalinclude:: /examples/container/rancher/deploy_container.py
+   :language: python
+
+Deploying a service
+-------------------
+
+.. literalinclude:: /examples/container/rancher/deploy_service.py
+   :language: python
+
+Deploying a stack
+-----------------
+
+.. literalinclude:: /examples/container/rancher/deploy_stack.py
+   :language: python
+
+Searching for a container
+-------------------------
+
+.. literalinclude:: /examples/container/rancher/search_containers.py
+   :language: python
+
+API Docs
+--------
+
+.. autoclass:: libcloud.container.drivers.rancher.RancherContainerDriver
+    :members:
+    :inherited-members:
+
+Contributors
+------------
+
+For the first version of this driver, Mario Loria of Arroyo Networks wrote most
+of the code. He received help from Anthony Shaw, a core libcloud contributor
+and Vincent Fiduccia, software architect at Rancher Labs.
+
+.. _`Rancher`: https://rancher.com/
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/062e3871/docs/examples/container/rancher/deploy_container.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/deploy_container.py b/docs/examples/container/rancher/deploy_container.py
new file mode 100644
index 0000000..51b64b2
--- /dev/null
+++ b/docs/examples/container/rancher/deploy_container.py
@@ -0,0 +1,13 @@
+from libcloud.container.types import Provider
+from libcloud.container.providers import get_driver
+
+driver = get_driver(Provider.RANCHER)
+
+connection = driver("MYRANCHERACCESSKEY", "MYRANCHERSECRETKEY",
+                    host="172.30.0.100", port=8080, secure=False)
+
+image = ContainerImage("hastebin", "hastebin", "rlister/hastebin", "latest",
+                       driver=None)
+
+new_container = connection.deploy_container(name="awesomecontainer",
+                                            image=image, networkMode="managed")

http://git-wip-us.apache.org/repos/asf/libcloud/blob/062e3871/docs/examples/container/rancher/deploy_service.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/deploy_service.py b/docs/examples/container/rancher/deploy_service.py
new file mode 100644
index 0000000..036aa1c
--- /dev/null
+++ b/docs/examples/container/rancher/deploy_service.py
@@ -0,0 +1,17 @@
+from libcloud.container.types import Provider
+from libcloud.container.providers import get_driver
+
+driver = get_driver(Provider.RANCHER)
+
+connection = driver("MYRANCHERACCESSKEY", "MYRANCHERSECRETKEY",
+                    host="17.23.66.4", port=443)
+
+image = ContainerImage("hastebin", "hastebin", "rlister/hastebin", "latest",
+                       driver=None)
+
+new_service = connection.ex_deploy_service(name="excitingservice", image=image,
+                                           environmentid="1e2",
+                                           environment={
+                                               "STORAGE_TYPE": "file"
+                                           })
+

http://git-wip-us.apache.org/repos/asf/libcloud/blob/062e3871/docs/examples/container/rancher/deploy_stack.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/deploy_stack.py b/docs/examples/container/rancher/deploy_stack.py
new file mode 100644
index 0000000..52d5122
--- /dev/null
+++ b/docs/examples/container/rancher/deploy_stack.py
@@ -0,0 +1,13 @@
+from libcloud.container.types import Provider
+from libcloud.container.providers import get_driver
+
+driver = get_driver(Provider.RANCHER)
+
+connection = driver("MYRANCHERACCESSKEY", "MYRANCHERSECRETKEY",
+                    host="172.30.0.100", port=8080, secure=False)
+
+new_stack = connection.ex_deploy_stack(name="GhostBlog",
+                                       description="Contains services for the"
+                                                   "ghost blog.")
+
+id_of_new_stack = new_stack['id']
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/062e3871/docs/examples/container/rancher/instantiate_driver.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/instantiate_driver.py b/docs/examples/container/rancher/instantiate_driver.py
new file mode 100644
index 0000000..8472599
--- /dev/null
+++ b/docs/examples/container/rancher/instantiate_driver.py
@@ -0,0 +1,9 @@
+from libcloud.container.types import Provider
+from libcloud.container.providers import get_driver
+
+driver = get_driver(Provider.RANCHER)
+
+connection = driver("MYRANCHERACCESSKEY", "MYRANCHERSECRETKEY",
+                    host="172.30.0.100", port=8080, secure=False)
+
+connection.list_containers()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/062e3871/docs/examples/container/rancher/search_containers.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/search_containers.py b/docs/examples/container/rancher/search_containers.py
new file mode 100644
index 0000000..8e7d632
--- /dev/null
+++ b/docs/examples/container/rancher/search_containers.py
@@ -0,0 +1,12 @@
+from libcloud.container.types import Provider
+from libcloud.container.providers import get_driver
+
+driver = get_driver(Provider.RANCHER)
+
+connection = driver("MYRANCHERACCESSKEY", "MYRANCHERSECRETKEY",
+                    host="172.30.22.1", port=8080, secure=False)
+
+search_results = connection.ex_search_containers(
+    search_params={ "imageUuid": "docker:mysql", "state": "running" })
+
+id_of_first_result = search_results[0]['id']
\ No newline at end of file


[20/27] libcloud git commit: dict instead of comprehension

Posted by an...@apache.org.
dict instead of comprehension


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/c3ffcf10
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/c3ffcf10
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/c3ffcf10

Branch: refs/heads/trunk
Commit: c3ffcf1067909162b9de325ee720d374c9d70f03
Parents: 4356c15
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Oct 6 21:48:48 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/c3ffcf10/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 66f8040..a7abf2d 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -201,7 +201,8 @@ class RancherContainerDriver(ContainerDriver):
             "rancherCompose": rancher_compose,
             "startOnCreate": start
         }
-        data = json.dumps({k: v for k, v in payload.items() if v is not None})
+        data = json.dumps(dict((k,v) for (k,v) in payload.items()
+                               if v is not None))
         result = self.connection.request('%s/environments' %
                                          self.baseuri, data=data,
                                          method='POST').object
@@ -391,8 +392,8 @@ class RancherContainerDriver(ContainerDriver):
             "vip": vip
         }
 
-        data = json.dumps({k: v for k, v in service_payload.items()
-                           if v is not None})
+        data = json.dumps(dict((k,v) for (k,v) in service_payload.items()
+                               if v is not None))
         result = self.connection.request('%s/services' % self.baseuri,
                                          data=data, method='POST').object
 


[19/27] libcloud git commit: move protocol check before super

Posted by an...@apache.org.
move protocol check before super


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/4356c156
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/4356c156
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/4356c156

Branch: refs/heads/trunk
Commit: 4356c156ff4a46f0d604435317416ffdb363c5f4
Parents: 062e387
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Oct 6 21:17:08 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4356c156/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 2a6b8d5..66f8040 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -128,11 +128,13 @@ class RancherContainerDriver(ContainerDriver):
 
         :return: ``None``
         """
+
+        if host.startswith('http://'):
+            secure = False
+
         super(RancherContainerDriver, self).__init__(key=key, secret=secret,
                                                      secure=secure, host=host,
                                                      port=port)
-        if host.startswith('http://'):
-            secure = False
 
         # strip the prefix
         prefixes = ['http://', 'https://']


[11/27] libcloud git commit: environment -> stack

Posted by an...@apache.org.
environment -> stack


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/12cdf36c
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/12cdf36c
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/12cdf36c

Branch: refs/heads/trunk
Commit: 12cdf36c6df12d73acc7ff34acafc695fec4df82
Parents: 723a179
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Sep 29 11:51:48 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 46 +++++++++++++++---------------
 1 file changed, 23 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/12cdf36c/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 1d0618e..63c1aeb 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -143,9 +143,9 @@ class RancherContainerDriver(ContainerDriver):
         # self.baseuri = "/v%s/projects/%s" % (self.version, project_id)
         self.baseuri = "/v%s" % self.version
 
-    def ex_list_environments(self):
+    def ex_list_stacks(self):
         """
-        List all Rancher Environments (called "Stacks" in the UI)
+        List all Rancher Stacks
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/
 
@@ -156,32 +156,32 @@ class RancherContainerDriver(ContainerDriver):
             "%s/environments" % self.baseuri).object
         return result['data']
 
-    def ex_deploy_environment(self, name, description=None, dockercompose=None,
+    def ex_deploy_stack(self, name, description=None, dockercompose=None,
                               environment=None, externalid=None, outputs=None,
                               previousenvironment=None,
                               previousexternalid=None, ranchercompose=None,
                               start=True):
         """
-        Deploy a new environment ("Stack" in the UI)
+        Deploy a new stack.
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#create
 
-        :param name: The desired name of the environment.
+        :param name: The desired name of the stack.
         :type name: ``str``
 
-        :param description: A desired description for the environment.
+        :param description: A desired description for the stack.
         :type description: ``str``
 
         :param dockercompose: The Docker Compose configuration to use.
         :type dockercompose: ``str``
 
-        :param environment: Environment K/V specific to this environment.
+        :param environment: Environment K/V specific to this stack.
         :type environment: ``dict``
 
-        :param externalid: The externalId of the environment.
+        :param externalid: The externalId of the stack.
         :type externalid: ``str``
 
-        :param outputs: Any outputs the environment should contain.
+        :param outputs: Any outputs the stack should contain.
         :type outputs: ``dict``
 
         :param previousenvironment: The previousEnvironment for this env.
@@ -193,10 +193,10 @@ class RancherContainerDriver(ContainerDriver):
         :param ranchercompose: The Rancher Compose configuration for this env.
         :type ranchercompose: ``str``
 
-        :param start: Whether to start this environment on creation.
+        :param start: Whether to start this stack on creation.
         :type start: ``bool``
 
-        :return: The newly created environment.
+        :return: The newly created stack.
         :rtype: ``dict``
         """
 
@@ -219,11 +219,11 @@ class RancherContainerDriver(ContainerDriver):
 
         return result
 
-    def ex_get_environment(self, env_id):
+    def ex_get_stack(self, env_id):
         """
-        Get an environment by ID
+        Get a stack by ID
 
-        :param env_id: The environment to be obtained.
+        :param env_id: The stack to be obtained.
         :type env_id: ``str``
 
         :rtype: ``dict``
@@ -233,13 +233,13 @@ class RancherContainerDriver(ContainerDriver):
 
         return result
 
-    def ex_destroy_environment(self, env_id):
+    def ex_destroy_stack(self, env_id):
         """
-        Destroy an environment by ID
+        Destroy a stack by ID
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#delete
 
-        :param env_id: The environment to be destroyed.
+        :param env_id: The stack to be destroyed.
         :type env_id: ``str``
 
         :return: True if destroy was successful, False otherwise.
@@ -250,13 +250,13 @@ class RancherContainerDriver(ContainerDriver):
                                          method='DELETE')
         return result.status in VALID_RESPONSE_CODES
 
-    def ex_activate_environment(self, env_id):
+    def ex_activate_stack(self, env_id):
         """
-        Activate Services for a environment.
+        Activate Services for a stack.
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#activateservices
 
-        :param env_id: The environment to activate services for.
+        :param env_id: The stack to activate services for.
         :type env_id: ``str``
 
         :return: True if activate was successful, False otherwise.
@@ -268,13 +268,13 @@ class RancherContainerDriver(ContainerDriver):
         )
         return result.status in VALID_RESPONSE_CODES
 
-    def ex_deactivate_environment(self, env_id):
+    def ex_deactivate_stack(self, env_id):
         """
-        Deactivate Services for a environment.
+        Deactivate Services for a stack.
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#deactivateservices
 
-        :param env_id: The environment to deactivate services for.
+        :param env_id: The stack to deactivate services for.
         :type env_id: ``str``
 
         :return: True if deactivate was successful, False otherwise.


[21/27] libcloud git commit: mod return in parse_error

Posted by an...@apache.org.
mod return in parse_error


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/613c6690
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/613c6690
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/613c6690

Branch: refs/heads/trunk
Commit: 613c6690bb7cb622f8746b22c90303837198a56a
Parents: c3ffcf1
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Oct 6 21:54:04 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/613c6690/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index a7abf2d..6e187d9 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -41,7 +41,7 @@ class RancherResponse(JsonResponse):
     def parse_error(self):
         if self.status == 401:
             raise InvalidCredsError('Invalid credentials')
-        return self.body
+        return super().parse_error()
 
     def success(self):
         return self.status in VALID_RESPONSE_CODES


[09/27] libcloud git commit: extra contains entire json resp

Posted by an...@apache.org.
extra contains entire json resp


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/ce913106
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/ce913106
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/ce913106

Branch: refs/heads/trunk
Commit: ce9131069f9dae62d8e7cba24ac8c08b6869d6fe
Parents: d6590e9
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Sep 29 11:12:54 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 28 ++--------------------------
 1 file changed, 2 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/ce913106/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 261f9f8..e0395e1 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -1175,32 +1175,8 @@ class RancherContainerDriver(ContainerDriver):
         else:
             state = ContainerState.UNKNOWN
 
-        # Includes the most used items atm. Eventually, everything ;)
-        extra = {
-            "state": rancher_state,
-            "command": data['command'],
-            "created": data['created'],
-            "dataVolumes": data['dataVolumes'],
-            "dns": data['dns'],
-            "dnsSearch": data['dnsSearch'],
-            "domainName": data['domainName'],
-            "entryPoint": data['entryPoint'],
-            "environment": data['environment'],
-            "expose": data['expose'],
-            "healthState": data['healthState'],
-            "hostId": data['hostId'],
-            "hostname": data['hostname'],
-            "labels": data['labels'],
-            "networkMode": data['networkMode'],
-            "ports": data['ports'],
-            "primaryIpAddress": data['primaryIpAddress'],
-            "privileged": data['privileged'],
-            "restartPolicy": data['restartPolicy'],
-            "stdinOpen": data['stdinOpen'],
-            "tty": data['tty'],
-            "uuid": data['uuid'],
-            "workingDir": data['workingDir']
-        }
+        # Everything contained in the json response is dumped in extra
+        extra = data
 
         return Container(
             id=data['id'],


[07/27] libcloud git commit: docstrings, flake8, error handling

Posted by an...@apache.org.
docstrings, flake8, error handling


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d96fc83d
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d96fc83d
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d96fc83d

Branch: refs/heads/trunk
Commit: d96fc83dbfa3b39916b1575a953a31f6f9bf8bea
Parents: 8495ea7
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Wed Sep 28 21:57:39 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 871 +++++++++++++++++++++++------
 1 file changed, 707 insertions(+), 164 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d96fc83d/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 5229442..62a88b5 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -1,7 +1,5 @@
 import base64
-import datetime
 import shlex
-import re
 
 try:
     import simplejson as json
@@ -83,13 +81,13 @@ class RancherContainerDriver(ContainerDriver):
     name = 'Rancher'
     website = 'http://rancher.com'
     connectionCls = RancherConnection
-    # Holding off on this for now. Only Environment API interaction enabled.
+    # 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=False, host='localhost',
-                 port=80, key_file=None, cert_file=None):
+    def __init__(self, key, secret, secure=False, host='localhost', port=80):
         """
         :param    key: API key or username to used (required)
         :type     key: ``str``
@@ -107,19 +105,12 @@ class RancherContainerDriver(ContainerDriver):
         :param    port: Override port used for connections.
         :type     port: ``int``
 
-        :param    key_file: Path to private key for TLS connection (optional)
-        :type     key_file: ``str``
-
-        :param    cert_file: Path to public key for TLS connection (optional)
-        :type     cert_file: ``str``
 
         :return: ``None``
         """
         super(RancherContainerDriver, self).__init__(key=key, secret=secret,
                                                      secure=secure, host=host,
-                                                     port=port,
-                                                     key_file=key_file,
-                                                     cert_file=cert_file)
+                                                     port=port)
         if host.startswith('https://'):
             secure = True
 
@@ -128,26 +119,10 @@ class RancherContainerDriver(ContainerDriver):
         for prefix in prefixes:
             if host.startswith(prefix):
                 host = host.strip(prefix)
-        """
-        if key_file or cert_file:
-            # docker tls authentication-
-            # https://docs.docker.com/articles/https/
-            # We pass two files, a key_file with the
-            # private key and cert_file with the certificate
-            # libcloud will handle them through LibcloudHTTPSConnection
-            if not (key_file and cert_file):
-                raise Exception(
-                    'Needs both private key file and '
-                    'certificate file for tls authentication')
-            self.connection.key_file = key_file
-            self.connection.cert_file = cert_file
-            self.connection.secure = True
-        else:
-            self.connection.secure = secure
-        """
 
         self.connection.host = host
         self.connection.port = port
+        self.connection.secure = secure
 
         # We only support environment api keys, meaning none of this:
         # self.baseuri = "/v%s/projects/%s" % (self.version, project_id)
@@ -155,21 +130,60 @@ class RancherContainerDriver(ContainerDriver):
 
     def ex_list_environments(self):
         """
-        List the deployed container images
-        :param image: Filter to containers with a certain image
-        :type  image: :class:`libcloud.container.base.ContainerImage`
-        :param all: Show all container (including stopped ones)
-        :type  all: ``bool``
-        :rtype: ``list`` of :class:`libcloud.container.base.Container`
+        List all Rancher Environments (called "Stacks" in the UI)
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/
+
+        :rtype: ``list`` of ``dict``
         """
 
-        result = self.connection.request("%s/environments" % self.baseuri).object
+        result = self.connection.request(
+            "%s/environments" % self.baseuri).object
         return result['data']
 
     def ex_deploy_environment(self, name, description=None, dockercompose=None,
                               environment=None, externalid=None, outputs=None,
-                              previousenvironment=None, previousexternalid=None,
-                              ranchercompose=None, start=True):
+                              previousenvironment=None,
+                              previousexternalid=None, ranchercompose=None,
+                              start=True):
+        """
+        Deploy a new environment ("Stack" in the UI)
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#create
+
+        :param name: The desired name of the environment.
+        :type name: ``str``
+
+        :param description: A desired description for the environment.
+        :type description: ``str``
+
+        :param dockercompose: The Docker Compose configuration to use.
+        :type dockercompose: ``str``
+
+        :param environment: Environment K/V specific to this environment.
+        :type environment: ``dict``
+
+        :param externalid: The externalId of the environment.
+        :type externalid: ``str``
+
+        :param outputs: Any outputs the environment should contain.
+        :type outputs: ``dict``
+
+        :param previousenvironment: The previousEnvironment for this env.
+        :type previousenvironment: ``dict``
+
+        :param previousexternalid: The previousExternalId for this env.
+        :type previousexternalid: ``str``
+
+        :param ranchercompose: The Rancher Compose configuration for this env.
+        :type ranchercompose: ``str``
+
+        :param start: Whether to start this environment on creation.
+        :type start: ``bool``
+
+        :return: The newly created environment.
+        :rtype: ``dict``
+        """
 
         payload = {
             "description": description,
@@ -192,9 +206,12 @@ class RancherContainerDriver(ContainerDriver):
 
     def ex_get_environment(self, env_id):
         """
-        Get a service by ID
+        Get an environment by ID
+
         :param env_id: The environment to be obtained.
-        :return: The API dict object returned for the new service.
+        :type env_id: ``str``
+
+        :rtype: ``dict``
         """
         result = self.connection.request("%s/environments/%s" %
                                          (self.baseuri, env_id)).object
@@ -202,57 +219,230 @@ class RancherContainerDriver(ContainerDriver):
         return result
 
     def ex_destroy_environment(self, env_id):
+        """
+        Destroy an environment by ID
 
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#delete
+
+        :param env_id: The environment to be destroyed.
+        :type env_id: ``str``
+
+        :return: True if destroy was successful, False otherwise.
+        :rtype: ``bool``
+        """
         result = self.connection.request('%s/environments/%s' % (
-                                         self.baseuri, env_id), method='DELETE')
-        if result.status in VALID_RESPONSE_CODES:
-            return result.status in VALID_RESPONSE_CODES
-        else:
-            raise RancherException(result.status,
-                                   'failed to destroy environment')
+                                         self.baseuri, env_id),
+                                         method='DELETE')
+        return result.status in VALID_RESPONSE_CODES
 
     def ex_activate_environment(self, env_id):
+        """
+        Activate Services for a environment.
 
-        result = self.connection.request('%s/environments/%s?action=activateservices' %
-                                         (self.baseuri, env_id),
-                                         method='POST')
-        if result.status in VALID_RESPONSE_CODES:
-            return result.status in VALID_RESPONSE_CODES
-        else:
-            raise RancherException(result.status,
-                                   'failed to activate environment')
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#activateservices
+
+        :param env_id: The environment to activate services for.
+        :type env_id: ``str``
+
+        :return: True if activate was successful, False otherwise.
+        :rtype: ``bool``
+        """
+        result = self.connection.request(
+            '%s/environments/%s?action=activateservices' % (
+                self.baseuri, env_id), method='POST'
+        )
+        return result.status in VALID_RESPONSE_CODES
 
     def ex_deactivate_environment(self, env_id):
+        """
+        Deactivate Services for a environment.
 
-        result = self.connection.request('%s/environments/%s?action=deactivateservices' %
-                                         (self.baseuri, env_id),
-                                         method='POST')
-        if result.status in VALID_RESPONSE_CODES:
-            return result.status in VALID_RESPONSE_CODES
-        else:
-            raise RancherException(result.status,
-                                   'failed to deactivate environment')
-
-    def build_payload(self, image, start=True, name=None, image_type="docker",
-                      blkiodeviceoptions=None, build=None,
-                      capadd=None,
-                      capdrop=None, command=None,
-                      count=None, cpuset=None, cpushares=None,
-                      datavolumemounts=None, datavolumes=None,
-                      datavolumesfrom=None, description=None, devices=None,
-                      dns=None, dnssearch=None, domainname=None,
-                      entrypoint=None, environment=None, expose=None,
-                      extrahosts=None, healthcheck=None, hostname=None,
-                      instancelinks=None, labels=None, logconfig=None,
-                      lxcconf=None, memory=None, memoryswap=None,
-                      networkcontainerrid=None, networkids=None,
-                      networkmode=None, pidmode=None, ports=None,
-                      privileged=None, publishallports=None,
-                      readonly=None, registrycredentialid=None,
-                      requestedhostid=None, restartpolicy=None,
-                      securityopt=None,
-                      stdinopen=None, tty=None, user=None,
-                      volumedriver=None, workingdir=None):
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#deactivateservices
+
+        :param env_id: The environment to deactivate services for.
+        :type env_id: ``str``
+
+        :return: True if deactivate was successful, False otherwise.
+        :rtype: ``bool``
+        """
+
+        result = self.connection.request(
+            '%s/environments/%s?action=deactivateservices' % (
+                self.baseuri, env_id), method='POST'
+        )
+        return result.status in VALID_RESPONSE_CODES
+
+    def _build_payload(self, image, start=True, name=None, image_type="docker",
+                       blkiodeviceoptions=None, build=None,
+                       capadd=None,
+                       capdrop=None, command=None,
+                       count=None, cpuset=None, cpushares=None,
+                       datavolumemounts=None, datavolumes=None,
+                       datavolumesfrom=None, description=None, devices=None,
+                       dns=None, dnssearch=None, domainname=None,
+                       entrypoint=None, environment=None, expose=None,
+                       extrahosts=None, healthcheck=None, hostname=None,
+                       instancelinks=None, labels=None, logconfig=None,
+                       lxcconf=None, memory=None, memoryswap=None,
+                       networkcontainerrid=None, networkids=None,
+                       networkmode=None, pidmode=None, ports=None,
+                       privileged=None, publishallports=None,
+                       readonly=None, registrycredentialid=None,
+                       requestedhostid=None, restartpolicy=None,
+                       securityopt=None,
+                       stdinopen=None, tty=None, user=None,
+                       volumedriver=None, workingdir=None):
+        """
+
+        :param image: The Image object to deploy.
+        :type image: :class:`libcloud.container.base.ContainerImage`
+
+        :param start: Whether to start the container on creation.
+        :type start: ``bool``
+
+        :param name: The desired name of the container.
+        :type name: ``str``
+
+        :param image_type: The image format of the desired image to deploy.
+        :type image_type: ``str``
+
+        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
+        :type blkiodeviceoptions: ``dict``
+
+        :param build: Build details for the container.
+        :type build: ``dict``
+
+        :param capadd: Linux Capabilities to enable for this container.
+        :type capadd: ``list``
+
+        :param capdrop: Linux capabilities to disable for this container.
+        :type capdrop: ``list``
+
+        :param command: The command to execute when this container is run.
+        :type command: ``list``
+
+        :param count: The number of containers of this nature to launch.
+        :type count: ``int``
+
+        :param cpuset: Memory nodes in which to allow execution.
+        :type cpuset: ``str``
+
+        :param cpushares: Relative weight cpu shares to allow.
+        :type cpushares: ``int``
+
+        :param datavolumemounts: Data volume mountes this container should have
+        :type datavolumemounts: ``dict``
+
+        :param datavolumes: Data volumes to associate with this container.
+        :type datavolumes: ``list``
+
+        :param datavolumesfrom: Data volumes to inherit.
+        :type datavolumesfrom: ``list``
+
+        :param description: Description for this container.
+        :type description: ``str``
+
+        :param devices: Devices inside the container without privliged mode.
+        :type devices: ``list``
+
+        :param dns: DNS servers the container should utilize.
+        :type dns: ``list``
+
+        :param dnssearch: DNS search domains the container should utilize.
+        :type dnssearch: ``list``
+
+        :param domainname: The domain name the container should have.
+        :type domainname: ``str``
+
+        :param entrypoint: The entrypoint the container should have.
+        :type entrypoint: ``list``
+
+        :param environment: Environment variables the container should have.
+        :type environment: ``dict``
+
+        :param expose: Ports which should be exposed in the container.
+        :type expose: ``list``
+
+        :param extrahosts: Extra hosts file entries this container should have.
+        :type extrahosts: ``list``
+
+        :param healthcheck: Health check parameters for this container.
+        :type healthcheck: ``dict``
+
+        :param hostname: The hostname this container should have.
+        :type hostname: ``str``
+
+        :param instancelinks: Instance links the container should have.
+        :type instancelinks: ``dict``
+
+        :param labels: Labels to associate with this container.
+        :type labels: ``dict``
+
+        :param logconfig: Log configuration for this container.
+        :type logconfig: ``dict``
+
+        :param lxcconf: lxcConf specific to this container.
+        :type lxcconf: ``dict``
+
+        :param memory: The memory limit for this container.
+        :type memory: ``int``
+
+        :param memoryswap: Total memory limit for this container.
+        :type memoryswap: ``int``
+
+        :param networkcontainerrid: A Network container Id for this container.
+        :type networkcontainerrid: ``dict``
+
+        :param networkids: NetworkIds this container should contain.
+        :type networkids: ``list``
+
+        :param networkmode: The networkMode to enable for this container.
+        :type networkmode: ``str``
+
+        :param pidmode: The pidMode for this container.
+        :type pidmode: ``str``
+
+        :param ports: The ports to publicize for this container.
+        :type ports: ``list``
+
+        :param privileged: Whether to enable privileged mode for this container
+        :type privileged: ``bool``
+
+        :param publishallports: Publish all ports in container.
+        :type publishallports: ``bool``
+
+        :param readonly: Whether this container should be readOnly.
+        :type readonly: ``bool``
+
+        :param registrycredentialid: Registry credentials to use.
+        :type registrycredentialid: ``dict``
+
+        :param requestedhostid: Id of the requested host to run this container.
+        :type requestedhostid: ``dict``
+
+        :param restartpolicy: The container restart policy.
+        :type restartpolicy: ``dict``
+
+        :param securityopt: Security options to provide for this container.
+        :type securityopt: ``list``
+
+        :param stdinopen: Whether to keep stdin open.
+        :type stdinopen: ``bool``
+
+        :param tty: Enable a tty for this container.
+        :type tty: ``bool``
+
+        :param user: User this container should be tied to.
+        :type user: ``str``
+
+        :param volumedriver: The volume driver to use for this container.
+        :type volumedriver: ``str``
+
+        :param workingdir: The workingDir this container should start in.
+        :type workingdir: ``str``
+
+        :return:
+        """
 
         if command is not None:
             command = shlex.split(str(command))
@@ -317,35 +507,237 @@ class RancherContainerDriver(ContainerDriver):
 
     def ex_list_services(self):
         """
-        List the deployed container images
-        :param image: Filter to containers with a certain image
-        :type  image: :class:`libcloud.container.base.ContainerImage`
-        :param all: Show all container (including stopped ones)
-        :type  all: ``bool``
-        :rtype: ``list`` of :class:`libcloud.container.base.Container`
+        List all Rancher Services
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/
+
+        :rtype: ``list`` of ``dict``
         """
 
         result = self.connection.request("%s/services" % self.baseuri).object
         return result['data']
 
-    def ex_deploy_service(self, name, image, environmentid, start=True,
-                          assignserviceipaddress=None, service_description=None,
-                          externalid=None, metadata=None, retainip=None,
-                          scale=None, scalepolicy=None,
-                          secondarylaunchconfigs=None, selectorcontainer=None,
-                          selectorlink=None,
+    def ex_deploy_service(self, name, image, environmentid,
+                          start=True, assignserviceipaddress=None,
+                          service_description=None, externalid=None,
+                          metadata=None, retainip=None, scale=None,
+                          scalepolicy=None, secondarylaunchconfigs=None,
+                          selectorcontainer=None, selectorlink=None,
                           vip=None, datavolumesfromlaunchconfigs=None,
                           disks=None, kind=None, memorymb=None,
                           networklaunchconfig=None, requsetedipaddress=None,
                           userdata=None, vcpu=None, **kwargs):
         """
         Deploy a Rancher Service under a stack.
-        :param name: Name of the service.
-        :param image: ContainerImage object of image to utilize.
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#create
+
+        :param name: The desired name of the service.
+        :type name: ``str``
+
+        :param image: The Image object to deploy.
+        :type image: :class:`libcloud.container.base.ContainerImage`
+
         :param environmentid: The environment/stack ID this service is tied to.
-        :param kwargs: The Launchconfig provided as top-level options,
-        similar to deploy_container.
-        :return: The API object returned on proper service creation.
+        :type environmentid: ``str``
+
+        :param start: Whether to start the service/container on creation.
+        :type start: ``bool``
+
+        :param assignserviceipaddress: The IP address to assign the service.
+        :type assignserviceipaddress: ``bool``
+
+        :param service_description: The service description.
+        :type service_description: ``str``
+
+        :param externalid: The externalId for this service.
+        :type externalid: ``str``
+
+        :param metadata: K/V Metadata for this service.
+        :type metadata: ``dict``
+
+        :param retainip: Whether this service should retain its IP.
+        :type retainip: ``bool``
+
+        :param scale: The scale of containers in this service.
+        :type scale: ``int``
+
+        :param scalepolicy: The scaling policy for this service.
+        :type scalepolicy: ``dict``
+
+        :param secondarylaunchconfigs: Secondary container launch configs.
+        :type secondarylaunchconfigs: ``list``
+
+        :param selectorcontainer: The selectorContainer for this service.
+        :type selectorcontainer: ``str``
+
+        :param selectorlink: The selectorLink for this service.
+        :type selectorlink: ``type``
+
+        :param vip: The VIP to assign to this service.
+        :type vip: ``str``
+
+        :param datavolumesfromlaunchconfigs: The dataVolumesFromLaunchConfigs.
+        :type datavolumesfromlaunchconfigs: ``list``
+
+        :param disks: The disks to associate with this container/service.
+        :type disks: ``list``
+
+        :param kind: The kind of object to deploy.
+        :type kind: ``str``
+
+        :param memorymb: The memoryMb to allow this container/service.
+        :type memorymb: ``int``
+
+        :param networklaunchconfig: The networkLaunchConfig for this container.
+        :type networklaunchconfig: ``str``
+
+        :param requsetedipaddress: The requested IP address for this container.
+        :type requsetedipaddress: ``str``
+
+        :param userdata: User data to associate with this container.
+        :type userdata: ``str``
+
+        :param vcpu: Virtual host cpu's to assign to allow this container.
+        :type vcpu: ``int``
+
+        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
+        :type blkiodeviceoptions: ``dict``
+
+        :param build: Build details for the container.
+        :type build: ``dict``
+
+        :param capadd: Linux Capabilities to enable for this container.
+        :type capadd: ``list``
+
+        :param capdrop: Linux capabilities to disable for this container.
+        :type capdrop: ``list``
+
+        :param command: The command to execute when this container is run.
+        :type command: ``list``
+
+        :param count: The number of containers of this nature to launch.
+        :type count: ``int``
+
+        :param cpuset: Memory nodes in which to allow execution.
+        :type cpuset: ``str``
+
+        :param cpushares: Relative weight cpu shares to allow.
+        :type cpushares: ``int``
+
+        :param datavolumemounts: Data volume mountes this container should have
+        :type datavolumemounts: ``dict``
+
+        :param datavolumes: Data volumes to associate with this container.
+        :type datavolumes: ``list``
+
+        :param datavolumesfrom: Data volumes to inherit.
+        :type datavolumesfrom: ``list``
+
+        :param description: Description for this container.
+        :type description: ``str``
+
+        :param devices: Devices inside the container without privliged mode.
+        :type devices: ``list``
+
+        :param dns: DNS servers the container should utilize.
+        :type dns: ``list``
+
+        :param dnssearch: DNS search domains the container should utilize.
+        :type dnssearch: ``list``
+
+        :param domainname: The domain name the container should have.
+        :type domainname: ``str``
+
+        :param entrypoint: The entrypoint the container should have.
+        :type entrypoint: ``list``
+
+        :param environment: Environment variables the container should have.
+        :type environment: ``dict``
+
+        :param expose: Ports which should be exposed in the container.
+        :type expose: ``list``
+
+        :param extrahosts: Extra hosts file entries this container should have.
+        :type extrahosts: ``list``
+
+        :param healthcheck: Health check parameters for this container.
+        :type healthcheck: ``dict``
+
+        :param hostname: The hostname this container should have.
+        :type hostname: ``str``
+
+        :param instancelinks: Instance links the container should have.
+        :type instancelinks: ``dict``
+
+        :param labels: Labels to associate with this container.
+        :type labels: ``dict``
+
+        :param logconfig: Log configuration for this container.
+        :type logconfig: ``dict``
+
+        :param lxcconf: lxcConf specific to this container.
+        :type lxcconf: ``dict``
+
+        :param memory: The memory limit for this container.
+        :type memory: ``int``
+
+        :param memoryswap: Total memory limit for this container.
+        :type memoryswap: ``int``
+
+        :param networkcontainerrid: A Network container Id for this container.
+        :type networkcontainerrid: ``dict``
+
+        :param networkids: NetworkIds this container should contain.
+        :type networkids: ``list``
+
+        :param networkmode: The networkMode to enable for this container.
+        :type networkmode: ``str``
+
+        :param pidmode: The pidMode for this container.
+        :type pidmode: ``str``
+
+        :param ports: The ports to publicize for this container.
+        :type ports: ``list``
+
+        :param privileged: Whether to enable privileged mode for this container
+        :type privileged: ``bool``
+
+        :param publishallports: Publish all ports in container.
+        :type publishallports: ``bool``
+
+        :param readonly: Whether this container should be readOnly.
+        :type readonly: ``bool``
+
+        :param registrycredentialid: Registry credentials to use.
+        :type registrycredentialid: ``dict``
+
+        :param requestedhostid: Id of the requested host to run this container.
+        :type requestedhostid: ``dict``
+
+        :param restartpolicy: The container restart policy.
+        :type restartpolicy: ``dict``
+
+        :param securityopt: Security options to provide for this container.
+        :type securityopt: ``list``
+
+        :param stdinopen: Whether to keep stdin open.
+        :type stdinopen: ``bool``
+
+        :param tty: Enable a tty for this container.
+        :type tty: ``bool``
+
+        :param user: User this container should be tied to.
+        :type user: ``str``
+
+        :param volumedriver: The volume driver to use for this container.
+        :type volumedriver: ``str``
+
+        :param workingdir: The workingDir this container should start in.
+        :type workingdir: ``str``
+
+        :return: The newly created service.
+        :rtype: ``dict``
         """
 
         service_specific_container_config = {
@@ -361,7 +753,7 @@ class RancherContainerDriver(ContainerDriver):
 
         # Build the de-facto container payload
         # Note that we don't need to remove "name" since its None by default.
-        launchconfig = self.build_payload(image, start, **kwargs)
+        launchconfig = self._build_payload(image, start, **kwargs)
         # Add in extra service configuration
         launchconfig.update(service_specific_container_config)
         launchconfig = json.dumps({k: v for k, v in launchconfig.items()
@@ -394,8 +786,11 @@ class RancherContainerDriver(ContainerDriver):
     def ex_get_service(self, service_id):
         """
         Get a service by ID
-        :param service_id: The service to be obtained.
-        :return: The API dict object returned for the new service.
+
+        :param service_id: The service_id to be obtained.
+        :type service_id: ``str``
+
+        :rtype: ``dict``
         """
         result = self.connection.request("%s/services/%s" %
                                          (self.baseuri, service_id)).object
@@ -404,48 +799,60 @@ class RancherContainerDriver(ContainerDriver):
 
     def ex_destroy_service(self, service_id):
         """
-        Delete a service.
-        :param service_id: The service to be destroyed
-        :return: True if the destroy was successful, False otherwise.
+        Destroy a service by ID
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#delete
+
+        :param service_id: The service to be destroyed.
+        :type service_id: ``str``
+
+        :return: True if destroy was successful, False otherwise.
         :rtype: ``bool``
         """
         result = self.connection.request('%s/services/%s' % (self.baseuri,
                                          service_id), method='DELETE')
-        if result.status in VALID_RESPONSE_CODES:
-            return result.status in VALID_RESPONSE_CODES
-        else:
-            raise RancherException(result.status,
-                                   'failed to destroy service')
+        return result.status in VALID_RESPONSE_CODES
 
     def ex_activate_service(self, service_id):
+        """
+        Activate a service.
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#activate
 
+        :param service_id: The service to activate services for.
+        :type service_id: ``str``
+
+        :return: True if activate was successful, False otherwise.
+        :rtype: ``bool``
+        """
         result = self.connection.request('%s/services/%s?action=activate' %
                                          (self.baseuri, service_id),
                                          method='POST')
-        if result.status in VALID_RESPONSE_CODES:
-            return result.status in VALID_RESPONSE_CODES
-        else:
-            raise RancherException(result.status,
-                                   'failed to activate service')
+        return result.status in VALID_RESPONSE_CODES
 
     def ex_deactivate_service(self, service_id):
+        """
+        Deactivate a service.
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#deactivate
+
+        :param service_id: The service to deactivate services for.
+        :type service_id: ``str``
 
+        :return: True if deactivate was successful, False otherwise.
+        :rtype: ``bool``
+        """
         result = self.connection.request('%s/services/%s?action=deactivate' %
                                          (self.baseuri, service_id),
                                          method='POST')
-        if result.status in VALID_RESPONSE_CODES:
-            return result.status in VALID_RESPONSE_CODES
-        else:
-            raise RancherException(result.status,
-                                   'failed to deactivate service')
+        return result.status in VALID_RESPONSE_CODES
 
-    def list_containers(self, image=None, all=True):
+    def list_containers(self):
         """
-        List the deployed container images
-        :param image: Filter to containers with a certain image
-        :type  image: :class:`libcloud.container.base.ContainerImage`
-        :param all: Show all container (including stopped ones)
-        :type  all: ``bool``
+        List the deployed containers.
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/container/
+
         :rtype: ``list`` of :class:`libcloud.container.base.Container`
         """
 
@@ -456,19 +863,160 @@ class RancherContainerDriver(ContainerDriver):
     def deploy_container(self, name, image, parameters=None, start=True,
                          **kwargs):
         """
-        Deploy an installed container image
-        For details on the additional parameters see : http://bit.ly/1PjMVKV
-        :param name: The name of the new container
-        :type  name: ``str``
-        :param image: The container image to deploy
-        :type  image: :class:`libcloud.container.base.ContainerImage`
-        :param parameters: Container Image parameters
+        Deploy a new container.
+
+        http://docs.rancher.com/rancher/v1.2/en/api/api-resources/container/#create
+
+        :param name: The desired name of the container.
+        :type name: ``str``
+
+        :param image: The Image object to deploy.
+        :type image: :class:`libcloud.container.base.ContainerImage`
+
+        :param parameters: Container Image parameters (unused)
         :type  parameters: ``str``
-        :param start: Start the container on deployment
-        :type  start: ``bool``
+
+        :param start: Whether to start the container on creation.
+        :type start: ``bool``
+
+        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
+        :type blkiodeviceoptions: ``dict``
+
+        :param build: Build details for the container.
+        :type build: ``dict``
+
+        :param capadd: Linux Capabilities to enable for this container.
+        :type capadd: ``list``
+
+        :param capdrop: Linux capabilities to disable for this container.
+        :type capdrop: ``list``
+
+        :param command: The command to execute when this container is run.
+        :type command: ``list``
+
+        :param count: The number of containers of this nature to launch.
+        :type count: ``int``
+
+        :param cpuset: Memory nodes in which to allow execution.
+        :type cpuset: ``str``
+
+        :param cpushares: Relative weight cpu shares to allow.
+        :type cpushares: ``int``
+
+        :param datavolumemounts: Data volume mountes this container should have
+        :type datavolumemounts: ``dict``
+
+        :param datavolumes: Data volumes to associate with this container.
+        :type datavolumes: ``list``
+
+        :param datavolumesfrom: Data volumes to inherit.
+        :type datavolumesfrom: ``list``
+
+        :param description: Description for this container.
+        :type description: ``str``
+
+        :param devices: Devices inside the container without privliged mode.
+        :type devices: ``list``
+
+        :param dns: DNS servers the container should utilize.
+        :type dns: ``list``
+
+        :param dnssearch: DNS search domains the container should utilize.
+        :type dnssearch: ``list``
+
+        :param domainname: The domain name the container should have.
+        :type domainname: ``str``
+
+        :param entrypoint: The entrypoint the container should have.
+        :type entrypoint: ``list``
+
+        :param environment: Environment variables the container should have.
+        :type environment: ``dict``
+
+        :param expose: Ports which should be exposed in the container.
+        :type expose: ``list``
+
+        :param extrahosts: Extra hosts file entries this container should have.
+        :type extrahosts: ``list``
+
+        :param healthcheck: Health check parameters for this container.
+        :type healthcheck: ``dict``
+
+        :param hostname: The hostname this container should have.
+        :type hostname: ``str``
+
+        :param instancelinks: Instance links the container should have.
+        :type instancelinks: ``dict``
+
+        :param labels: Labels to associate with this container.
+        :type labels: ``dict``
+
+        :param logconfig: Log configuration for this container.
+        :type logconfig: ``dict``
+
+        :param lxcconf: lxcConf specific to this container.
+        :type lxcconf: ``dict``
+
+        :param memory: The memory limit for this container.
+        :type memory: ``int``
+
+        :param memoryswap: Total memory limit for this container.
+        :type memoryswap: ``int``
+
+        :param networkcontainerrid: A Network container Id for this container.
+        :type networkcontainerrid: ``dict``
+
+        :param networkids: NetworkIds this container should contain.
+        :type networkids: ``list``
+
+        :param networkmode: The networkMode to enable for this container.
+        :type networkmode: ``str``
+
+        :param pidmode: The pidMode for this container.
+        :type pidmode: ``str``
+
+        :param ports: The ports to publicize for this container.
+        :type ports: ``list``
+
+        :param privileged: Whether to enable privileged mode for this container
+        :type privileged: ``bool``
+
+        :param publishallports: Publish all ports in container.
+        :type publishallports: ``bool``
+
+        :param readonly: Whether this container should be readOnly.
+        :type readonly: ``bool``
+
+        :param registrycredentialid: Registry credentials to use.
+        :type registrycredentialid: ``dict``
+
+        :param requestedhostid: Id of the requested host to run this container.
+        :type requestedhostid: ``dict``
+
+        :param restartpolicy: The container restart policy.
+        :type restartpolicy: ``dict``
+
+        :param securityopt: Security options to provide for this container.
+        :type securityopt: ``list``
+
+        :param stdinopen: Whether to keep stdin open.
+        :type stdinopen: ``bool``
+
+        :param tty: Enable a tty for this container.
+        :type tty: ``bool``
+
+        :param user: User this container should be tied to.
+        :type user: ``str``
+
+        :param volumedriver: The volume driver to use for this container.
+        :type volumedriver: ``str``
+
+        :param workingdir: The workingDir this container should start in.
+        :type workingdir: ``str``
+
         :rtype: :class:`Container`
         """
-        payload = self.build_payload(name, image, start, **kwargs)
+        payload = self._build_payload(name, image, start, **kwargs)
         data = json.dumps({k: v for k, v in payload.items() if v is not None})
 
         result = self.connection.request('%s/containers' % self.baseuri,
@@ -479,8 +1027,10 @@ class RancherContainerDriver(ContainerDriver):
     def get_container(self, id):
         """
         Get a container by ID
+
         :param id: The ID of the container to get
         :type  id: ``str``
+
         :rtype: :class:`libcloud.container.base.Container`
         """
         result = self.connection.request("%s/containers/%s" %
@@ -491,8 +1041,10 @@ class RancherContainerDriver(ContainerDriver):
     def stop_container(self, container):
         """
         Stop a container
+
         :param container: The container to be stopped
         :type  container: :class:`libcloud.container.base.Container`
+
         :return: The container refreshed with current data
         :rtype: :class:`libcloud.container.base.Container`
         """
@@ -502,43 +1054,43 @@ class RancherContainerDriver(ContainerDriver):
         if result.status in VALID_RESPONSE_CODES:
             return self.get_container(container.id)
         else:
-            raise RancherException(result.status,
-                                  'failed to stop container')
+            raise RancherException(result.status, 'failed to stop container')
 
     def destroy_container(self, container):
         """
         Remove a container
+
         :param container: The container to be destroyed
         :type  container: :class:`libcloud.container.base.Container`
+
         :return: True if the destroy was successful, False otherwise.
         :rtype: ``bool``
         """
         result = self.connection.request('%s/containers/%s' % (self.baseuri,
                                          container.id), method='DELETE')
-        if result.status in VALID_RESPONSE_CODES:
-            return self.get_container(container.id)
-        else:
-            raise RancherException(result.status,
-                                  'failed to destroy container')
+        return result.status in VALID_RESPONSE_CODES
 
     def _gen_image(self, imageuuid):
         """
-        This function converts a valid Rancher `imageUuid` string to a valid
+        This function converts a valid Rancher ``imageUuid`` string to a valid
         image object. Only supports docker based images hence `docker:` must
         prefix!!
 
-        For a imageuuid:
-            docker:<hostname>:<port>/<namespace>/<imagename>:<version>
+        For a ``imageuuid``:
+            ``docker:<hostname>:<port>/<namespace>/<imagename>:<version>``
 
         The following applies:
-            id = <imagename>
-            name = <imagename>
-            path = <hostname>:<port>/<namespace>/<imagename>
-            version = <version>
+            ``id`` = ``<imagename>``
+            ``name`` = ``<imagename>``
+            ``path`` = ``<hostname>:<port>/<namespace>/<imagename>``
+            ``version`` = ``<version>``
+
+        :param imageuuid: A valid Rancher image string
+            i.e. ``docker:rlister/hastebin:8.0``
+        :type imageuuid: ``str``
 
-        :param imageUuid: A valid Rancher image string
-        i.e. `docker:rlister/hastebin:8.0`
-        :return: Proper ContainerImage object.
+        :return: Converted ContainerImage object.
+        :rtype: :class:`libcloud.container.base.ContainerImage`
         """
         # Obtain just the name(:version) for parsing
         if '/' not in imageuuid:
@@ -637,12 +1189,3 @@ class RancherContainerDriver(ContainerDriver):
             state=state,
             driver=self.connection.driver,
             extra=extra)
-
-
-def ts_to_str(timestamp):
-    """
-    Return a timestamp as a nicely formated datetime string.
-    """
-    date = datetime.datetime.fromtimestamp(timestamp)
-    date_string = date.strftime("%d/%m/%Y %H:%M %Z")
-    return date_string


[22/27] libcloud git commit: casing and option changes

Posted by an...@apache.org.
casing and option changes


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/038411cb
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/038411cb
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/038411cb

Branch: refs/heads/trunk
Commit: 038411cb20d181d0558b42755d682f19b190dd42
Parents: 5962ef0
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Sep 30 11:37:52 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 98 +++++++++++++-----------------
 1 file changed, 42 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/038411cb/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index b60dd27..b4811ba 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -142,11 +142,9 @@ class RancherContainerDriver(ContainerDriver):
             "%s/environments" % self.baseuri).object
         return result['data']
 
-    def ex_deploy_stack(self, name, description=None, dockercompose=None,
-                        environment=None, externalid=None, outputs=None,
-                        previousenvironment=None,
-                        previousexternalid=None, ranchercompose=None,
-                        start=True):
+    def ex_deploy_stack(self, name, description=None, docker_compose=None,
+                        environment=None, external_id=None,
+                        rancher_compose=None, start=True):
         """
         Deploy a new stack.
 
@@ -158,26 +156,17 @@ class RancherContainerDriver(ContainerDriver):
         :param description: A desired description for the stack.
         :type description: ``str``
 
-        :param dockercompose: The Docker Compose configuration to use.
-        :type dockercompose: ``str``
+        :param docker_compose: The Docker Compose configuration to use.
+        :type docker_compose: ``str``
 
         :param environment: Environment K/V specific to this stack.
         :type environment: ``dict``
 
-        :param externalid: The externalId of the stack.
-        :type externalid: ``str``
+        :param external_id: The externalId of the stack.
+        :type external_id: ``str``
 
-        :param outputs: Any outputs the stack should contain.
-        :type outputs: ``dict``
-
-        :param previousenvironment: The previousEnvironment for this env.
-        :type previousenvironment: ``dict``
-
-        :param previousexternalid: The previousExternalId for this env.
-        :type previousexternalid: ``str``
-
-        :param ranchercompose: The Rancher Compose configuration for this env.
-        :type ranchercompose: ``str``
+        :param rancher_compose: The Rancher Compose configuration for this env.
+        :type rancher_compose: ``str``
 
         :param start: Whether to start this stack on creation.
         :type start: ``bool``
@@ -188,14 +177,11 @@ class RancherContainerDriver(ContainerDriver):
 
         payload = {
             "description": description,
-            "dockerCompose": dockercompose,
+            "dockerCompose": docker_compose,
             "environment": environment,
-            "externalId": externalid,
+            "externalId": external_id,
             "name": name,
-            "outputs": outputs,
-            "previousEnvironment": previousenvironment,
-            "previousExternalId": previousexternalid,
-            "rancherCompose": ranchercompose,
+            "rancherCompose": rancher_compose,
             "startOnCreate": start
         }
         data = json.dumps({k: v for k, v in payload.items() if v is not None})
@@ -285,12 +271,12 @@ class RancherContainerDriver(ContainerDriver):
         result = self.connection.request("%s/services" % self.baseuri).object
         return result['data']
 
-    def ex_deploy_service(self, name, image, environmentid,
-                          start=True, assignserviceipaddress=None,
-                          service_description=None, externalid=None,
-                          metadata=None, retainip=None, scale=None,
-                          scalepolicy=None, secondarylaunchconfigs=None,
-                          selectorcontainer=None, selectorlink=None,
+    def ex_deploy_service(self, name, image, environment_id,
+                          start=True, assign_service_ip_address=None,
+                          service_description=None, external_id=None,
+                          metadata=None, retain_ip=None, scale=None,
+                          scale_policy=None, secondary_launch_configs=None,
+                          selector_container=None, selector_link=None,
                           vip=None, **kwargs):
         """
         Deploy a Rancher Service under a stack.
@@ -305,41 +291,41 @@ class RancherContainerDriver(ContainerDriver):
         :param image: The Image object to deploy. (required)
         :type image: :class:`libcloud.container.base.ContainerImage`
 
-        :param environmentid: The stack ID this service is tied to. (required)
-        :type environmentid: ``str``
+        :param environment_id: The stack ID this service is tied to. (required)
+        :type environment_id: ``str``
 
         :param start: Whether to start the service on creation.
         :type start: ``bool``
 
-        :param assignserviceipaddress: The IP address to assign the service.
-        :type assignserviceipaddress: ``bool``
+        :param assign_service_ip_address: The IP address to assign the service.
+        :type assign_service_ip_address: ``bool``
 
         :param service_description: The service description.
         :type service_description: ``str``
 
-        :param externalid: The externalId for this service.
-        :type externalid: ``str``
+        :param external_id: The externalId for this service.
+        :type external_id: ``str``
 
         :param metadata: K/V Metadata for this service.
         :type metadata: ``dict``
 
-        :param retainip: Whether this service should retain its IP.
-        :type retainip: ``bool``
+        :param retain_ip: Whether this service should retain its IP.
+        :type retain_ip: ``bool``
 
         :param scale: The scale of containers in this service.
         :type scale: ``int``
 
-        :param scalepolicy: The scaling policy for this service.
-        :type scalepolicy: ``dict``
+        :param scale_policy: The scaling policy for this service.
+        :type scale_policy: ``dict``
 
-        :param secondarylaunchconfigs: Secondary container launch configs.
-        :type secondarylaunchconfigs: ``list``
+        :param secondary_launch_configs: Secondary container launch configs.
+        :type secondary_launch_configs: ``list``
 
-        :param selectorcontainer: The selectorContainer for this service.
-        :type selectorcontainer: ``str``
+        :param selector_container: The selectorContainer for this service.
+        :type selector_container: ``str``
 
-        :param selectorlink: The selectorLink for this service.
-        :type selectorlink: ``type``
+        :param selector_link: The selectorLink for this service.
+        :type selector_link: ``type``
 
         :param vip: The VIP to assign to this service.
         :type vip: ``str``
@@ -354,19 +340,19 @@ class RancherContainerDriver(ContainerDriver):
         }
 
         service_payload = {
-            "assignServiceIpAddress": assignserviceipaddress,
+            "assignServiceIpAddress": assign_service_ip_address,
             "description": service_description,
-            "environmentId": environmentid,
-            "externalId": externalid,
+            "environmentId": environment_id,
+            "externalId": external_id,
             "launchConfig": launchconfig,
             "metadata": metadata,
             "name": name,
-            "retainIp": retainip,
+            "retainIp": retain_ip,
             "scale": scale,
-            "scalePolicy": scalepolicy,
-            "secondaryLaunchConfigs": secondarylaunchconfigs,
-            "selectorContainer": selectorcontainer,
-            "selectorLink": selectorlink,
+            "scalePolicy": scale_policy,
+            "secondary_launch_configs": secondary_launch_configs,
+            "selectorContainer": selector_container,
+            "selectorLink": selector_link,
             "startOnCreate": start,
             "vip": vip
         }


[26/27] libcloud git commit: lint fixes in doc examples Closes #876

Posted by an...@apache.org.
lint fixes in doc examples
Closes #876


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/5f1d6bcf
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/5f1d6bcf
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/5f1d6bcf

Branch: refs/heads/trunk
Commit: 5f1d6bcff2022b4f5470674a4de1eb5f62bd2e56
Parents: 87c9501
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Oct 7 22:08:25 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:30 2016 +1100

----------------------------------------------------------------------
 docs/examples/container/rancher/deploy_container.py  | 1 +
 docs/examples/container/rancher/deploy_service.py    | 2 +-
 docs/examples/container/rancher/deploy_stack.py      | 2 +-
 docs/examples/container/rancher/search_containers.py | 4 ++--
 4 files changed, 5 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/5f1d6bcf/docs/examples/container/rancher/deploy_container.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/deploy_container.py b/docs/examples/container/rancher/deploy_container.py
index 51b64b2..d783853 100644
--- a/docs/examples/container/rancher/deploy_container.py
+++ b/docs/examples/container/rancher/deploy_container.py
@@ -1,5 +1,6 @@
 from libcloud.container.types import Provider
 from libcloud.container.providers import get_driver
+from libcloud.container.base import ContainerImage
 
 driver = get_driver(Provider.RANCHER)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/5f1d6bcf/docs/examples/container/rancher/deploy_service.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/deploy_service.py b/docs/examples/container/rancher/deploy_service.py
index 036aa1c..2df6486 100644
--- a/docs/examples/container/rancher/deploy_service.py
+++ b/docs/examples/container/rancher/deploy_service.py
@@ -1,5 +1,6 @@
 from libcloud.container.types import Provider
 from libcloud.container.providers import get_driver
+from libcloud.container.base import ContainerImage
 
 driver = get_driver(Provider.RANCHER)
 
@@ -14,4 +15,3 @@ new_service = connection.ex_deploy_service(name="excitingservice", image=image,
                                            environment={
                                                "STORAGE_TYPE": "file"
                                            })
-

http://git-wip-us.apache.org/repos/asf/libcloud/blob/5f1d6bcf/docs/examples/container/rancher/deploy_stack.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/deploy_stack.py b/docs/examples/container/rancher/deploy_stack.py
index 52d5122..222a316 100644
--- a/docs/examples/container/rancher/deploy_stack.py
+++ b/docs/examples/container/rancher/deploy_stack.py
@@ -10,4 +10,4 @@ new_stack = connection.ex_deploy_stack(name="GhostBlog",
                                        description="Contains services for the"
                                                    "ghost blog.")
 
-id_of_new_stack = new_stack['id']
\ No newline at end of file
+id_of_new_stack = new_stack['id']

http://git-wip-us.apache.org/repos/asf/libcloud/blob/5f1d6bcf/docs/examples/container/rancher/search_containers.py
----------------------------------------------------------------------
diff --git a/docs/examples/container/rancher/search_containers.py b/docs/examples/container/rancher/search_containers.py
index 8e7d632..a41ecc3 100644
--- a/docs/examples/container/rancher/search_containers.py
+++ b/docs/examples/container/rancher/search_containers.py
@@ -7,6 +7,6 @@ connection = driver("MYRANCHERACCESSKEY", "MYRANCHERSECRETKEY",
                     host="172.30.22.1", port=8080, secure=False)
 
 search_results = connection.ex_search_containers(
-    search_params={ "imageUuid": "docker:mysql", "state": "running" })
+    search_params={"imageUuid": "docker:mysql", "state": "running"})
 
-id_of_first_result = search_results[0]['id']
\ No newline at end of file
+id_of_first_result = search_results[0]['id']


[06/27] libcloud git commit: initial push

Posted by an...@apache.org.
initial push


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/8495ea71
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/8495ea71
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/8495ea71

Branch: refs/heads/trunk
Commit: 8495ea71744394528f30e3e297ea41a2e22574bb
Parents: a37a02a
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Tue Sep 27 23:12:46 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 648 +++++++++++++++++++++++++++++
 libcloud/container/providers.py       |   2 +
 libcloud/container/types.py           |   1 +
 3 files changed, 651 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/8495ea71/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
new file mode 100644
index 0000000..5229442
--- /dev/null
+++ b/libcloud/container/drivers/rancher.py
@@ -0,0 +1,648 @@
+import base64
+import datetime
+import shlex
+import re
+
+try:
+    import simplejson as json
+except:
+    import json
+
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import b
+
+from libcloud.common.base import JsonResponse, ConnectionUserAndKey
+from libcloud.common.types import InvalidCredsError
+
+from libcloud.container.base import (Container, ContainerDriver,
+                                     ContainerImage)
+
+from libcloud.container.providers import Provider
+from libcloud.container.types import ContainerState
+
+VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
+                        httplib.NO_CONTENT]
+
+
+class RancherResponse(JsonResponse):
+
+    def parse_body(self):
+        if len(self.body) == 0 and not self.parse_zero_length_body:
+            return self.body
+        valid_content_types = ['application/json',
+                               'application/json; charset=utf-8']
+        content_type = self.headers.get('content-type')
+        if content_type in valid_content_types:
+            return json.loads(self.body)
+
+    def parse_error(self):
+        if self.status == 401:
+            raise InvalidCredsError('Invalid credentials')
+        return self.body
+
+    def success(self):
+        return self.status in VALID_RESPONSE_CODES
+
+
+class RancherException(Exception):
+
+    def __init__(self, code, message):
+        self.code = code
+        self.message = message
+        self.args = (code, message)
+
+    def __str__(self):
+        return "%s %s" % (self.code, self.message)
+
+    def __repr__(self):
+        return "RancherException %s %s" % (self.code, self.message)
+
+
+class RancherConnection(ConnectionUserAndKey):
+
+    responseCls = RancherResponse
+    timeout = 30
+
+    def add_default_headers(self, headers):
+        """
+        Add parameters that are necessary for every request
+        If user and password are specified, include a base http auth
+        header
+        """
+        headers['Content-Type'] = 'application/json'
+        headers['Accept'] = 'application/json'
+        if self.key and self.user_id:
+            user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key)))
+            headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8'))
+        return headers
+
+
+class RancherContainerDriver(ContainerDriver):
+
+    type = Provider.RANCHER
+    name = 'Rancher'
+    website = 'http://rancher.com'
+    connectionCls = RancherConnection
+    # Holding off on this for now. Only Environment API interaction enabled.
+    supports_clusters = False
+    # As in the /v1/
+    version = '1'
+
+    def __init__(self, key, secret, secure=False, host='localhost',
+                 port=80, key_file=None, cert_file=None):
+        """
+        :param    key: API key or username to used (required)
+        :type     key: ``str``
+
+        :param    secret: Secret password to be used (required)
+        :type     secret: ``str``
+
+        :param    secure: Whether to use HTTPS or HTTP. Note: Some providers
+                only support HTTPS, and it is on by default.
+        :type     secure: ``bool``
+
+        :param    host: Override hostname used for connections.
+        :type     host: ``str``
+
+        :param    port: Override port used for connections.
+        :type     port: ``int``
+
+        :param    key_file: Path to private key for TLS connection (optional)
+        :type     key_file: ``str``
+
+        :param    cert_file: Path to public key for TLS connection (optional)
+        :type     cert_file: ``str``
+
+        :return: ``None``
+        """
+        super(RancherContainerDriver, self).__init__(key=key, secret=secret,
+                                                     secure=secure, host=host,
+                                                     port=port,
+                                                     key_file=key_file,
+                                                     cert_file=cert_file)
+        if host.startswith('https://'):
+            secure = True
+
+        # strip the prefix
+        prefixes = ['http://', 'https://']
+        for prefix in prefixes:
+            if host.startswith(prefix):
+                host = host.strip(prefix)
+        """
+        if key_file or cert_file:
+            # docker tls authentication-
+            # https://docs.docker.com/articles/https/
+            # We pass two files, a key_file with the
+            # private key and cert_file with the certificate
+            # libcloud will handle them through LibcloudHTTPSConnection
+            if not (key_file and cert_file):
+                raise Exception(
+                    'Needs both private key file and '
+                    'certificate file for tls authentication')
+            self.connection.key_file = key_file
+            self.connection.cert_file = cert_file
+            self.connection.secure = True
+        else:
+            self.connection.secure = secure
+        """
+
+        self.connection.host = host
+        self.connection.port = 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
+
+    def ex_list_environments(self):
+        """
+        List the deployed container images
+        :param image: Filter to containers with a certain image
+        :type  image: :class:`libcloud.container.base.ContainerImage`
+        :param all: Show all container (including stopped ones)
+        :type  all: ``bool``
+        :rtype: ``list`` of :class:`libcloud.container.base.Container`
+        """
+
+        result = self.connection.request("%s/environments" % self.baseuri).object
+        return result['data']
+
+    def ex_deploy_environment(self, name, description=None, dockercompose=None,
+                              environment=None, externalid=None, outputs=None,
+                              previousenvironment=None, previousexternalid=None,
+                              ranchercompose=None, start=True):
+
+        payload = {
+            "description": description,
+            "dockerCompose": dockercompose,
+            "environment": environment,
+            "externalId": externalid,
+            "name": name,
+            "outputs": outputs,
+            "previousEnvironment": previousenvironment,
+            "previousExternalId": previousexternalid,
+            "rancherCompose": ranchercompose,
+            "startOnCreate": start
+        }
+        data = json.dumps({k: v for k, v in payload.items() if v is not None})
+        result = self.connection.request('%s/environments' %
+                                         self.baseuri, data=data,
+                                         method='POST').object
+
+        return result
+
+    def ex_get_environment(self, env_id):
+        """
+        Get a service by ID
+        :param env_id: The environment to be obtained.
+        :return: The API dict object returned for the new service.
+        """
+        result = self.connection.request("%s/environments/%s" %
+                                         (self.baseuri, env_id)).object
+
+        return result
+
+    def ex_destroy_environment(self, env_id):
+
+        result = self.connection.request('%s/environments/%s' % (
+                                         self.baseuri, env_id), method='DELETE')
+        if result.status in VALID_RESPONSE_CODES:
+            return result.status in VALID_RESPONSE_CODES
+        else:
+            raise RancherException(result.status,
+                                   'failed to destroy environment')
+
+    def ex_activate_environment(self, env_id):
+
+        result = self.connection.request('%s/environments/%s?action=activateservices' %
+                                         (self.baseuri, env_id),
+                                         method='POST')
+        if result.status in VALID_RESPONSE_CODES:
+            return result.status in VALID_RESPONSE_CODES
+        else:
+            raise RancherException(result.status,
+                                   'failed to activate environment')
+
+    def ex_deactivate_environment(self, env_id):
+
+        result = self.connection.request('%s/environments/%s?action=deactivateservices' %
+                                         (self.baseuri, env_id),
+                                         method='POST')
+        if result.status in VALID_RESPONSE_CODES:
+            return result.status in VALID_RESPONSE_CODES
+        else:
+            raise RancherException(result.status,
+                                   'failed to deactivate environment')
+
+    def build_payload(self, image, start=True, name=None, image_type="docker",
+                      blkiodeviceoptions=None, build=None,
+                      capadd=None,
+                      capdrop=None, command=None,
+                      count=None, cpuset=None, cpushares=None,
+                      datavolumemounts=None, datavolumes=None,
+                      datavolumesfrom=None, description=None, devices=None,
+                      dns=None, dnssearch=None, domainname=None,
+                      entrypoint=None, environment=None, expose=None,
+                      extrahosts=None, healthcheck=None, hostname=None,
+                      instancelinks=None, labels=None, logconfig=None,
+                      lxcconf=None, memory=None, memoryswap=None,
+                      networkcontainerrid=None, networkids=None,
+                      networkmode=None, pidmode=None, ports=None,
+                      privileged=None, publishallports=None,
+                      readonly=None, registrycredentialid=None,
+                      requestedhostid=None, restartpolicy=None,
+                      securityopt=None,
+                      stdinopen=None, tty=None, user=None,
+                      volumedriver=None, workingdir=None):
+
+        if command is not None:
+            command = shlex.split(str(command))
+
+        if image.version is not None:
+            imageuuid = image_type + ':' + image.path + ':' + image.version
+        else:
+            imageuuid = image_type + ':' + image.path
+
+        payload = {
+            "blkioDeviceOptions": blkiodeviceoptions,
+            "build": build,
+            "capAdd": capadd,
+            "capDrop": capdrop,
+            "command": command,
+            "count": count,
+            "cpuSet": cpuset,
+            "cpuShares": cpushares,
+            "dataVolumeMounts": datavolumemounts,
+            "dataVolumes": datavolumes,
+            "dataVolumesFrom": datavolumesfrom,
+            "description": description,
+            "devices": devices,
+            "dns": dns,
+            "dnsSearch": dnssearch,
+            "domainName": domainname,
+            "entryPoint": entrypoint,
+            "environment": environment,
+            "expose": expose,
+            "extraHosts": extrahosts,
+            "healthCheck": healthcheck,
+            "hostname": hostname,
+            "imageUuid": imageuuid,
+            "instanceLinks": instancelinks,
+            "labels": labels,
+            "logConfig": logconfig,
+            "lxcConf": lxcconf,
+            "memory": memory,
+            "memorySwap": memoryswap,
+            "name": name,
+            "networkContainerId": networkcontainerrid,
+            "networkIds": networkids,
+            "networkMode": networkmode,
+            "pidMode": pidmode,
+            "ports": ports,
+            "privileged": privileged,
+            "publishAllPorts": publishallports,
+            "readOnly": readonly,
+            "registryCredentialId": registrycredentialid,
+            "requestedHostId": requestedhostid,
+            "restartPolicy": restartpolicy,
+            "securityOpt": securityopt,
+            "startOnCreate": start,
+            "stdinOpen": stdinopen,
+            "tty": tty,
+            "user": user,
+            "volumeDriver": volumedriver,
+            "workingdir": workingdir
+        }
+
+        return payload
+
+    def ex_list_services(self):
+        """
+        List the deployed container images
+        :param image: Filter to containers with a certain image
+        :type  image: :class:`libcloud.container.base.ContainerImage`
+        :param all: Show all container (including stopped ones)
+        :type  all: ``bool``
+        :rtype: ``list`` of :class:`libcloud.container.base.Container`
+        """
+
+        result = self.connection.request("%s/services" % self.baseuri).object
+        return result['data']
+
+    def ex_deploy_service(self, name, image, environmentid, start=True,
+                          assignserviceipaddress=None, service_description=None,
+                          externalid=None, metadata=None, retainip=None,
+                          scale=None, scalepolicy=None,
+                          secondarylaunchconfigs=None, selectorcontainer=None,
+                          selectorlink=None,
+                          vip=None, datavolumesfromlaunchconfigs=None,
+                          disks=None, kind=None, memorymb=None,
+                          networklaunchconfig=None, requsetedipaddress=None,
+                          userdata=None, vcpu=None, **kwargs):
+        """
+        Deploy a Rancher Service under a stack.
+        :param name: Name of the service.
+        :param image: ContainerImage object of image to utilize.
+        :param environmentid: The environment/stack ID this service is tied to.
+        :param kwargs: The Launchconfig provided as top-level options,
+        similar to deploy_container.
+        :return: The API object returned on proper service creation.
+        """
+
+        service_specific_container_config = {
+            "dataVolumesFromLaunchConfigs": datavolumesfromlaunchconfigs,
+            "disks": disks,
+            "kind": kind,
+            "memoryMb": memorymb,
+            "networkLaunchConfig": networklaunchconfig,
+            "requestedIpAddress": requsetedipaddress,
+            "userdata": userdata,
+            "vcpu": vcpu
+        }
+
+        # Build the de-facto container payload
+        # Note that we don't need to remove "name" since its None by default.
+        launchconfig = self.build_payload(image, start, **kwargs)
+        # Add in extra service configuration
+        launchconfig.update(service_specific_container_config)
+        launchconfig = json.dumps({k: v for k, v in launchconfig.items()
+                                   if v is not None})
+        service_payload = {
+            "assignServiceIpAddress": assignserviceipaddress,
+            "description": service_description,
+            "environmentId": environmentid,
+            "externalId": externalid,
+            "launchConfig": json.loads(launchconfig),
+            "metadata": metadata,
+            "name": name,
+            "retainIp": retainip,
+            "scale": scale,
+            "scalePolicy": scalepolicy,
+            "secondaryLaunchConfigs": secondarylaunchconfigs,
+            "selectorContainer": selectorcontainer,
+            "selectorLink": selectorlink,
+            "startOnCreate": start,
+            "vip": vip
+        }
+
+        data = json.dumps({k: v for k, v in service_payload.items()
+                           if v is not None})
+        result = self.connection.request('%s/services' % self.baseuri,
+                                         data=data, method='POST').object
+
+        return result
+
+    def ex_get_service(self, service_id):
+        """
+        Get a service by ID
+        :param service_id: The service to be obtained.
+        :return: The API dict object returned for the new service.
+        """
+        result = self.connection.request("%s/services/%s" %
+                                         (self.baseuri, service_id)).object
+
+        return result
+
+    def ex_destroy_service(self, service_id):
+        """
+        Delete a service.
+        :param service_id: The service to be destroyed
+        :return: True if the destroy was successful, False otherwise.
+        :rtype: ``bool``
+        """
+        result = self.connection.request('%s/services/%s' % (self.baseuri,
+                                         service_id), method='DELETE')
+        if result.status in VALID_RESPONSE_CODES:
+            return result.status in VALID_RESPONSE_CODES
+        else:
+            raise RancherException(result.status,
+                                   'failed to destroy service')
+
+    def ex_activate_service(self, service_id):
+
+        result = self.connection.request('%s/services/%s?action=activate' %
+                                         (self.baseuri, service_id),
+                                         method='POST')
+        if result.status in VALID_RESPONSE_CODES:
+            return result.status in VALID_RESPONSE_CODES
+        else:
+            raise RancherException(result.status,
+                                   'failed to activate service')
+
+    def ex_deactivate_service(self, service_id):
+
+        result = self.connection.request('%s/services/%s?action=deactivate' %
+                                         (self.baseuri, service_id),
+                                         method='POST')
+        if result.status in VALID_RESPONSE_CODES:
+            return result.status in VALID_RESPONSE_CODES
+        else:
+            raise RancherException(result.status,
+                                   'failed to deactivate service')
+
+    def list_containers(self, image=None, all=True):
+        """
+        List the deployed container images
+        :param image: Filter to containers with a certain image
+        :type  image: :class:`libcloud.container.base.ContainerImage`
+        :param all: Show all container (including stopped ones)
+        :type  all: ``bool``
+        :rtype: ``list`` of :class:`libcloud.container.base.Container`
+        """
+
+        result = self.connection.request("%s/containers" % self.baseuri).object
+        containers = [self._to_container(value) for value in result['data']]
+        return containers
+
+    def deploy_container(self, name, image, parameters=None, start=True,
+                         **kwargs):
+        """
+        Deploy an installed container image
+        For details on the additional parameters see : http://bit.ly/1PjMVKV
+        :param name: The name of the new container
+        :type  name: ``str``
+        :param image: The container image to deploy
+        :type  image: :class:`libcloud.container.base.ContainerImage`
+        :param parameters: Container Image parameters
+        :type  parameters: ``str``
+        :param start: Start the container on deployment
+        :type  start: ``bool``
+        :rtype: :class:`Container`
+        """
+        payload = self.build_payload(name, image, start, **kwargs)
+        data = json.dumps({k: v for k, v in payload.items() if v is not None})
+
+        result = self.connection.request('%s/containers' % self.baseuri,
+                                         data=data, method='POST').object
+
+        return self._to_container(result)
+
+    def get_container(self, id):
+        """
+        Get a container by ID
+        :param id: The ID of the container to get
+        :type  id: ``str``
+        :rtype: :class:`libcloud.container.base.Container`
+        """
+        result = self.connection.request("%s/containers/%s" %
+                                         (self.baseuri, id)).object
+
+        return self._to_container(result)
+
+    def stop_container(self, container):
+        """
+        Stop a container
+        :param container: The container to be stopped
+        :type  container: :class:`libcloud.container.base.Container`
+        :return: The container refreshed with current data
+        :rtype: :class:`libcloud.container.base.Container`
+        """
+        result = self.connection.request('%s/containers/%s?action=stop' %
+                                         (self.baseuri, container.id),
+                                         method='POST')
+        if result.status in VALID_RESPONSE_CODES:
+            return self.get_container(container.id)
+        else:
+            raise RancherException(result.status,
+                                  'failed to stop container')
+
+    def destroy_container(self, container):
+        """
+        Remove a container
+        :param container: The container to be destroyed
+        :type  container: :class:`libcloud.container.base.Container`
+        :return: True if the destroy was successful, False otherwise.
+        :rtype: ``bool``
+        """
+        result = self.connection.request('%s/containers/%s' % (self.baseuri,
+                                         container.id), method='DELETE')
+        if result.status in VALID_RESPONSE_CODES:
+            return self.get_container(container.id)
+        else:
+            raise RancherException(result.status,
+                                  'failed to destroy container')
+
+    def _gen_image(self, imageuuid):
+        """
+        This function converts a valid Rancher `imageUuid` string to a valid
+        image object. Only supports docker based images hence `docker:` must
+        prefix!!
+
+        For a imageuuid:
+            docker:<hostname>:<port>/<namespace>/<imagename>:<version>
+
+        The following applies:
+            id = <imagename>
+            name = <imagename>
+            path = <hostname>:<port>/<namespace>/<imagename>
+            version = <version>
+
+        :param imageUuid: A valid Rancher image string
+        i.e. `docker:rlister/hastebin:8.0`
+        :return: Proper ContainerImage object.
+        """
+        # Obtain just the name(:version) for parsing
+        if '/' not in imageuuid:
+            # String looks like `docker:mysql:8.0`
+            image_name_version = imageuuid.partition(':')[2]
+        else:
+            # String looks like `docker:oracle/mysql:8.0`
+            image_name_version = imageuuid.rpartition("/")[2]
+        # Parse based on ':'
+        if ':' in image_name_version:
+            version = image_name_version.partition(":")[2]
+            id = image_name_version.partition(":")[0]
+            name = id
+        else:
+            version = 'latest'
+            id = image_name_version
+            name = id
+        # Get our path based on if there was a version
+        if version != 'latest':
+            path = imageuuid.partition(':')[2].rpartition(':')[0]
+        else:
+            path = imageuuid.partition(':')[2]
+
+        return ContainerImage(
+            id=id,
+            name=name,
+            path=path,
+            version=version,
+            driver=self.connection.driver,
+            extra={
+                "imageUuid": imageuuid
+            }
+        )
+
+    def _to_container(self, data):
+        """
+        Convert container in proper Container instance object
+        ** Updating is NOT supported!!
+
+        :param data: API data about container i.e. result.object
+        :return: Proper Container object:
+         see http://libcloud.readthedocs.io/en/latest/container/api.html
+
+        """
+        rancher_state = data['state']
+        if 'running' in rancher_state:
+            state = ContainerState.RUNNING
+        elif 'stopped' in rancher_state:
+            state = ContainerState.STOPPED
+        elif 'restarting' in rancher_state:
+            state = ContainerState.REBOOTING
+        elif 'error' in rancher_state:
+            state = ContainerState.ERROR
+        elif 'removed' or 'purged' in rancher_state:
+            # A Removed container is purged after x amt of time.
+            # Both of these render the container dead (can't be started later)
+            state = ContainerState.TERMINATED
+        elif rancher_state.endswith('ing'):
+            # Best we can do for current actions
+            state = ContainerState.PENDING
+        else:
+            state = ContainerState.UNKNOWN
+
+        # Includes the most used items atm. Eventually, everything ;)
+        extra = {
+            "state": rancher_state,
+            "command": data['command'],
+            "created": data['created'],
+            "dataVolumes": data['dataVolumes'],
+            "dns": data['dns'],
+            "dnsSearch": data['dnsSearch'],
+            "domainName": data['domainName'],
+            "entryPoint": data['entryPoint'],
+            "environment": data['environment'],
+            "expose": data['expose'],
+            "healthState": data['healthState'],
+            "hostId": data['hostId'],
+            "hostname": data['hostname'],
+            "labels": data['labels'],
+            "networkMode": data['networkMode'],
+            "ports": data['ports'],
+            "primaryIpAddress": data['primaryIpAddress'],
+            "privileged": data['privileged'],
+            "restartPolicy": data['restartPolicy'],
+            "stdinOpen": data['stdinOpen'],
+            "tty": data['tty'],
+            "uuid": data['uuid'],
+            "workingDir": data['workingDir']
+        }
+
+        return Container(
+            id=data['id'],
+            name=data['name'],
+            image=self._gen_image(data['imageUuid']),
+            ip_addresses=[data['primaryIpAddress']],
+            state=state,
+            driver=self.connection.driver,
+            extra=extra)
+
+
+def ts_to_str(timestamp):
+    """
+    Return a timestamp as a nicely formated datetime string.
+    """
+    date = datetime.datetime.fromtimestamp(timestamp)
+    date_string = date.strftime("%d/%m/%Y %H:%M %Z")
+    return date_string

http://git-wip-us.apache.org/repos/asf/libcloud/blob/8495ea71/libcloud/container/providers.py
----------------------------------------------------------------------
diff --git a/libcloud/container/providers.py b/libcloud/container/providers.py
index 16ab58c..a823382 100644
--- a/libcloud/container/providers.py
+++ b/libcloud/container/providers.py
@@ -28,6 +28,8 @@ DRIVERS = {
     ('libcloud.container.drivers.ecs', 'ElasticContainerDriver'),
     Provider.KUBERNETES:
     ('libcloud.container.drivers.kubernetes', 'KubernetesContainerDriver'),
+    Provider.RANCHER:
+    ('libcloud.container.drivers.rancher', 'RancherContainerDriver'),
 }
 
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/8495ea71/libcloud/container/types.py
----------------------------------------------------------------------
diff --git a/libcloud/container/types.py b/libcloud/container/types.py
index bddca7f..b89fdfd 100644
--- a/libcloud/container/types.py
+++ b/libcloud/container/types.py
@@ -51,6 +51,7 @@ class Provider(object):
     ECS = 'ecs'
     JOYENT = 'joyent'
     KUBERNETES = 'kubernetes'
+    RANCHER = 'rancher'
 
 
 class ContainerState(Type):


[25/27] libcloud git commit: tonybaloney rm parse_error sugg

Posted by an...@apache.org.
tonybaloney rm parse_error sugg


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/4b497e68
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/4b497e68
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/4b497e68

Branch: refs/heads/trunk
Commit: 4b497e684656f125117ef7012455c31f3928622e
Parents: 613c669
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Oct 6 22:19:15 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 5 -----
 1 file changed, 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4b497e68/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 6e187d9..f627692 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -38,11 +38,6 @@ VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
 
 class RancherResponse(JsonResponse):
 
-    def parse_error(self):
-        if self.status == 401:
-            raise InvalidCredsError('Invalid credentials')
-        return super().parse_error()
-
     def success(self):
         return self.status in VALID_RESPONSE_CODES
 


[10/27] libcloud git commit: secure by default

Posted by an...@apache.org.
secure by default


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/723a179b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/723a179b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/723a179b

Branch: refs/heads/trunk
Commit: 723a179b728c46b0f3d8f6376eb08b7ed6b46168
Parents: ce91310
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Sep 29 11:47:46 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/723a179b/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index e0395e1..1d0618e 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -87,7 +87,7 @@ class RancherContainerDriver(ContainerDriver):
     # As in the /v1/
     version = '1'
 
-    def __init__(self, key, secret, secure=False, host='localhost', port=80):
+    def __init__(self, key, secret, secure=True, host='localhost', port=443):
         """
         Rancher Container driver class.
 
@@ -126,8 +126,8 @@ class RancherContainerDriver(ContainerDriver):
         super(RancherContainerDriver, self).__init__(key=key, secret=secret,
                                                      secure=secure, host=host,
                                                      port=port)
-        if host.startswith('https://'):
-            secure = True
+        if host.startswith('http://'):
+            secure = False
 
         # strip the prefix
         prefixes = ['http://', 'https://']


[02/27] libcloud git commit: everything is perfect; add tests

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_search_services.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_search_services.json b/libcloud/test/container/fixtures/rancher/ex_search_services.json
new file mode 100644
index 0000000..56be671
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_search_services.json
@@ -0,0 +1,346 @@
+{
+  "type": "collection",
+  "resourceType": "service",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/services"
+  },
+  "createTypes": {
+    "dnsService": "http://172.30.0.100:8080/v1/dnsservices",
+    "externalService": "http://172.30.0.100:8080/v1/externalservices",
+    "loadBalancerService": "http://172.30.0.100:8080/v1/loadbalancerservices",
+    "service": "http://172.30.0.100:8080/v1/services"
+  },
+  "actions": {},
+  "data": [
+    {
+      "id": "1s3",
+      "type": "service",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/services/1s3",
+        "account": "http://172.30.0.100:8080/v1/services/1s3/account",
+        "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s3/consumedbyservices",
+        "consumedservices": "http://172.30.0.100:8080/v1/services/1s3/consumedservices",
+        "environment": "http://172.30.0.100:8080/v1/services/1s3/environment",
+        "instances": "http://172.30.0.100:8080/v1/services/1s3/instances",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s3/serviceexposemaps",
+        "containerStats": "http://172.30.0.100:8080/v1/services/1s3/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/services/1s3/?action=update",
+        "restart": "http://172.30.0.100:8080/v1/services/1s3/?action=restart",
+        "remove": "http://172.30.0.100:8080/v1/services/1s3/?action=remove",
+        "setservicelinks": "http://172.30.0.100:8080/v1/services/1s3/?action=setservicelinks",
+        "removeservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=removeservicelink",
+        "upgrade": "http://172.30.0.100:8080/v1/services/1s3/?action=upgrade",
+        "addservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=addservicelink",
+        "deactivate": "http://172.30.0.100:8080/v1/services/1s3/?action=deactivate"
+      },
+      "name": "ghost",
+      "state": "active",
+      "accountId": "1a5",
+      "assignServiceIpAddress": false,
+      "createIndex": 1,
+      "created": "2016-09-22T18:00:26Z",
+      "createdTS": 1474567226000,
+      "currentScale": 1,
+      "description": null,
+      "environmentId": "1e2",
+      "externalId": null,
+      "fqdn": null,
+      "healthState": "healthy",
+      "kind": "service",
+      "launchConfig": {
+        "imageUuid": "docker:ghost",
+        "kind": "container",
+        "labels": {
+          "io.rancher.service.hash": "af9b5ddd2891271b12a88129e2bc37ff57998182"
+        },
+        "logConfig": {},
+        "networkMode": "managed",
+        "ports": [
+          "80:2368/tcp"
+        ],
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "startOnCreate": true,
+        "stdinOpen": false,
+        "tty": false,
+        "version": "0",
+        "vcpu": 1
+      },
+      "metadata": {
+        "io.rancher.service.hash": "f49280e1f709117b76693b638834791e4f4ef0fd"
+      },
+      "publicEndpoints": [
+        {
+          "ipAddress": "172.30.0.101",
+          "port": 80,
+          "serviceId": "1s3",
+          "hostId": "1h1",
+          "instanceId": "1i5"
+        }
+      ],
+      "removed": null,
+      "retainIp": null,
+      "scale": 1,
+      "scalePolicy": null,
+      "secondaryLaunchConfigs": [],
+      "selectorContainer": null,
+      "selectorLink": null,
+      "startOnCreate": false,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "upgrade": null,
+      "uuid": "c2ce7050-e5b5-42c7-a9fb-8ed8d33a4884",
+      "vip": null
+    },
+    {
+      "id": "1s6",
+      "type": "service",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/services/1s6",
+        "account": "http://172.30.0.100:8080/v1/services/1s6/account",
+        "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s6/consumedbyservices",
+        "consumedservices": "http://172.30.0.100:8080/v1/services/1s6/consumedservices",
+        "environment": "http://172.30.0.100:8080/v1/services/1s6/environment",
+        "instances": "http://172.30.0.100:8080/v1/services/1s6/instances",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s6/serviceexposemaps",
+        "containerStats": "http://172.30.0.100:8080/v1/services/1s6/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/services/1s6/?action=update",
+        "restart": "http://172.30.0.100:8080/v1/services/1s6/?action=restart",
+        "remove": "http://172.30.0.100:8080/v1/services/1s6/?action=remove",
+        "setservicelinks": "http://172.30.0.100:8080/v1/services/1s6/?action=setservicelinks",
+        "removeservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=removeservicelink",
+        "upgrade": "http://172.30.0.100:8080/v1/services/1s6/?action=upgrade",
+        "addservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=addservicelink",
+        "deactivate": "http://172.30.0.100:8080/v1/services/1s6/?action=deactivate"
+      },
+      "name": "123",
+      "state": "active",
+      "accountId": "1a5",
+      "assignServiceIpAddress": false,
+      "createIndex": 1,
+      "created": "2016-09-22T18:28:04Z",
+      "createdTS": 1474568884000,
+      "currentScale": 1,
+      "description": null,
+      "environmentId": "1e2",
+      "externalId": null,
+      "fqdn": null,
+      "healthState": "healthy",
+      "kind": "service",
+      "launchConfig": {
+        "capAdd": [],
+        "capDrop": [],
+        "count": null,
+        "cpuSet": null,
+        "cpuShares": null,
+        "dataVolumes": [],
+        "dataVolumesFrom": [],
+        "description": null,
+        "devices": [],
+        "dns": [],
+        "dnsSearch": [],
+        "domainName": null,
+        "hostname": null,
+        "imageUuid": "docker:ubuntu:trusty",
+        "kind": "container",
+        "labels": {
+          "io.rancher.container.pull_image": "always"
+        },
+        "logConfig": {
+          "config": {},
+          "driver": ""
+        },
+        "memory": null,
+        "memoryMb": null,
+        "memorySwap": null,
+        "networkMode": "managed",
+        "pidMode": null,
+        "ports": [],
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "requestedIpAddress": null,
+        "startOnCreate": true,
+        "stdinOpen": true,
+        "tty": true,
+        "user": null,
+        "userdata": null,
+        "version": "0bdea468-c3e9-4562-951c-d543958e966a",
+        "volumeDriver": null,
+        "workingDir": null,
+        "dataVolumesFromLaunchConfigs": [],
+        "networkLaunchConfig": null,
+        "vcpu": 1
+      },
+      "metadata": null,
+      "publicEndpoints": null,
+      "removed": null,
+      "retainIp": null,
+      "scale": 1,
+      "scalePolicy": null,
+      "secondaryLaunchConfigs": [],
+      "selectorContainer": null,
+      "selectorLink": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "upgrade": {
+        "inServiceStrategy": {
+          "batchSize": 1,
+          "intervalMillis": 2000,
+          "launchConfig": {
+            "capAdd": [],
+            "capDrop": [],
+            "count": null,
+            "cpuSet": null,
+            "cpuShares": null,
+            "dataVolumes": [],
+            "dataVolumesFrom": [],
+            "description": null,
+            "devices": [],
+            "dns": [],
+            "dnsSearch": [],
+            "domainName": null,
+            "hostname": null,
+            "imageUuid": "docker:ubuntu:trusty",
+            "kind": "container",
+            "labels": {
+              "io.rancher.container.pull_image": "always"
+            },
+            "logConfig": {
+              "config": {},
+              "driver": ""
+            },
+            "memory": null,
+            "memoryMb": null,
+            "memorySwap": null,
+            "networkMode": "managed",
+            "pidMode": null,
+            "ports": [],
+            "privileged": false,
+            "publishAllPorts": false,
+            "readOnly": false,
+            "requestedIpAddress": null,
+            "startOnCreate": true,
+            "stdinOpen": true,
+            "tty": true,
+            "user": null,
+            "userdata": null,
+            "version": "0bdea468-c3e9-4562-951c-d543958e966a",
+            "volumeDriver": null,
+            "workingDir": null,
+            "dataVolumesFromLaunchConfigs": [],
+            "networkLaunchConfig": null,
+            "vcpu": 1
+          },
+          "previousLaunchConfig": {
+            "capAdd": [],
+            "capDrop": [],
+            "count": null,
+            "cpuSet": null,
+            "cpuShares": null,
+            "dataVolumes": [],
+            "dataVolumesFrom": [],
+            "description": null,
+            "devices": [],
+            "dns": [],
+            "dnsSearch": [],
+            "domainName": null,
+            "hostname": null,
+            "imageUuid": "docker:ubuntu:trusty",
+            "kind": "container",
+            "labels": {
+              "io.rancher.container.pull_image": "always"
+            },
+            "logConfig": {
+              "config": {},
+              "driver": ""
+            },
+            "memory": null,
+            "memoryMb": null,
+            "memorySwap": null,
+            "networkMode": "managed",
+            "pidMode": null,
+            "ports": [],
+            "privileged": false,
+            "publishAllPorts": false,
+            "readOnly": false,
+            "requestedIpAddress": null,
+            "startOnCreate": true,
+            "stdinOpen": true,
+            "tty": true,
+            "user": null,
+            "userdata": null,
+            "version": "0",
+            "volumeDriver": null,
+            "workingDir": null,
+            "dataVolumesFromLaunchConfigs": [],
+            "networkLaunchConfig": null,
+            "vcpu": 1
+          },
+          "previousSecondaryLaunchConfigs": [],
+          "secondaryLaunchConfigs": [],
+          "startFirst": true
+        },
+        "toServiceStrategy": null
+      },
+      "uuid": "c0ae4d08-e20a-45ef-9fb9-ad9f7cdeeb15",
+      "vip": null
+    }
+  ],
+  "sortLinks": {
+    "accountId": "http://172.30.0.100:8080/v1/services?limit=4&sort=accountId",
+    "createIndex": "http://172.30.0.100:8080/v1/services?limit=4&sort=createIndex",
+    "created": "http://172.30.0.100:8080/v1/services?limit=4&sort=created",
+    "description": "http://172.30.0.100:8080/v1/services?limit=4&sort=description",
+    "environmentId": "http://172.30.0.100:8080/v1/services?limit=4&sort=environmentId",
+    "externalId": "http://172.30.0.100:8080/v1/services?limit=4&sort=externalId",
+    "healthState": "http://172.30.0.100:8080/v1/services?limit=4&sort=healthState",
+    "id": "http://172.30.0.100:8080/v1/services?limit=4&sort=id",
+    "kind": "http://172.30.0.100:8080/v1/services?limit=4&sort=kind",
+    "name": "http://172.30.0.100:8080/v1/services?limit=4&sort=name",
+    "removeTime": "http://172.30.0.100:8080/v1/services?limit=4&sort=removeTime",
+    "removed": "http://172.30.0.100:8080/v1/services?limit=4&sort=removed",
+    "selectorContainer": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorContainer",
+    "selectorLink": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorLink",
+    "state": "http://172.30.0.100:8080/v1/services?limit=4&sort=state",
+    "uuid": "http://172.30.0.100:8080/v1/services?limit=4&sort=uuid",
+    "vip": "http://172.30.0.100:8080/v1/services?limit=4&sort=vip"
+  },
+  "pagination": {
+    "first": null,
+    "previous": null,
+    "next": "http://172.30.0.100:8080/v1/services?limit=4&marker=m4",
+    "limit": 4,
+    "total": null,
+    "partial": true
+  },
+  "sort": null,
+  "filters": {
+    "accountId": null,
+    "createIndex": null,
+    "created": null,
+    "description": null,
+    "environmentId": null,
+    "externalId": null,
+    "healthState": null,
+    "id": null,
+    "kind": null,
+    "name": null,
+    "removeTime": null,
+    "removed": null,
+    "selectorContainer": null,
+    "selectorLink": null,
+    "state": null,
+    "uuid": null,
+    "vip": null
+  },
+  "createDefaults": {}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/list_containers.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/list_containers.json b/libcloud/test/container/fixtures/rancher/list_containers.json
new file mode 100644
index 0000000..e55d786
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/list_containers.json
@@ -0,0 +1,336 @@
+{
+  "type": "collection",
+  "resourceType": "container",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/containers"
+  },
+  "createTypes": {
+    "container": "http://172.30.0.100:8080/v1/containers",
+    "launchConfig": "http://172.30.0.100:8080/v1/launchconfigs",
+    "virtualMachine": "http://172.30.0.100:8080/v1/virtualmachines"
+  },
+  "actions": {},
+  "data": [
+    {
+      "id": "1i1",
+      "type": "container",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/containers/1i1",
+        "account": "http://172.30.0.100:8080/v1/containers/1i1/account",
+        "credentials": "http://172.30.0.100:8080/v1/containers/1i1/credentials",
+        "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i1/healthcheckinstancehostmaps",
+        "hosts": "http://172.30.0.100:8080/v1/containers/1i1/hosts",
+        "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i1/instancelabels",
+        "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i1/instancelinks",
+        "instances": "http://172.30.0.100:8080/v1/containers/1i1/instances",
+        "mounts": "http://172.30.0.100:8080/v1/containers/1i1/mounts",
+        "ports": "http://172.30.0.100:8080/v1/containers/1i1/ports",
+        "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i1/serviceevents",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i1/serviceexposemaps",
+        "services": "http://172.30.0.100:8080/v1/containers/1i1/services",
+        "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i1/targetinstancelinks",
+        "volumes": "http://172.30.0.100:8080/v1/containers/1i1/volumes",
+        "stats": "http://172.30.0.100:8080/v1/containers/1i1/stats",
+        "containerStats": "http://172.30.0.100:8080/v1/containers/1i1/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/containers/1i1/?action=update",
+        "error": "http://172.30.0.100:8080/v1/containers/1i1/?action=error",
+        "remove": "http://172.30.0.100:8080/v1/containers/1i1/?action=remove",
+        "start": "http://172.30.0.100:8080/v1/containers/1i1/?action=start",
+        "logs": "http://172.30.0.100:8080/v1/containers/1i1/?action=logs",
+        "setlabels": "http://172.30.0.100:8080/v1/containers/1i1/?action=setlabels"
+      },
+      "name": "Concrete5_CMSMysql_1",
+      "state": "stopped",
+      "accountId": "1a5",
+      "blkioDeviceOptions": null,
+      "build": null,
+      "capAdd": null,
+      "capDrop": null,
+      "command": null,
+      "cpuSet": null,
+      "cpuShares": null,
+      "createIndex": 1,
+      "created": "2016-09-22T17:58:55Z",
+      "createdTS": 1474567135000,
+      "dataVolumeMounts": {},
+      "dataVolumes": [
+        "CMS_DB_DATA:/var/lib/mysql"
+      ],
+      "dataVolumesFrom": null,
+      "deploymentUnitUuid": "761675e2-7fc7-4fbf-a825-132429a44349",
+      "description": null,
+      "devices": null,
+      "dns": [
+        "169.254.169.250"
+      ],
+      "dnsSearch": [
+        "concrete5.rancher.internal",
+        "cmsmysql.concrete5.rancher.internal",
+        "rancher.internal"
+      ],
+      "dockerPorts": [],
+      "domainName": null,
+      "entryPoint": null,
+      "environment": {
+        "MYSQL_DATABASE": "CMS_DB",
+        "MYSQL_PASSWORD": "password",
+        "MYSQL_ROOT_PASSWORD": "password",
+        "MYSQL_USER": "CMS_USER"
+      },
+      "expose": null,
+      "externalId": "957136960bd1b51acf5a6c0079d0e35b8d5c14f54722a3063ceb868e85fd3758",
+      "extraHosts": null,
+      "firstRunning": "2016-09-22T17:59:40Z",
+      "firstRunningTS": 1474567180000,
+      "healthCheck": null,
+      "healthState": null,
+      "hostId": "1h1",
+      "hostname": null,
+      "imageUuid": "docker:mysql",
+      "kind": "container",
+      "labels": {
+        "io.rancher.project.name": "Concrete5",
+        "io.rancher.container.pull_image": "always",
+        "io.rancher.service.deployment.unit": "761675e2-7fc7-4fbf-a825-132429a44349",
+        "io.rancher.service.launch.config": "io.rancher.service.primary.launch.config",
+        "io.rancher.project_service.name": "Concrete5/CMSMysql",
+        "io.rancher.stack.name": "Concrete5",
+        "io.rancher.stack_service.name": "Concrete5/CMSMysql",
+        "io.rancher.service.hash": "c5d6bacef4be47a5ca5d1517a1d33319d024cdde",
+        "io.rancher.container.uuid": "a1140e7c-9260-423e-a7d0-8f5f7bb8e946",
+        "io.rancher.container.name": "Concrete5_CMSMysql_1",
+        "io.rancher.container.ip": "10.42.80.96/16"
+      },
+      "logConfig": {},
+      "lxcConf": null,
+      "memory": null,
+      "memorySwap": null,
+      "nativeContainer": false,
+      "networkContainerId": null,
+      "networkMode": "managed",
+      "pidMode": null,
+      "ports": null,
+      "primaryIpAddress": "10.42.80.96",
+      "privileged": false,
+      "publishAllPorts": false,
+      "readOnly": false,
+      "registryCredentialId": null,
+      "removed": null,
+      "requestedHostId": null,
+      "restartPolicy": null,
+      "securityOpt": null,
+      "startCount": 4,
+      "startOnCreate": true,
+      "stdinOpen": true,
+      "systemContainer": null,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "tty": true,
+      "user": null,
+      "uuid": "a1140e7c-9260-423e-a7d0-8f5f7bb8e946",
+      "version": "0",
+      "volumeDriver": null,
+      "workingDir": null
+    },
+    {
+      "id": "1i2",
+      "type": "container",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/containers/1i2",
+        "account": "http://172.30.0.100:8080/v1/containers/1i2/account",
+        "credentials": "http://172.30.0.100:8080/v1/containers/1i2/credentials",
+        "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i2/healthcheckinstancehostmaps",
+        "hosts": "http://172.30.0.100:8080/v1/containers/1i2/hosts",
+        "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i2/instancelabels",
+        "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/instancelinks",
+        "instances": "http://172.30.0.100:8080/v1/containers/1i2/instances",
+        "mounts": "http://172.30.0.100:8080/v1/containers/1i2/mounts",
+        "ports": "http://172.30.0.100:8080/v1/containers/1i2/ports",
+        "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i2/serviceevents",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i2/serviceexposemaps",
+        "services": "http://172.30.0.100:8080/v1/containers/1i2/services",
+        "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/targetinstancelinks",
+        "volumes": "http://172.30.0.100:8080/v1/containers/1i2/volumes",
+        "stats": "http://172.30.0.100:8080/v1/containers/1i2/stats",
+        "containerStats": "http://172.30.0.100:8080/v1/containers/1i2/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/containers/1i2/?action=update",
+        "stop": "http://172.30.0.100:8080/v1/containers/1i2/?action=stop",
+        "restart": "http://172.30.0.100:8080/v1/containers/1i2/?action=restart",
+        "migrate": "http://172.30.0.100:8080/v1/containers/1i2/?action=migrate",
+        "logs": "http://172.30.0.100:8080/v1/containers/1i2/?action=logs",
+        "setlabels": "http://172.30.0.100:8080/v1/containers/1i2/?action=setlabels",
+        "execute": "http://172.30.0.100:8080/v1/containers/1i2/?action=execute",
+        "proxy": "http://172.30.0.100:8080/v1/containers/1i2/?action=proxy"
+      },
+      "name": "Network Agent",
+      "state": "running",
+      "accountId": "1a5",
+      "blkioDeviceOptions": null,
+      "build": null,
+      "capAdd": null,
+      "capDrop": null,
+      "command": null,
+      "cpuSet": null,
+      "cpuShares": null,
+      "createIndex": null,
+      "created": "2016-09-22T17:58:57Z",
+      "createdTS": 1474567137000,
+      "dataVolumeMounts": {},
+      "dataVolumes": [
+        "/var/lib/rancher/etc:/var/lib/rancher/etc:ro"
+      ],
+      "dataVolumesFrom": null,
+      "deploymentUnitUuid": null,
+      "description": null,
+      "devices": null,
+      "dns": null,
+      "dnsSearch": null,
+      "domainName": null,
+      "entryPoint": null,
+      "environment": null,
+      "expose": null,
+      "externalId": "129c67adc9fa084fbc8e1f963db0180896b88af3dca69c7e8fe0493284e4651c",
+      "extraHosts": null,
+      "firstRunning": "2016-09-22T17:59:11Z",
+      "firstRunningTS": 1474567151000,
+      "healthCheck": null,
+      "healthState": null,
+      "hostId": "1h1",
+      "hostname": null,
+      "imageUuid": "docker:rancher/agent-instance:v0.8.3",
+      "kind": "container",
+      "labels": {
+        "io.rancher.container.system": "NetworkAgent",
+        "io.rancher.container.uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb",
+        "io.rancher.container.name": "Network Agent",
+        "io.rancher.container.agent_id": "2",
+        "io.rancher.container.ip": "10.42.247.188/16"
+      },
+      "logConfig": null,
+      "lxcConf": null,
+      "memory": null,
+      "memorySwap": null,
+      "nativeContainer": false,
+      "networkContainerId": null,
+      "networkIds": [],
+      "networkMode": null,
+      "pidMode": null,
+      "ports": null,
+      "primaryIpAddress": "10.42.247.188",
+      "privileged": true,
+      "publishAllPorts": false,
+      "readOnly": false,
+      "registryCredentialId": null,
+      "removed": null,
+      "requestedHostId": null,
+      "restartPolicy": null,
+      "securityOpt": null,
+      "startCount": 3,
+      "startOnCreate": true,
+      "stdinOpen": false,
+      "systemContainer": "NetworkAgent",
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "tty": false,
+      "user": null,
+      "uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb",
+      "version": "0",
+      "volumeDriver": null,
+      "workingDir": null
+    }
+  ],
+  "sortLinks": {
+    "accountId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=accountId",
+    "agentId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=agentId",
+    "allocationState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=allocationState",
+    "compute": "http://172.30.0.100:8080/v1/containers?limit=2&sort=compute",
+    "createIndex": "http://172.30.0.100:8080/v1/containers?limit=2&sort=createIndex",
+    "created": "http://172.30.0.100:8080/v1/containers?limit=2&sort=created",
+    "deploymentUnitUuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=deploymentUnitUuid",
+    "description": "http://172.30.0.100:8080/v1/containers?limit=2&sort=description",
+    "dnsInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsInternal",
+    "dnsSearchInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsSearchInternal",
+    "domain": "http://172.30.0.100:8080/v1/containers?limit=2&sort=domain",
+    "externalId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=externalId",
+    "firstRunning": "http://172.30.0.100:8080/v1/containers?limit=2&sort=firstRunning",
+    "healthState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthState",
+    "healthUpdated": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthUpdated",
+    "hostname": "http://172.30.0.100:8080/v1/containers?limit=2&sort=hostname",
+    "id": "http://172.30.0.100:8080/v1/containers?limit=2&sort=id",
+    "imageId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=imageId",
+    "instanceTriggeredStop": "http://172.30.0.100:8080/v1/containers?limit=2&sort=instanceTriggeredStop",
+    "kind": "http://172.30.0.100:8080/v1/containers?limit=2&sort=kind",
+    "memoryMb": "http://172.30.0.100:8080/v1/containers?limit=2&sort=memoryMb",
+    "name": "http://172.30.0.100:8080/v1/containers?limit=2&sort=name",
+    "nativeContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=nativeContainer",
+    "networkContainerId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=networkContainerId",
+    "offeringId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=offeringId",
+    "registryCredentialId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=registryCredentialId",
+    "removeTime": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removeTime",
+    "removed": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removed",
+    "serviceIndexId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=serviceIndexId",
+    "startCount": "http://172.30.0.100:8080/v1/containers?limit=2&sort=startCount",
+    "state": "http://172.30.0.100:8080/v1/containers?limit=2&sort=state",
+    "systemContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=systemContainer",
+    "token": "http://172.30.0.100:8080/v1/containers?limit=2&sort=token",
+    "userdata": "http://172.30.0.100:8080/v1/containers?limit=2&sort=userdata",
+    "uuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=uuid",
+    "version": "http://172.30.0.100:8080/v1/containers?limit=2&sort=version",
+    "zoneId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=zoneId"
+  },
+  "pagination": {
+    "first": null,
+    "previous": null,
+    "next": "http://172.30.0.100:8080/v1/containers?limit=2&marker=m2",
+    "limit": 2,
+    "total": null,
+    "partial": true
+  },
+  "sort": null,
+  "filters": {
+    "accountId": null,
+    "agentId": null,
+    "allocationState": null,
+    "compute": null,
+    "createIndex": null,
+    "created": null,
+    "deploymentUnitUuid": null,
+    "description": null,
+    "dnsInternal": null,
+    "dnsSearchInternal": null,
+    "domain": null,
+    "externalId": null,
+    "firstRunning": null,
+    "healthState": null,
+    "healthUpdated": null,
+    "hostname": null,
+    "id": null,
+    "imageId": null,
+    "instanceTriggeredStop": null,
+    "kind": null,
+    "memoryMb": null,
+    "name": null,
+    "nativeContainer": null,
+    "networkContainerId": null,
+    "offeringId": null,
+    "registryCredentialId": null,
+    "removeTime": null,
+    "removed": null,
+    "serviceIndexId": null,
+    "startCount": null,
+    "state": null,
+    "systemContainer": null,
+    "token": null,
+    "userdata": null,
+    "uuid": null,
+    "version": null,
+    "zoneId": null
+  },
+  "createDefaults": {}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/stop_container.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/stop_container.json b/libcloud/test/container/fixtures/rancher/stop_container.json
new file mode 100644
index 0000000..fad41a6
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/stop_container.json
@@ -0,0 +1,109 @@
+{
+  "id": "1i31",
+  "type": "container",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/containers/1i31",
+    "account": "http://172.30.0.100:8080/v1/containers/1i31/account",
+    "credentials": "http://172.30.0.100:8080/v1/containers/1i31/credentials",
+    "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i31/healthcheckinstancehostmaps",
+    "hosts": "http://172.30.0.100:8080/v1/containers/1i31/hosts",
+    "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i31/instancelabels",
+    "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/instancelinks",
+    "instances": "http://172.30.0.100:8080/v1/containers/1i31/instances",
+    "mounts": "http://172.30.0.100:8080/v1/containers/1i31/mounts",
+    "ports": "http://172.30.0.100:8080/v1/containers/1i31/ports",
+    "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i31/serviceevents",
+    "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i31/serviceexposemaps",
+    "services": "http://172.30.0.100:8080/v1/containers/1i31/services",
+    "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/targetinstancelinks",
+    "volumes": "http://172.30.0.100:8080/v1/containers/1i31/volumes",
+    "stats": "http://172.30.0.100:8080/v1/containers/1i31/stats",
+    "containerStats": "http://172.30.0.100:8080/v1/containers/1i31/containerstats"
+  },
+  "actions": {
+    "update": "http://172.30.0.100:8080/v1/containers/1i31/?action=update",
+    "error": "http://172.30.0.100:8080/v1/containers/1i31/?action=error",
+    "remove": "http://172.30.0.100:8080/v1/containers/1i31/?action=remove",
+    "start": "http://172.30.0.100:8080/v1/containers/1i31/?action=start",
+    "logs": "http://172.30.0.100:8080/v1/containers/1i31/?action=logs",
+    "setlabels": "http://172.30.0.100:8080/v1/containers/1i31/?action=setlabels"
+  },
+  "name": "newcontainer",
+  "state": "stopping",
+  "accountId": "1a5",
+  "blkioDeviceOptions": null,
+  "build": null,
+  "capAdd": null,
+  "capDrop": null,
+  "command": null,
+  "cpuSet": null,
+  "cpuShares": null,
+  "createIndex": null,
+  "created": "2016-10-06T15:55:58Z",
+  "createdTS": 1475769358000,
+  "dataVolumeMounts": {},
+  "dataVolumes": [],
+  "dataVolumesFrom": null,
+  "deploymentUnitUuid": null,
+  "description": null,
+  "devices": null,
+  "dns": [
+    "169.254.169.250"
+  ],
+  "dnsSearch": [
+    "rancher.internal"
+  ],
+  "dockerPorts": [],
+  "domainName": null,
+  "entryPoint": null,
+  "environment": {
+    "STORAGE_TYPE": "file"
+  },
+  "expose": null,
+  "externalId": "ab334bd25d25db7b94fdcead8f5c023b05bed424f56243187aa90f5ef7f07b09",
+  "extraHosts": null,
+  "firstRunning": "2016-10-06T15:56:00Z",
+  "firstRunningTS": 1475769360000,
+  "healthCheck": null,
+  "healthState": null,
+  "hostId": "1h1",
+  "hostname": null,
+  "imageUuid": "docker:rlister/hastebin:latest",
+  "kind": "container",
+  "labels": {
+    "io.rancher.container.uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805",
+    "io.rancher.container.name": "newcontainer",
+    "io.rancher.container.ip": "10.42.204.104/16"
+  },
+  "logConfig": null,
+  "lxcConf": null,
+  "memory": null,
+  "memorySwap": null,
+  "nativeContainer": false,
+  "networkContainerId": null,
+  "networkMode": "managed",
+  "pidMode": null,
+  "ports": null,
+  "primaryIpAddress": "10.42.204.104",
+  "privileged": false,
+  "publishAllPorts": false,
+  "readOnly": false,
+  "registryCredentialId": null,
+  "removed": null,
+  "requestedHostId": null,
+  "restartPolicy": null,
+  "securityOpt": null,
+  "startCount": 1,
+  "startOnCreate": true,
+  "stdinOpen": false,
+  "systemContainer": null,
+  "transitioning": "yes",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "tty": false,
+  "user": null,
+  "uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805",
+  "version": "0",
+  "volumeDriver": null,
+  "workingDir": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/test_rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_rancher.py b/libcloud/test/container/test_rancher.py
new file mode 100644
index 0000000..2d1cc4d
--- /dev/null
+++ b/libcloud/test/container/test_rancher.py
@@ -0,0 +1,245 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+
+from libcloud.test import unittest
+
+from libcloud.container.base import ContainerImage
+from libcloud.container.drivers.rancher import RancherContainerDriver
+
+from libcloud.utils.py3 import httplib
+from libcloud.test.secrets import CONTAINER_PARAMS_RANCHER
+from libcloud.test.file_fixtures import ContainerFileFixtures
+from libcloud.test import MockHttp
+
+
+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
+    def test_ex_list_stacks(self):
+        stacks = self.driver.ex_list_stacks()
+        self.assertEqual(len(stacks), 6)
+        self.assertEqual(stacks[0]['id'], "1e1")
+
+    def test_ex_deploy_stack(self):
+        stack = self.driver.ex_deploy_stack(name="newstack",
+                                            environment={
+                                                "root_password": "password"
+                                            })
+        self.assertEqual(stack['id'], "1e9")
+        self.assertEqual(stack['environment']['root_password'], "password")
+
+    def test_ex_get_stack(self):
+        # also uses ex_deploy_stack.json
+        stack = self.driver.ex_get_stack("1e9")
+        self.assertEqual(stack['id'], "1e9")
+        self.assertEqual(stack['environment']['root_password'], "password")
+
+    def test_ex_search_stacks(self):
+        # also uses ex_list_stacks.json
+        stacks = self.driver.ex_search_stacks({"healthState": "healthy"})
+        self.assertEqual(len(stacks), 6)
+        self.assertEqual(stacks[0]['healthState'], "healthy")
+
+    def test_ex_destroy_stack(self):
+        # Not sure how to do these with returns in mockhttp
+        response = self.driver.ex_destroy_stack("1e10")
+        self.assertEqual(response, True)
+
+    def test_ex_activate_stack(self):
+        response = self.driver.ex_activate_stack("1e1")
+        self.assertEqual(response, True)
+
+    def test_ex_deactivate_stack(self):
+        # also uses ex_activate_stack.json
+        response = self.driver.ex_activate_stack("1e1")
+        self.assertEqual(response, True)
+
+    def test_ex_list_services(self):
+        services = self.driver.ex_list_services()
+        self.assertEqual(len(services), 4)
+        self.assertEqual(services[0]['id'], "1s1")
+
+    def test_ex_deploy_service(self):
+        image = ContainerImage(
+            id="hastebin",
+            name="hastebin",
+            path="rlister/hastebin",
+            version="latest",
+            driver=None
+        )
+        service = self.driver.ex_deploy_service(name="newservice",
+                                                environment_id="1e1",
+                                                image=image,
+                                                environment={
+                                                    "root_password": "password"
+                                                })
+        self.assertEqual(service['id'], "1s13")
+        self.assertEqual(service['environmentId'], "1e6")
+        self.assertEqual(service['launchConfig']['environment']
+                         ['root_password'], "password")
+        self.assertEqual(service['launchConfig']['imageUuid'],
+                         "docker:rlister/hastebin:latest")
+
+    def test_ex_get_service(self):
+        # also uses ex_deploy_service.json
+        service = self.driver.ex_get_service("1s13")
+        self.assertEqual(service['id'], "1s13")
+        self.assertEqual(service['environmentId'], "1e6")
+        self.assertEqual(service['launchConfig']['environment']
+                         ['root_password'], "password")
+
+    def test_ex_search_services(self):
+        services = self.driver.ex_search_services({"healthState": "healthy"})
+        self.assertEqual(len(services), 2)
+        self.assertEqual(services[0]['healthState'], "healthy")
+
+    def test_ex_destroy_service(self):
+        # Not sure how to do these with returns in mockhttp
+        response = self.driver.ex_destroy_service("1s13")
+        self.assertEqual(response, True)
+
+    def test_ex_activate_service(self):
+        response = self.driver.ex_activate_service("1s6")
+        self.assertEqual(response, True)
+
+    def test_ex_deactivate_service(self):
+        # also uses ex_activate_service.json
+        response = self.driver.ex_activate_service("1s6")
+        self.assertEqual(response, True)
+
+    def test_list_containers(self):
+        containers = self.driver.list_containers()
+        self.assertEqual(len(containers), 2)
+        self.assertEqual(containers[0].id, "1i1")
+
+    def test_deploy_container(self):
+        container = self.driver.deploy_container(
+            name='newcontainer',
+            image=ContainerImage(
+                id="hastebin",
+                name="hastebin",
+                path="rlister/hastebin",
+                version="latest",
+                driver=None
+            ),
+            environment={"STORAGE_TYPE": "file"},
+            networkMode="managed"
+        )
+        self.assertEqual(container.id, '1i31')
+        self.assertEqual(container.name, 'newcontainer')
+        self.assertEqual(container.extra['environment'],
+                         {'STORAGE_TYPE': 'file'})
+
+    def test_get_container(self):
+        # also uses ex_deploy_container.json
+        container = self.driver.get_container("1i31")
+        self.assertEqual(container.id, '1i31')
+        self.assertEqual(container.name, 'newcontainer')
+        self.assertEqual(container.extra['environment'],
+                         {'STORAGE_TYPE': 'file'})
+
+    def test_stop_container(self):
+        container = self.driver.get_container("1i31")
+        container.stop()
+
+    def test_ex_search_containers(self):
+        containers = self.driver.ex_search_containers({"state": "running"})
+        self.assertEqual(len(containers), 1)
+
+    def test_destroy_container(self):
+        container = self.driver.get_container("1i31")
+        container.destroy()
+
+
+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])
+        else:
+            return (httplib.OK, self.fixtures.load('deploy_container.json'),
+                    {}, httplib.responses[httplib.OK])
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())


[23/27] libcloud git commit: and secrets file

Posted by an...@apache.org.
and secrets file


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/4f8a3e68
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/4f8a3e68
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/4f8a3e68

Branch: refs/heads/trunk
Commit: 4f8a3e68ad36fdba2350b4e000b959110c410fb1
Parents: ceffaf9
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Oct 7 21:08:32 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/test/secrets.py-dist | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4f8a3e68/libcloud/test/secrets.py-dist
----------------------------------------------------------------------
diff --git a/libcloud/test/secrets.py-dist b/libcloud/test/secrets.py-dist
index 5b17a86..e2e6165 100644
--- a/libcloud/test/secrets.py-dist
+++ b/libcloud/test/secrets.py-dist
@@ -93,3 +93,4 @@ DNS_PARAMS_DNSPOD = ('key', )
 CONTAINER_PARAMS_DOCKER = ('user', 'password')
 CONTAINER_PARAMS_ECS = ('user', 'password', 'region')
 CONTAINER_PARAMS_KUBERNETES = ('user', 'password')
+CONTAINER_PARAMS_RANCHER = ('user', 'password')
\ No newline at end of file


[03/27] libcloud git commit: everything is perfect; add tests

Posted by an...@apache.org.
everything is perfect; add tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d179167a
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d179167a
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d179167a

Branch: refs/heads/trunk
Commit: d179167ab8d7ff98a19cbd9440d08ea0c496e3cb
Parents: 5b17bdf
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Oct 7 20:46:15 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py           |   5 +-
 .../fixtures/rancher/deploy_container.json      | 109 ++++
 .../fixtures/rancher/ex_activate_service.json   | 198 +++++++
 .../fixtures/rancher/ex_activate_stack.json     |  52 ++
 .../fixtures/rancher/ex_deploy_service.json     |  66 +++
 .../fixtures/rancher/ex_deploy_stack.json       |  40 ++
 .../fixtures/rancher/ex_destroy_service.json    |  66 +++
 .../fixtures/rancher/ex_destroy_stack.json      |  40 ++
 .../fixtures/rancher/ex_list_services.json      | 536 +++++++++++++++++++
 .../fixtures/rancher/ex_list_stacks.json        | 310 +++++++++++
 .../fixtures/rancher/ex_search_containers.json  | 212 ++++++++
 .../fixtures/rancher/ex_search_services.json    | 346 ++++++++++++
 .../fixtures/rancher/list_containers.json       | 336 ++++++++++++
 .../fixtures/rancher/stop_container.json        | 109 ++++
 libcloud/test/container/test_rancher.py         | 245 +++++++++
 15 files changed, 2667 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 9bf810a..c0d2f9d 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -24,7 +24,6 @@ from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 
 from libcloud.common.base import JsonResponse, ConnectionUserAndKey
-from libcloud.common.types import InvalidCredsError
 
 from libcloud.container.base import (Container, ContainerDriver,
                                      ContainerImage)
@@ -200,7 +199,7 @@ class RancherContainerDriver(ContainerDriver):
             "rancherCompose": rancher_compose,
             "startOnCreate": start
         }
-        data = json.dumps(dict((k,v) for (k,v) in payload.items()
+        data = json.dumps(dict((k, v) for (k, v) in payload.items()
                                if v is not None))
         result = self.connection.request('%s/environments' %
                                          self.baseuri, data=data,
@@ -391,7 +390,7 @@ class RancherContainerDriver(ContainerDriver):
             "vip": vip
         }
 
-        data = json.dumps(dict((k,v) for (k,v) in service_payload.items()
+        data = json.dumps(dict((k, v) for (k, v) in service_payload.items()
                                if v is not None))
         result = self.connection.request('%s/services' % self.baseuri,
                                          data=data, method='POST').object

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/deploy_container.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/deploy_container.json b/libcloud/test/container/fixtures/rancher/deploy_container.json
new file mode 100644
index 0000000..bfe0963
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/deploy_container.json
@@ -0,0 +1,109 @@
+{
+  "id": "1i31",
+  "type": "container",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/containers/1i31",
+    "account": "http://172.30.0.100:8080/v1/containers/1i31/account",
+    "credentials": "http://172.30.0.100:8080/v1/containers/1i31/credentials",
+    "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i31/healthcheckinstancehostmaps",
+    "hosts": "http://172.30.0.100:8080/v1/containers/1i31/hosts",
+    "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i31/instancelabels",
+    "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/instancelinks",
+    "instances": "http://172.30.0.100:8080/v1/containers/1i31/instances",
+    "mounts": "http://172.30.0.100:8080/v1/containers/1i31/mounts",
+    "ports": "http://172.30.0.100:8080/v1/containers/1i31/ports",
+    "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i31/serviceevents",
+    "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i31/serviceexposemaps",
+    "services": "http://172.30.0.100:8080/v1/containers/1i31/services",
+    "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i31/targetinstancelinks",
+    "volumes": "http://172.30.0.100:8080/v1/containers/1i31/volumes",
+    "stats": "http://172.30.0.100:8080/v1/containers/1i31/stats",
+    "containerStats": "http://172.30.0.100:8080/v1/containers/1i31/containerstats"
+  },
+  "actions": {
+    "update": "http://172.30.0.100:8080/v1/containers/1i31/?action=update",
+    "error": "http://172.30.0.100:8080/v1/containers/1i31/?action=error",
+    "remove": "http://172.30.0.100:8080/v1/containers/1i31/?action=remove",
+    "start": "http://172.30.0.100:8080/v1/containers/1i31/?action=start",
+    "logs": "http://172.30.0.100:8080/v1/containers/1i31/?action=logs",
+    "setlabels": "http://172.30.0.100:8080/v1/containers/1i31/?action=setlabels"
+  },
+  "name": "newcontainer",
+  "state": "running",
+  "accountId": "1a5",
+  "blkioDeviceOptions": null,
+  "build": null,
+  "capAdd": null,
+  "capDrop": null,
+  "command": null,
+  "cpuSet": null,
+  "cpuShares": null,
+  "createIndex": null,
+  "created": "2016-10-06T15:55:58Z",
+  "createdTS": 1475769358000,
+  "dataVolumeMounts": {},
+  "dataVolumes": [],
+  "dataVolumesFrom": null,
+  "deploymentUnitUuid": null,
+  "description": null,
+  "devices": null,
+  "dns": [
+    "169.254.169.250"
+  ],
+  "dnsSearch": [
+    "rancher.internal"
+  ],
+  "dockerPorts": [],
+  "domainName": null,
+  "entryPoint": null,
+  "environment": {
+    "STORAGE_TYPE": "file"
+  },
+  "expose": null,
+  "externalId": "ab334bd25d25db7b94fdcead8f5c023b05bed424f56243187aa90f5ef7f07b09",
+  "extraHosts": null,
+  "firstRunning": "2016-10-06T15:56:00Z",
+  "firstRunningTS": 1475769360000,
+  "healthCheck": null,
+  "healthState": null,
+  "hostId": "1h1",
+  "hostname": null,
+  "imageUuid": "docker:rlister/hastebin:latest",
+  "kind": "container",
+  "labels": {
+    "io.rancher.container.uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805",
+    "io.rancher.container.name": "newcontainer",
+    "io.rancher.container.ip": "10.42.204.104/16"
+  },
+  "logConfig": null,
+  "lxcConf": null,
+  "memory": null,
+  "memorySwap": null,
+  "nativeContainer": false,
+  "networkContainerId": null,
+  "networkMode": "managed",
+  "pidMode": null,
+  "ports": null,
+  "primaryIpAddress": "10.42.204.104",
+  "privileged": false,
+  "publishAllPorts": false,
+  "readOnly": false,
+  "registryCredentialId": null,
+  "removed": null,
+  "requestedHostId": null,
+  "restartPolicy": null,
+  "securityOpt": null,
+  "startCount": 1,
+  "startOnCreate": true,
+  "stdinOpen": false,
+  "systemContainer": null,
+  "transitioning": "no",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "tty": false,
+  "user": null,
+  "uuid": "6d3dcf5f-28b8-4e60-9bf1-618b76a9a805",
+  "version": "0",
+  "volumeDriver": null,
+  "workingDir": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_activate_service.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_activate_service.json b/libcloud/test/container/fixtures/rancher/ex_activate_service.json
new file mode 100644
index 0000000..a103ef5
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_activate_service.json
@@ -0,0 +1,198 @@
+{
+  "id": "1s6",
+  "type": "service",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/services/1s6",
+    "account": "http://172.30.0.100:8080/v1/services/1s6/account",
+    "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s6/consumedbyservices",
+    "consumedservices": "http://172.30.0.100:8080/v1/services/1s6/consumedservices",
+    "environment": "http://172.30.0.100:8080/v1/services/1s6/environment",
+    "instances": "http://172.30.0.100:8080/v1/services/1s6/instances",
+    "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s6/serviceexposemaps",
+    "containerStats": "http://172.30.0.100:8080/v1/services/1s6/containerstats"
+  },
+  "actions": {
+    "update": "http://172.30.0.100:8080/v1/services/1s6/?action=update",
+    "restart": "http://172.30.0.100:8080/v1/services/1s6/?action=restart",
+    "remove": "http://172.30.0.100:8080/v1/services/1s6/?action=remove",
+    "setservicelinks": "http://172.30.0.100:8080/v1/services/1s6/?action=setservicelinks",
+    "removeservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=removeservicelink",
+    "upgrade": "http://172.30.0.100:8080/v1/services/1s6/?action=upgrade",
+    "addservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=addservicelink",
+    "deactivate": "http://172.30.0.100:8080/v1/services/1s6/?action=deactivate"
+  },
+  "name": "123",
+  "state": "active",
+  "accountId": "1a5",
+  "assignServiceIpAddress": false,
+  "createIndex": 1,
+  "created": "2016-09-22T18:28:04Z",
+  "createdTS": 1474568884000,
+  "currentScale": 1,
+  "description": null,
+  "environmentId": "1e2",
+  "externalId": null,
+  "fqdn": null,
+  "healthState": "healthy",
+  "kind": "service",
+  "launchConfig": {
+    "capAdd": [],
+    "capDrop": [],
+    "count": null,
+    "cpuSet": null,
+    "cpuShares": null,
+    "dataVolumes": [],
+    "dataVolumesFrom": [],
+    "description": null,
+    "devices": [],
+    "dns": [],
+    "dnsSearch": [],
+    "domainName": null,
+    "hostname": null,
+    "imageUuid": "docker:ubuntu:trusty",
+    "kind": "container",
+    "labels": {
+      "io.rancher.container.pull_image": "always"
+    },
+    "logConfig": {
+      "config": {},
+      "driver": ""
+    },
+    "memory": null,
+    "memoryMb": null,
+    "memorySwap": null,
+    "networkMode": "managed",
+    "pidMode": null,
+    "ports": [],
+    "privileged": false,
+    "publishAllPorts": false,
+    "readOnly": false,
+    "requestedIpAddress": null,
+    "startOnCreate": true,
+    "stdinOpen": true,
+    "tty": true,
+    "user": null,
+    "userdata": null,
+    "version": "0bdea468-c3e9-4562-951c-d543958e966a",
+    "volumeDriver": null,
+    "workingDir": null,
+    "dataVolumesFromLaunchConfigs": [],
+    "networkLaunchConfig": null,
+    "vcpu": 1
+  },
+  "metadata": null,
+  "publicEndpoints": null,
+  "removed": null,
+  "retainIp": null,
+  "scale": 1,
+  "scalePolicy": null,
+  "secondaryLaunchConfigs": [],
+  "selectorContainer": null,
+  "selectorLink": null,
+  "startOnCreate": true,
+  "transitioning": "no",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "upgrade": {
+    "inServiceStrategy": {
+      "batchSize": 1,
+      "intervalMillis": 2000,
+      "launchConfig": {
+        "capAdd": [],
+        "capDrop": [],
+        "count": null,
+        "cpuSet": null,
+        "cpuShares": null,
+        "dataVolumes": [],
+        "dataVolumesFrom": [],
+        "description": null,
+        "devices": [],
+        "dns": [],
+        "dnsSearch": [],
+        "domainName": null,
+        "hostname": null,
+        "imageUuid": "docker:ubuntu:trusty",
+        "kind": "container",
+        "labels": {
+          "io.rancher.container.pull_image": "always"
+        },
+        "logConfig": {
+          "config": {},
+          "driver": ""
+        },
+        "memory": null,
+        "memoryMb": null,
+        "memorySwap": null,
+        "networkMode": "managed",
+        "pidMode": null,
+        "ports": [],
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "requestedIpAddress": null,
+        "startOnCreate": true,
+        "stdinOpen": true,
+        "tty": true,
+        "user": null,
+        "userdata": null,
+        "version": "0bdea468-c3e9-4562-951c-d543958e966a",
+        "volumeDriver": null,
+        "workingDir": null,
+        "dataVolumesFromLaunchConfigs": [],
+        "networkLaunchConfig": null,
+        "vcpu": 1
+      },
+      "previousLaunchConfig": {
+        "capAdd": [],
+        "capDrop": [],
+        "count": null,
+        "cpuSet": null,
+        "cpuShares": null,
+        "dataVolumes": [],
+        "dataVolumesFrom": [],
+        "description": null,
+        "devices": [],
+        "dns": [],
+        "dnsSearch": [],
+        "domainName": null,
+        "hostname": null,
+        "imageUuid": "docker:ubuntu:trusty",
+        "kind": "container",
+        "labels": {
+          "io.rancher.container.pull_image": "always"
+        },
+        "logConfig": {
+          "config": {},
+          "driver": ""
+        },
+        "memory": null,
+        "memoryMb": null,
+        "memorySwap": null,
+        "networkMode": "managed",
+        "pidMode": null,
+        "ports": [],
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "requestedIpAddress": null,
+        "startOnCreate": true,
+        "stdinOpen": true,
+        "tty": true,
+        "user": null,
+        "userdata": null,
+        "version": "0",
+        "volumeDriver": null,
+        "workingDir": null,
+        "dataVolumesFromLaunchConfigs": [],
+        "networkLaunchConfig": null,
+        "vcpu": 1
+      },
+      "previousSecondaryLaunchConfigs": [],
+      "secondaryLaunchConfigs": [],
+      "startFirst": true
+    },
+    "toServiceStrategy": null
+  },
+  "uuid": "c0ae4d08-e20a-45ef-9fb9-ad9f7cdeeb15",
+  "vip": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_activate_stack.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_activate_stack.json b/libcloud/test/container/fixtures/rancher/ex_activate_stack.json
new file mode 100644
index 0000000..65148eb
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_activate_stack.json
@@ -0,0 +1,52 @@
+{
+  "id": "1e1",
+  "type": "environment",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/environments/1e1",
+    "account": "http://172.30.0.100:8080/v1/environments/1e1/account",
+    "services": "http://172.30.0.100:8080/v1/environments/1e1/services",
+    "composeConfig": "http://172.30.0.100:8080/v1/environments/1e1/composeconfig"
+  },
+  "actions": {
+    "upgrade": "http://172.30.0.100:8080/v1/environments/1e1/?action=upgrade",
+    "update": "http://172.30.0.100:8080/v1/environments/1e1/?action=update",
+    "remove": "http://172.30.0.100:8080/v1/environments/1e1/?action=remove",
+    "addoutputs": "http://172.30.0.100:8080/v1/environments/1e1/?action=addoutputs",
+    "activateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=activateservices",
+    "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=deactivateservices",
+    "exportconfig": "http://172.30.0.100:8080/v1/environments/1e1/?action=exportconfig"
+  },
+  "name": "Concrete5",
+  "state": "active",
+  "accountId": "1a5",
+  "created": "2016-09-22T17:58:53Z",
+  "createdTS": 1474567133000,
+  "description": null,
+  "dockerCompose": "CMSMysql:\r\n    environment:\r\n        MYSQL_ROOT_PASSWORD: ${root_password}\r\n        MYSQL_DATABASE: ${db_name}\r\n        MYSQL_USER: ${db_username}\r\n        MYSQL_PASSWORD: ${db_password}\r\n    labels:\r\n        io.rancher.container.pull_image: always\r\n    tty: true\r\n    image: mysql\r\n    volumes:\r\n    - ${db_data_location}:/var/lib/mysql\r\n    stdin_open: true\r\n    volume_driver: ${volume_driver}\r\n\r\nCMSConfig:\r\n    image: opensaas/concrete5\r\n    tty: true\r\n    stdin_open: true\r\n    links:\r\n    - CMSMysql:mysql\r\n    volumes:\r\n    - ${cms_application_data}:/var/www/html/application\r\n    - ${cms_packages_data}:/var/www/html/packages\r\n    labels:\r\n        io.rancher.container.hostname_override: container_name\r\n        io.rancher.container.start_once: true\r\n    volume_driver: ${volume_driver}\r\n    command: bash -c \"chown -R www-data. application; chown -R www-data. packages; sleep 2m; php -f concrete/bin/concrete5.
 php c5:install --db-server=mysql --db-username=${db_username} --db-password=${db_password} --db-database=${db_name} --site=${cms_sitename} --admin-email=${cms_admin_email} --admin-password=${cms_admin_password} -n -vvv\"\r\n\r\nConcrete5App:\r\n    labels:\r\n        io.rancher.container.pull_image: always\r\n        io.rancher.sidekicks: CMSConfig\r\n    tty: true\r\n    links:\r\n    - CMSMysql:mysql\r\n    image: opensaas/concrete5\r\n    volumes:\r\n    - ${cms_application_data}:/var/www/html/application\r\n    - ${cms_packages_data}:/var/www/html/packages\r\n    volume_driver: ${volume_driver}\r\n    stdin_open: true",
+  "environment": {
+    "root_password": "password",
+    "db_name": "CMS_DB",
+    "db_username": "CMS_USER",
+    "db_password": "password",
+    "db_data_location": "CMS_DB_DATA",
+    "volume_driver": "",
+    "cms_application_data": "CMS_APP_DATA",
+    "cms_packages_data": "CMS_PACK_DATA",
+    "cms_admin_email": "admin@example.com",
+    "cms_admin_password": "password",
+    "cms_sitename": "MySite"
+  },
+  "externalId": "catalog://community:Concrete5:1",
+  "healthState": "unhealthy",
+  "kind": "environment",
+  "outputs": null,
+  "previousEnvironment": null,
+  "previousExternalId": null,
+  "rancherCompose": ".catalog:\r\n    name: \"Concrete5\"\r\n    version: \"v0.2\"\r\n    description: \"Concrete5 CMS\"\r\n    uuid: Concrete5-1\r\n    minimum_rancher_version: v0.51.0\r\n    questions:\r\n        - variable: root_password\r\n          description: \"MySQL root password - keep this password complex and secure\"\r\n          label: \"MySQL Root Password\"\r\n          required: true\r\n          default: \"password\"\r\n          type: \"string\"\r\n        - variable: db_name\r\n          description: \"MySQL Database Name - to use in the Concrete5 setup\"\r\n          label: \"MySQL Database Name\"\r\n          required: true\r\n          default: \"CMS_DB\"\r\n          type: \"string\"\r\n        - variable: db_username\r\n          description: \"MySQL Username - to use in the Concrete5 setup\"\r\n          label: \"MySQL Username\"\r\n          required: true\r\n          default: \"CMS_USER\"\r\n          type: \"string\"\r\n        - variable: db_password\r\
 n          description: \"MySQL password for the above user - to use in the Concrete5 setup\"\r\n          label: \"MySQL Password\"\r\n          required: true\r\n          default: \"password\"\r\n          type: \"string\"\r\n        - variable: db_data_location\r\n          description: \"Location on the host for the database files\"\r\n          label: \"DB Data Location\"\r\n          required: true\r\n          default: \"CMS_DB_DATA\"\r\n          type: \"string\"\r\n        - variable: volume_driver\r\n          description: \"Volume Driver for the persistant data locations requires docker 1.7\"\r\n          label: \"Volume Driver\"\r\n          type: \"string\"\r\n        - variable: cms_application_data\r\n          description: \"Concrcte5 application folder for persistant data storage\"\r\n          label: \"Application Folder\"\r\n          required: true\r\n          default: \"CMS_APP_DATA\"\r\n          type: \"string\"\r\n        - variable: cms_packages_data\r\n  
         description: \"Concrcte5 packages folder for persistant data storage\"\r\n          label: \"Packages Folder\"\r\n          required: true\r\n          default: \"CMS_PACK_DATA\"\r\n          type: \"string\"\r\n        - variable: cms_admin_email\r\n          description: \"Concrcete5 admin email address\"\r\n          label: \"Admin Email\"\r\n          required: true\r\n          default: \"admin@example.com\"\r\n          type: \"string\"\r\n        - variable: cms_admin_password\r\n          description: \"Concrcete5 admin password\"\r\n          label: \"Admin Password\"\r\n          required: true\r\n          default: \"password\"\r\n          type: \"string\"\r\n        - variable: cms_sitename\r\n          description: \"Concrcete5 Sitename\"\r\n          label: \"Sitename\"\r\n          required: true\r\n          default: \"MySite\"\r\n          type: \"string\"\r\nCMSMysql:\r\n    scale: 1\r\nConcrete5App:\r\n    scale: 1\r\n\r\n",
+  "removed": null,
+  "startOnCreate": true,
+  "transitioning": "no",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "uuid": "e129ed27-3823-4e2e-af62-4565d68995d4"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_deploy_service.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_deploy_service.json b/libcloud/test/container/fixtures/rancher/ex_deploy_service.json
new file mode 100644
index 0000000..e30bc47
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_deploy_service.json
@@ -0,0 +1,66 @@
+{
+  "id": "1s13",
+  "type": "service",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/services/1s13",
+    "account": "http://172.30.0.100:8080/v1/services/1s13/account",
+    "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s13/consumedbyservices",
+    "consumedservices": "http://172.30.0.100:8080/v1/services/1s13/consumedservices",
+    "environment": "http://172.30.0.100:8080/v1/services/1s13/environment",
+    "instances": "http://172.30.0.100:8080/v1/services/1s13/instances",
+    "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s13/serviceexposemaps",
+    "containerStats": "http://172.30.0.100:8080/v1/services/1s13/containerstats"
+  },
+  "actions": {
+    "setservicelinks": "http://172.30.0.100:8080/v1/services/1s13/?action=setservicelinks",
+    "removeservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=removeservicelink",
+    "addservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=addservicelink"
+  },
+  "name": "newservice",
+  "state": "active",
+  "accountId": "1a5",
+  "assignServiceIpAddress": false,
+  "createIndex": 1,
+  "created": "2016-10-06T15:31:35Z",
+  "createdTS": 1475767895000,
+  "currentScale": 1,
+  "description": null,
+  "environmentId": "1e6",
+  "externalId": null,
+  "fqdn": null,
+  "healthState": "unhealthy",
+  "kind": "service",
+  "launchConfig": {
+    "environment": {
+      "root_password": "password"
+    },
+    "imageUuid": "docker:rlister/hastebin:latest",
+    "kind": "container",
+    "networkMode": "managed",
+    "privileged": false,
+    "publishAllPorts": false,
+    "readOnly": false,
+    "startOnCreate": true,
+    "stdinOpen": false,
+    "tty": false,
+    "version": "0",
+    "vcpu": 1
+  },
+  "metadata": null,
+  "publicEndpoints": null,
+  "removed": "2016-10-06T15:45:03Z",
+  "removedTS": 1475768703000,
+  "retainIp": null,
+  "scale": 1,
+  "scalePolicy": null,
+  "secondaryLaunchConfigs": [],
+  "selectorContainer": null,
+  "selectorLink": null,
+  "startOnCreate": true,
+  "transitioning": "no",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "upgrade": null,
+  "uuid": "de2cd54f-9936-49fb-a41a-35653c4510f7",
+  "vip": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_deploy_stack.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_deploy_stack.json b/libcloud/test/container/fixtures/rancher/ex_deploy_stack.json
new file mode 100644
index 0000000..38b1db4
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_deploy_stack.json
@@ -0,0 +1,40 @@
+{
+  "id": "1e9",
+  "type": "environment",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/environments/1e9",
+    "account": "http://172.30.0.100:8080/v1/environments/1e9/account",
+    "services": "http://172.30.0.100:8080/v1/environments/1e9/services",
+    "composeConfig": "http://172.30.0.100:8080/v1/environments/1e9/composeconfig"
+  },
+  "actions": {
+    "upgrade": "http://172.30.0.100:8080/v1/environments/1e9/?action=upgrade",
+    "update": "http://172.30.0.100:8080/v1/environments/1e9/?action=update",
+    "remove": "http://172.30.0.100:8080/v1/environments/1e9/?action=remove",
+    "addoutputs": "http://172.30.0.100:8080/v1/environments/1e9/?action=addoutputs",
+    "activateservices": "http://172.30.0.100:8080/v1/environments/1e9/?action=activateservices",
+    "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e9/?action=deactivateservices",
+    "exportconfig": "http://172.30.0.100:8080/v1/environments/1e9/?action=exportconfig"
+  },
+  "name": "newstack",
+  "state": "active",
+  "accountId": "1a5",
+  "created": "2016-10-06T14:12:34Z",
+  "createdTS": 1475763154000,
+  "description": null,
+  "dockerCompose": null,
+  "environment": {"root_password": "password"},
+  "externalId": null,
+  "healthState": "healthy",
+  "kind": "environment",
+  "outputs": null,
+  "previousEnvironment": null,
+  "previousExternalId": null,
+  "rancherCompose": null,
+  "removed": null,
+  "startOnCreate": true,
+  "transitioning": "no",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "uuid": "7f8b1836-5619-4e19-adfe-6967fe55bda7"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_destroy_service.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_destroy_service.json b/libcloud/test/container/fixtures/rancher/ex_destroy_service.json
new file mode 100644
index 0000000..6af70ad
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_destroy_service.json
@@ -0,0 +1,66 @@
+{
+  "id": "1s13",
+  "type": "service",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/services/1s13",
+    "account": "http://172.30.0.100:8080/v1/services/1s13/account",
+    "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s13/consumedbyservices",
+    "consumedservices": "http://172.30.0.100:8080/v1/services/1s13/consumedservices",
+    "environment": "http://172.30.0.100:8080/v1/services/1s13/environment",
+    "instances": "http://172.30.0.100:8080/v1/services/1s13/instances",
+    "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s13/serviceexposemaps",
+    "containerStats": "http://172.30.0.100:8080/v1/services/1s13/containerstats"
+  },
+  "actions": {
+    "setservicelinks": "http://172.30.0.100:8080/v1/services/1s13/?action=setservicelinks",
+    "removeservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=removeservicelink",
+    "addservicelink": "http://172.30.0.100:8080/v1/services/1s13/?action=addservicelink"
+  },
+  "name": "newservice",
+  "state": "removing",
+  "accountId": "1a5",
+  "assignServiceIpAddress": false,
+  "createIndex": 1,
+  "created": "2016-10-06T15:31:35Z",
+  "createdTS": 1475767895000,
+  "currentScale": 1,
+  "description": null,
+  "environmentId": "1e6",
+  "externalId": null,
+  "fqdn": null,
+  "healthState": "unhealthy",
+  "kind": "service",
+  "launchConfig": {
+    "environment": {
+      "root_password": "password"
+    },
+    "imageUuid": "docker:rlister/hastebin:latest",
+    "kind": "container",
+    "networkMode": "managed",
+    "privileged": false,
+    "publishAllPorts": false,
+    "readOnly": false,
+    "startOnCreate": true,
+    "stdinOpen": false,
+    "tty": false,
+    "version": "0",
+    "vcpu": 1
+  },
+  "metadata": null,
+  "publicEndpoints": null,
+  "removed": "2016-10-06T15:45:03Z",
+  "removedTS": 1475768703000,
+  "retainIp": null,
+  "scale": 1,
+  "scalePolicy": null,
+  "secondaryLaunchConfigs": [],
+  "selectorContainer": null,
+  "selectorLink": null,
+  "startOnCreate": true,
+  "transitioning": "no",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "upgrade": null,
+  "uuid": "de2cd54f-9936-49fb-a41a-35653c4510f7",
+  "vip": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_destroy_stack.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_destroy_stack.json b/libcloud/test/container/fixtures/rancher/ex_destroy_stack.json
new file mode 100644
index 0000000..daef943
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_destroy_stack.json
@@ -0,0 +1,40 @@
+{
+  "id": "1e10",
+  "type": "environment",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/environments/1e10",
+    "account": "http://172.30.0.100:8080/v1/environments/1e10/account",
+    "services": "http://172.30.0.100:8080/v1/environments/1e10/services",
+    "composeConfig": "http://172.30.0.100:8080/v1/environments/1e10/composeconfig"
+  },
+  "actions": {
+    "addoutputs": "http://172.30.0.100:8080/v1/environments/1e10/?action=addoutputs",
+    "activateservices": "http://172.30.0.100:8080/v1/environments/1e10/?action=activateservices",
+    "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e10/?action=deactivateservices",
+    "exportconfig": "http://172.30.0.100:8080/v1/environments/1e10/?action=exportconfig"
+  },
+  "name": "newstack1",
+  "state": "removing",
+  "accountId": "1a5",
+  "created": "2016-10-06T14:15:41Z",
+  "createdTS": 1475763341000,
+  "description": null,
+  "dockerCompose": null,
+  "environment": {
+    "root_password": "password"
+  },
+  "externalId": null,
+  "healthState": "healthy",
+  "kind": "environment",
+  "outputs": null,
+  "previousEnvironment": null,
+  "previousExternalId": null,
+  "rancherCompose": null,
+  "removed": "2016-10-06T14:56:16Z",
+  "removedTS": 1475765776000,
+  "startOnCreate": true,
+  "transitioning": "no",
+  "transitioningMessage": null,
+  "transitioningProgress": null,
+  "uuid": "289f380f-d00a-4faf-b69f-53a559dbfd05"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_list_services.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_list_services.json b/libcloud/test/container/fixtures/rancher/ex_list_services.json
new file mode 100644
index 0000000..789bca8
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_list_services.json
@@ -0,0 +1,536 @@
+{
+  "type": "collection",
+  "resourceType": "service",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/services"
+  },
+  "createTypes": {
+    "dnsService": "http://172.30.0.100:8080/v1/dnsservices",
+    "externalService": "http://172.30.0.100:8080/v1/externalservices",
+    "loadBalancerService": "http://172.30.0.100:8080/v1/loadbalancerservices",
+    "service": "http://172.30.0.100:8080/v1/services"
+  },
+  "actions": {},
+  "data": [
+    {
+      "id": "1s1",
+      "type": "service",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/services/1s1",
+        "account": "http://172.30.0.100:8080/v1/services/1s1/account",
+        "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s1/consumedbyservices",
+        "consumedservices": "http://172.30.0.100:8080/v1/services/1s1/consumedservices",
+        "environment": "http://172.30.0.100:8080/v1/services/1s1/environment",
+        "instances": "http://172.30.0.100:8080/v1/services/1s1/instances",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s1/serviceexposemaps",
+        "containerStats": "http://172.30.0.100:8080/v1/services/1s1/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/services/1s1/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/services/1s1/?action=remove",
+        "setservicelinks": "http://172.30.0.100:8080/v1/services/1s1/?action=setservicelinks",
+        "removeservicelink": "http://172.30.0.100:8080/v1/services/1s1/?action=removeservicelink",
+        "activate": "http://172.30.0.100:8080/v1/services/1s1/?action=activate",
+        "upgrade": "http://172.30.0.100:8080/v1/services/1s1/?action=upgrade",
+        "addservicelink": "http://172.30.0.100:8080/v1/services/1s1/?action=addservicelink"
+      },
+      "name": "CMSMysql",
+      "state": "inactive",
+      "accountId": "1a5",
+      "assignServiceIpAddress": false,
+      "createIndex": 1,
+      "created": "2016-09-22T17:58:54Z",
+      "createdTS": 1474567134000,
+      "currentScale": 1,
+      "description": null,
+      "environmentId": "1e1",
+      "externalId": null,
+      "fqdn": null,
+      "healthState": "unhealthy",
+      "kind": "service",
+      "launchConfig": {
+        "dataVolumes": [
+          "CMS_DB_DATA:/var/lib/mysql"
+        ],
+        "environment": {
+          "MYSQL_DATABASE": "CMS_DB",
+          "MYSQL_PASSWORD": "password",
+          "MYSQL_ROOT_PASSWORD": "password",
+          "MYSQL_USER": "CMS_USER"
+        },
+        "imageUuid": "docker:mysql",
+        "kind": "container",
+        "labels": {
+          "io.rancher.container.pull_image": "always",
+          "io.rancher.service.hash": "c5d6bacef4be47a5ca5d1517a1d33319d024cdde"
+        },
+        "logConfig": {},
+        "networkMode": "managed",
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "startOnCreate": true,
+        "stdinOpen": true,
+        "tty": true,
+        "version": "0",
+        "vcpu": 1
+      },
+      "metadata": {
+        "io.rancher.service.hash": "41ccfd7f8023f2efcc758a925a9f461d607c990d"
+      },
+      "publicEndpoints": null,
+      "removed": null,
+      "retainIp": null,
+      "scale": 1,
+      "scalePolicy": null,
+      "secondaryLaunchConfigs": [],
+      "selectorContainer": null,
+      "selectorLink": null,
+      "startOnCreate": false,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "upgrade": null,
+      "uuid": "85f4e9fc-c311-45a0-9a1a-a9da229aaa2a",
+      "vip": null
+    },
+    {
+      "id": "1s2",
+      "type": "service",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/services/1s2",
+        "account": "http://172.30.0.100:8080/v1/services/1s2/account",
+        "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s2/consumedbyservices",
+        "consumedservices": "http://172.30.0.100:8080/v1/services/1s2/consumedservices",
+        "environment": "http://172.30.0.100:8080/v1/services/1s2/environment",
+        "instances": "http://172.30.0.100:8080/v1/services/1s2/instances",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s2/serviceexposemaps",
+        "containerStats": "http://172.30.0.100:8080/v1/services/1s2/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/services/1s2/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/services/1s2/?action=remove",
+        "setservicelinks": "http://172.30.0.100:8080/v1/services/1s2/?action=setservicelinks",
+        "removeservicelink": "http://172.30.0.100:8080/v1/services/1s2/?action=removeservicelink",
+        "activate": "http://172.30.0.100:8080/v1/services/1s2/?action=activate",
+        "upgrade": "http://172.30.0.100:8080/v1/services/1s2/?action=upgrade",
+        "addservicelink": "http://172.30.0.100:8080/v1/services/1s2/?action=addservicelink"
+      },
+      "name": "Concrete5App",
+      "state": "inactive",
+      "accountId": "1a5",
+      "assignServiceIpAddress": false,
+      "createIndex": 2,
+      "created": "2016-09-22T17:58:54Z",
+      "createdTS": 1474567134000,
+      "currentScale": 1,
+      "description": null,
+      "environmentId": "1e1",
+      "externalId": null,
+      "fqdn": null,
+      "healthState": "degraded",
+      "kind": "service",
+      "launchConfig": {
+        "dataVolumes": [
+          "CMS_APP_DATA:/var/www/html/application",
+          "CMS_PACK_DATA:/var/www/html/packages"
+        ],
+        "imageUuid": "docker:opensaas/concrete5",
+        "kind": "container",
+        "labels": {
+          "io.rancher.container.pull_image": "always",
+          "io.rancher.service.hash": "6033469e7596fd16896eb87b3a99f50af2dbf522",
+          "io.rancher.sidekicks": "CMSConfig"
+        },
+        "logConfig": {},
+        "networkMode": "managed",
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "startOnCreate": true,
+        "stdinOpen": true,
+        "tty": true,
+        "version": "0",
+        "vcpu": 1
+      },
+      "metadata": {
+        "io.rancher.service.hash": "037726f2f6d389022953a652a5d3e5775415d0b0"
+      },
+      "publicEndpoints": null,
+      "removed": null,
+      "retainIp": null,
+      "scale": 1,
+      "scalePolicy": null,
+      "secondaryLaunchConfigs": [
+        {
+          "command": [
+            "bash",
+            "-c",
+            "chown -R www-data. application; chown -R www-data. packages; sleep 2m; php -f concrete/bin/concrete5.php c5:install --db-server=mysql --db-username=CMS_USER --db-password=password --db-database=CMS_DB --site=MySite --admin-email=admin@example.com --admin-password=password -n -vvv"
+          ],
+          "dataVolumes": [
+            "CMS_APP_DATA:/var/www/html/application",
+            "CMS_PACK_DATA:/var/www/html/packages"
+          ],
+          "imageUuid": "docker:opensaas/concrete5",
+          "labels": {
+            "io.rancher.container.hostname_override": "container_name",
+            "io.rancher.container.start_once": "true",
+            "io.rancher.service.hash": "db08c70dbb11ff2955a5cac93c2c6e5e1ac95e7e"
+          },
+          "logConfig": {},
+          "name": "CMSConfig",
+          "networkMode": "managed",
+          "startOnCreate": true,
+          "stdinOpen": true,
+          "tty": true,
+          "kind": "container",
+          "privileged": false,
+          "publishAllPorts": false,
+          "readOnly": false,
+          "vcpu": 1,
+          "version": "0"
+        }
+      ],
+      "selectorContainer": null,
+      "selectorLink": null,
+      "startOnCreate": false,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "upgrade": null,
+      "uuid": "1d824bd6-e18b-4ac4-8ea1-5cd0a3c7e234",
+      "vip": null
+    },
+    {
+      "id": "1s3",
+      "type": "service",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/services/1s3",
+        "account": "http://172.30.0.100:8080/v1/services/1s3/account",
+        "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s3/consumedbyservices",
+        "consumedservices": "http://172.30.0.100:8080/v1/services/1s3/consumedservices",
+        "environment": "http://172.30.0.100:8080/v1/services/1s3/environment",
+        "instances": "http://172.30.0.100:8080/v1/services/1s3/instances",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s3/serviceexposemaps",
+        "containerStats": "http://172.30.0.100:8080/v1/services/1s3/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/services/1s3/?action=update",
+        "restart": "http://172.30.0.100:8080/v1/services/1s3/?action=restart",
+        "remove": "http://172.30.0.100:8080/v1/services/1s3/?action=remove",
+        "setservicelinks": "http://172.30.0.100:8080/v1/services/1s3/?action=setservicelinks",
+        "removeservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=removeservicelink",
+        "upgrade": "http://172.30.0.100:8080/v1/services/1s3/?action=upgrade",
+        "addservicelink": "http://172.30.0.100:8080/v1/services/1s3/?action=addservicelink",
+        "deactivate": "http://172.30.0.100:8080/v1/services/1s3/?action=deactivate"
+      },
+      "name": "ghost",
+      "state": "active",
+      "accountId": "1a5",
+      "assignServiceIpAddress": false,
+      "createIndex": 1,
+      "created": "2016-09-22T18:00:26Z",
+      "createdTS": 1474567226000,
+      "currentScale": 1,
+      "description": null,
+      "environmentId": "1e2",
+      "externalId": null,
+      "fqdn": null,
+      "healthState": "healthy",
+      "kind": "service",
+      "launchConfig": {
+        "imageUuid": "docker:ghost",
+        "kind": "container",
+        "labels": {
+          "io.rancher.service.hash": "af9b5ddd2891271b12a88129e2bc37ff57998182"
+        },
+        "logConfig": {},
+        "networkMode": "managed",
+        "ports": [
+          "80:2368/tcp"
+        ],
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "startOnCreate": true,
+        "stdinOpen": false,
+        "tty": false,
+        "version": "0",
+        "vcpu": 1
+      },
+      "metadata": {
+        "io.rancher.service.hash": "f49280e1f709117b76693b638834791e4f4ef0fd"
+      },
+      "publicEndpoints": [
+        {
+          "ipAddress": "172.30.0.101",
+          "port": 80,
+          "serviceId": "1s3",
+          "hostId": "1h1",
+          "instanceId": "1i5"
+        }
+      ],
+      "removed": null,
+      "retainIp": null,
+      "scale": 1,
+      "scalePolicy": null,
+      "secondaryLaunchConfigs": [],
+      "selectorContainer": null,
+      "selectorLink": null,
+      "startOnCreate": false,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "upgrade": null,
+      "uuid": "c2ce7050-e5b5-42c7-a9fb-8ed8d33a4884",
+      "vip": null
+    },
+    {
+      "id": "1s6",
+      "type": "service",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/services/1s6",
+        "account": "http://172.30.0.100:8080/v1/services/1s6/account",
+        "consumedbyservices": "http://172.30.0.100:8080/v1/services/1s6/consumedbyservices",
+        "consumedservices": "http://172.30.0.100:8080/v1/services/1s6/consumedservices",
+        "environment": "http://172.30.0.100:8080/v1/services/1s6/environment",
+        "instances": "http://172.30.0.100:8080/v1/services/1s6/instances",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/services/1s6/serviceexposemaps",
+        "containerStats": "http://172.30.0.100:8080/v1/services/1s6/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/services/1s6/?action=update",
+        "restart": "http://172.30.0.100:8080/v1/services/1s6/?action=restart",
+        "remove": "http://172.30.0.100:8080/v1/services/1s6/?action=remove",
+        "setservicelinks": "http://172.30.0.100:8080/v1/services/1s6/?action=setservicelinks",
+        "removeservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=removeservicelink",
+        "upgrade": "http://172.30.0.100:8080/v1/services/1s6/?action=upgrade",
+        "addservicelink": "http://172.30.0.100:8080/v1/services/1s6/?action=addservicelink",
+        "deactivate": "http://172.30.0.100:8080/v1/services/1s6/?action=deactivate"
+      },
+      "name": "123",
+      "state": "active",
+      "accountId": "1a5",
+      "assignServiceIpAddress": false,
+      "createIndex": 1,
+      "created": "2016-09-22T18:28:04Z",
+      "createdTS": 1474568884000,
+      "currentScale": 1,
+      "description": null,
+      "environmentId": "1e2",
+      "externalId": null,
+      "fqdn": null,
+      "healthState": "healthy",
+      "kind": "service",
+      "launchConfig": {
+        "capAdd": [],
+        "capDrop": [],
+        "count": null,
+        "cpuSet": null,
+        "cpuShares": null,
+        "dataVolumes": [],
+        "dataVolumesFrom": [],
+        "description": null,
+        "devices": [],
+        "dns": [],
+        "dnsSearch": [],
+        "domainName": null,
+        "hostname": null,
+        "imageUuid": "docker:ubuntu:trusty",
+        "kind": "container",
+        "labels": {
+          "io.rancher.container.pull_image": "always"
+        },
+        "logConfig": {
+          "config": {},
+          "driver": ""
+        },
+        "memory": null,
+        "memoryMb": null,
+        "memorySwap": null,
+        "networkMode": "managed",
+        "pidMode": null,
+        "ports": [],
+        "privileged": false,
+        "publishAllPorts": false,
+        "readOnly": false,
+        "requestedIpAddress": null,
+        "startOnCreate": true,
+        "stdinOpen": true,
+        "tty": true,
+        "user": null,
+        "userdata": null,
+        "version": "0bdea468-c3e9-4562-951c-d543958e966a",
+        "volumeDriver": null,
+        "workingDir": null,
+        "dataVolumesFromLaunchConfigs": [],
+        "networkLaunchConfig": null,
+        "vcpu": 1
+      },
+      "metadata": null,
+      "publicEndpoints": null,
+      "removed": null,
+      "retainIp": null,
+      "scale": 1,
+      "scalePolicy": null,
+      "secondaryLaunchConfigs": [],
+      "selectorContainer": null,
+      "selectorLink": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "upgrade": {
+        "inServiceStrategy": {
+          "batchSize": 1,
+          "intervalMillis": 2000,
+          "launchConfig": {
+            "capAdd": [],
+            "capDrop": [],
+            "count": null,
+            "cpuSet": null,
+            "cpuShares": null,
+            "dataVolumes": [],
+            "dataVolumesFrom": [],
+            "description": null,
+            "devices": [],
+            "dns": [],
+            "dnsSearch": [],
+            "domainName": null,
+            "hostname": null,
+            "imageUuid": "docker:ubuntu:trusty",
+            "kind": "container",
+            "labels": {
+              "io.rancher.container.pull_image": "always"
+            },
+            "logConfig": {
+              "config": {},
+              "driver": ""
+            },
+            "memory": null,
+            "memoryMb": null,
+            "memorySwap": null,
+            "networkMode": "managed",
+            "pidMode": null,
+            "ports": [],
+            "privileged": false,
+            "publishAllPorts": false,
+            "readOnly": false,
+            "requestedIpAddress": null,
+            "startOnCreate": true,
+            "stdinOpen": true,
+            "tty": true,
+            "user": null,
+            "userdata": null,
+            "version": "0bdea468-c3e9-4562-951c-d543958e966a",
+            "volumeDriver": null,
+            "workingDir": null,
+            "dataVolumesFromLaunchConfigs": [],
+            "networkLaunchConfig": null,
+            "vcpu": 1
+          },
+          "previousLaunchConfig": {
+            "capAdd": [],
+            "capDrop": [],
+            "count": null,
+            "cpuSet": null,
+            "cpuShares": null,
+            "dataVolumes": [],
+            "dataVolumesFrom": [],
+            "description": null,
+            "devices": [],
+            "dns": [],
+            "dnsSearch": [],
+            "domainName": null,
+            "hostname": null,
+            "imageUuid": "docker:ubuntu:trusty",
+            "kind": "container",
+            "labels": {
+              "io.rancher.container.pull_image": "always"
+            },
+            "logConfig": {
+              "config": {},
+              "driver": ""
+            },
+            "memory": null,
+            "memoryMb": null,
+            "memorySwap": null,
+            "networkMode": "managed",
+            "pidMode": null,
+            "ports": [],
+            "privileged": false,
+            "publishAllPorts": false,
+            "readOnly": false,
+            "requestedIpAddress": null,
+            "startOnCreate": true,
+            "stdinOpen": true,
+            "tty": true,
+            "user": null,
+            "userdata": null,
+            "version": "0",
+            "volumeDriver": null,
+            "workingDir": null,
+            "dataVolumesFromLaunchConfigs": [],
+            "networkLaunchConfig": null,
+            "vcpu": 1
+          },
+          "previousSecondaryLaunchConfigs": [],
+          "secondaryLaunchConfigs": [],
+          "startFirst": true
+        },
+        "toServiceStrategy": null
+      },
+      "uuid": "c0ae4d08-e20a-45ef-9fb9-ad9f7cdeeb15",
+      "vip": null
+    }
+  ],
+  "sortLinks": {
+    "accountId": "http://172.30.0.100:8080/v1/services?limit=4&sort=accountId",
+    "createIndex": "http://172.30.0.100:8080/v1/services?limit=4&sort=createIndex",
+    "created": "http://172.30.0.100:8080/v1/services?limit=4&sort=created",
+    "description": "http://172.30.0.100:8080/v1/services?limit=4&sort=description",
+    "environmentId": "http://172.30.0.100:8080/v1/services?limit=4&sort=environmentId",
+    "externalId": "http://172.30.0.100:8080/v1/services?limit=4&sort=externalId",
+    "healthState": "http://172.30.0.100:8080/v1/services?limit=4&sort=healthState",
+    "id": "http://172.30.0.100:8080/v1/services?limit=4&sort=id",
+    "kind": "http://172.30.0.100:8080/v1/services?limit=4&sort=kind",
+    "name": "http://172.30.0.100:8080/v1/services?limit=4&sort=name",
+    "removeTime": "http://172.30.0.100:8080/v1/services?limit=4&sort=removeTime",
+    "removed": "http://172.30.0.100:8080/v1/services?limit=4&sort=removed",
+    "selectorContainer": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorContainer",
+    "selectorLink": "http://172.30.0.100:8080/v1/services?limit=4&sort=selectorLink",
+    "state": "http://172.30.0.100:8080/v1/services?limit=4&sort=state",
+    "uuid": "http://172.30.0.100:8080/v1/services?limit=4&sort=uuid",
+    "vip": "http://172.30.0.100:8080/v1/services?limit=4&sort=vip"
+  },
+  "pagination": {
+    "first": null,
+    "previous": null,
+    "next": "http://172.30.0.100:8080/v1/services?limit=4&marker=m4",
+    "limit": 4,
+    "total": null,
+    "partial": true
+  },
+  "sort": null,
+  "filters": {
+    "accountId": null,
+    "createIndex": null,
+    "created": null,
+    "description": null,
+    "environmentId": null,
+    "externalId": null,
+    "healthState": null,
+    "id": null,
+    "kind": null,
+    "name": null,
+    "removeTime": null,
+    "removed": null,
+    "selectorContainer": null,
+    "selectorLink": null,
+    "state": null,
+    "uuid": null,
+    "vip": null
+  },
+  "createDefaults": {}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_list_stacks.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_list_stacks.json b/libcloud/test/container/fixtures/rancher/ex_list_stacks.json
new file mode 100644
index 0000000..d2d1c3c
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_list_stacks.json
@@ -0,0 +1,310 @@
+{
+  "type": "collection",
+  "resourceType": "environment",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/environments"
+  },
+  "createTypes": {
+    "composeProject": "http://172.30.0.100:8080/v1/composeprojects",
+    "environment": "http://172.30.0.100:8080/v1/environments"
+  },
+  "actions": {},
+  "data": [
+    {
+      "id": "1e1",
+      "type": "environment",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/environments/1e1",
+        "account": "http://172.30.0.100:8080/v1/environments/1e1/account",
+        "services": "http://172.30.0.100:8080/v1/environments/1e1/services",
+        "composeConfig": "http://172.30.0.100:8080/v1/environments/1e1/composeconfig"
+      },
+      "actions": {
+        "upgrade": "http://172.30.0.100:8080/v1/environments/1e1/?action=upgrade",
+        "update": "http://172.30.0.100:8080/v1/environments/1e1/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/environments/1e1/?action=remove",
+        "addoutputs": "http://172.30.0.100:8080/v1/environments/1e1/?action=addoutputs",
+        "activateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=activateservices",
+        "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e1/?action=deactivateservices",
+        "exportconfig": "http://172.30.0.100:8080/v1/environments/1e1/?action=exportconfig"
+      },
+      "name": "Concrete5",
+      "state": "active",
+      "accountId": "1a5",
+      "created": "2016-09-22T17:58:53Z",
+      "createdTS": 1474567133000,
+      "description": null,
+      "dockerCompose": "CMSMysql:\r\n    environment:\r\n        MYSQL_ROOT_PASSWORD: ${root_password}\r\n        MYSQL_DATABASE: ${db_name}\r\n        MYSQL_USER: ${db_username}\r\n        MYSQL_PASSWORD: ${db_password}\r\n    labels:\r\n        io.rancher.container.pull_image: always\r\n    tty: true\r\n    image: mysql\r\n    volumes:\r\n    - ${db_data_location}:/var/lib/mysql\r\n    stdin_open: true\r\n    volume_driver: ${volume_driver}\r\n\r\nCMSConfig:\r\n    image: opensaas/concrete5\r\n    tty: true\r\n    stdin_open: true\r\n    links:\r\n    - CMSMysql:mysql\r\n    volumes:\r\n    - ${cms_application_data}:/var/www/html/application\r\n    - ${cms_packages_data}:/var/www/html/packages\r\n    labels:\r\n        io.rancher.container.hostname_override: container_name\r\n        io.rancher.container.start_once: true\r\n    volume_driver: ${volume_driver}\r\n    command: bash -c \"chown -R www-data. application; chown -R www-data. packages; sleep 2m; php -f concrete/bin/concre
 te5.php c5:install --db-server=mysql --db-username=${db_username} --db-password=${db_password} --db-database=${db_name} --site=${cms_sitename} --admin-email=${cms_admin_email} --admin-password=${cms_admin_password} -n -vvv\"\r\n\r\nConcrete5App:\r\n    labels:\r\n        io.rancher.container.pull_image: always\r\n        io.rancher.sidekicks: CMSConfig\r\n    tty: true\r\n    links:\r\n    - CMSMysql:mysql\r\n    image: opensaas/concrete5\r\n    volumes:\r\n    - ${cms_application_data}:/var/www/html/application\r\n    - ${cms_packages_data}:/var/www/html/packages\r\n    volume_driver: ${volume_driver}\r\n    stdin_open: true",
+      "environment": {
+        "root_password": "password",
+        "db_name": "CMS_DB",
+        "db_username": "CMS_USER",
+        "db_password": "password",
+        "db_data_location": "CMS_DB_DATA",
+        "volume_driver": "",
+        "cms_application_data": "CMS_APP_DATA",
+        "cms_packages_data": "CMS_PACK_DATA",
+        "cms_admin_email": "admin@example.com",
+        "cms_admin_password": "password",
+        "cms_sitename": "MySite"
+      },
+      "externalId": "catalog://community:Concrete5:1",
+      "healthState": "healthy",
+      "kind": "environment",
+      "outputs": null,
+      "previousEnvironment": null,
+      "previousExternalId": null,
+      "rancherCompose": ".catalog:\r\n    name: \"Concrete5\"\r\n    version: \"v0.2\"\r\n    description: \"Concrete5 CMS\"\r\n    uuid: Concrete5-1\r\n    minimum_rancher_version: v0.51.0\r\n    questions:\r\n        - variable: root_password\r\n          description: \"MySQL root password - keep this password complex and secure\"\r\n          label: \"MySQL Root Password\"\r\n          required: true\r\n          default: \"password\"\r\n          type: \"string\"\r\n        - variable: db_name\r\n          description: \"MySQL Database Name - to use in the Concrete5 setup\"\r\n          label: \"MySQL Database Name\"\r\n          required: true\r\n          default: \"CMS_DB\"\r\n          type: \"string\"\r\n        - variable: db_username\r\n          description: \"MySQL Username - to use in the Concrete5 setup\"\r\n          label: \"MySQL Username\"\r\n          required: true\r\n          default: \"CMS_USER\"\r\n          type: \"string\"\r\n        - variable: db_passwor
 d\r\n          description: \"MySQL password for the above user - to use in the Concrete5 setup\"\r\n          label: \"MySQL Password\"\r\n          required: true\r\n          default: \"password\"\r\n          type: \"string\"\r\n        - variable: db_data_location\r\n          description: \"Location on the host for the database files\"\r\n          label: \"DB Data Location\"\r\n          required: true\r\n          default: \"CMS_DB_DATA\"\r\n          type: \"string\"\r\n        - variable: volume_driver\r\n          description: \"Volume Driver for the persistant data locations requires docker 1.7\"\r\n          label: \"Volume Driver\"\r\n          type: \"string\"\r\n        - variable: cms_application_data\r\n          description: \"Concrcte5 application folder for persistant data storage\"\r\n          label: \"Application Folder\"\r\n          required: true\r\n          default: \"CMS_APP_DATA\"\r\n          type: \"string\"\r\n        - variable: cms_packages_data\r
 \n          description: \"Concrcte5 packages folder for persistant data storage\"\r\n          label: \"Packages Folder\"\r\n          required: true\r\n          default: \"CMS_PACK_DATA\"\r\n          type: \"string\"\r\n        - variable: cms_admin_email\r\n          description: \"Concrcete5 admin email address\"\r\n          label: \"Admin Email\"\r\n          required: true\r\n          default: \"admin@example.com\"\r\n          type: \"string\"\r\n        - variable: cms_admin_password\r\n          description: \"Concrcete5 admin password\"\r\n          label: \"Admin Password\"\r\n          required: true\r\n          default: \"password\"\r\n          type: \"string\"\r\n        - variable: cms_sitename\r\n          description: \"Concrcete5 Sitename\"\r\n          label: \"Sitename\"\r\n          required: true\r\n          default: \"MySite\"\r\n          type: \"string\"\r\nCMSMysql:\r\n    scale: 1\r\nConcrete5App:\r\n    scale: 1\r\n\r\n",
+      "removed": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "uuid": "e129ed27-3823-4e2e-af62-4565d68995d4"
+    },
+    {
+      "id": "1e2",
+      "type": "environment",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/environments/1e2",
+        "account": "http://172.30.0.100:8080/v1/environments/1e2/account",
+        "services": "http://172.30.0.100:8080/v1/environments/1e2/services",
+        "composeConfig": "http://172.30.0.100:8080/v1/environments/1e2/composeconfig"
+      },
+      "actions": {
+        "upgrade": "http://172.30.0.100:8080/v1/environments/1e2/?action=upgrade",
+        "update": "http://172.30.0.100:8080/v1/environments/1e2/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/environments/1e2/?action=remove",
+        "addoutputs": "http://172.30.0.100:8080/v1/environments/1e2/?action=addoutputs",
+        "activateservices": "http://172.30.0.100:8080/v1/environments/1e2/?action=activateservices",
+        "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e2/?action=deactivateservices",
+        "exportconfig": "http://172.30.0.100:8080/v1/environments/1e2/?action=exportconfig"
+      },
+      "name": "ghost",
+      "state": "active",
+      "accountId": "1a5",
+      "created": "2016-09-22T18:00:25Z",
+      "createdTS": 1474567225000,
+      "description": null,
+      "dockerCompose": "ghost:\n  image: ghost\n  ports:\n    - ${public_port}:2368\n",
+      "environment": {
+        "public_port": "80"
+      },
+      "externalId": "catalog://community:ghost:0",
+      "healthState": "healthy",
+      "kind": "environment",
+      "outputs": null,
+      "previousEnvironment": null,
+      "previousExternalId": null,
+      "rancherCompose": ".catalog:\n  name: \"Ghost\"\n  version: \"v0.1-educaas\"\n  description: \"Blog powered by Ghost. Requires no database\"\n  uuid: ghost-0\n  minimum_rancher_version: v0.51.0\n  questions:\n    - variable: public_port\n      description: \"public port to access the blog\"\n      label: \"Public Port\"\n      required: true\n      default: \"80\"\n      type: \"int\"\nghost:\n",
+      "removed": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "uuid": "4c335202-2ca7-41f1-8702-4984518566ec"
+    },
+    {
+      "id": "1e5",
+      "type": "environment",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/environments/1e5",
+        "account": "http://172.30.0.100:8080/v1/environments/1e5/account",
+        "services": "http://172.30.0.100:8080/v1/environments/1e5/services",
+        "composeConfig": "http://172.30.0.100:8080/v1/environments/1e5/composeconfig"
+      },
+      "actions": {
+        "upgrade": "http://172.30.0.100:8080/v1/environments/1e5/?action=upgrade",
+        "update": "http://172.30.0.100:8080/v1/environments/1e5/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/environments/1e5/?action=remove",
+        "addoutputs": "http://172.30.0.100:8080/v1/environments/1e5/?action=addoutputs",
+        "activateservices": "http://172.30.0.100:8080/v1/environments/1e5/?action=activateservices",
+        "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e5/?action=deactivateservices",
+        "exportconfig": "http://172.30.0.100:8080/v1/environments/1e5/?action=exportconfig"
+      },
+      "name": "heyk",
+      "state": "active",
+      "accountId": "1a5",
+      "created": "2016-09-29T20:40:14Z",
+      "createdTS": 1475181614000,
+      "description": null,
+      "dockerCompose": null,
+      "environment": null,
+      "externalId": null,
+      "healthState": "healthy",
+      "kind": "environment",
+      "outputs": null,
+      "previousEnvironment": null,
+      "previousExternalId": null,
+      "rancherCompose": null,
+      "removed": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "uuid": "d5a39304-9247-4a31-8662-7dba98238105"
+    },
+    {
+      "id": "1e6",
+      "type": "environment",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/environments/1e6",
+        "account": "http://172.30.0.100:8080/v1/environments/1e6/account",
+        "services": "http://172.30.0.100:8080/v1/environments/1e6/services",
+        "composeConfig": "http://172.30.0.100:8080/v1/environments/1e6/composeconfig"
+      },
+      "actions": {
+        "upgrade": "http://172.30.0.100:8080/v1/environments/1e6/?action=upgrade",
+        "update": "http://172.30.0.100:8080/v1/environments/1e6/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/environments/1e6/?action=remove",
+        "addoutputs": "http://172.30.0.100:8080/v1/environments/1e6/?action=addoutputs",
+        "activateservices": "http://172.30.0.100:8080/v1/environments/1e6/?action=activateservices",
+        "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e6/?action=deactivateservices",
+        "exportconfig": "http://172.30.0.100:8080/v1/environments/1e6/?action=exportconfig"
+      },
+      "name": "ilikegurls",
+      "state": "active",
+      "accountId": "1a5",
+      "created": "2016-10-06T00:40:23Z",
+      "createdTS": 1475714423000,
+      "description": null,
+      "dockerCompose": null,
+      "environment": null,
+      "externalId": null,
+      "healthState": "healthy",
+      "kind": "environment",
+      "outputs": null,
+      "previousEnvironment": null,
+      "previousExternalId": null,
+      "rancherCompose": null,
+      "removed": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "uuid": "19101511-6dcb-49f7-a8e1-063bcded1956"
+    },
+    {
+      "id": "1e7",
+      "type": "environment",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/environments/1e7",
+        "account": "http://172.30.0.100:8080/v1/environments/1e7/account",
+        "services": "http://172.30.0.100:8080/v1/environments/1e7/services",
+        "composeConfig": "http://172.30.0.100:8080/v1/environments/1e7/composeconfig"
+      },
+      "actions": {
+        "upgrade": "http://172.30.0.100:8080/v1/environments/1e7/?action=upgrade",
+        "update": "http://172.30.0.100:8080/v1/environments/1e7/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/environments/1e7/?action=remove",
+        "addoutputs": "http://172.30.0.100:8080/v1/environments/1e7/?action=addoutputs",
+        "activateservices": "http://172.30.0.100:8080/v1/environments/1e7/?action=activateservices",
+        "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e7/?action=deactivateservices",
+        "exportconfig": "http://172.30.0.100:8080/v1/environments/1e7/?action=exportconfig"
+      },
+      "name": "maybethisyear",
+      "state": "active",
+      "accountId": "1a5",
+      "created": "2016-10-06T00:41:17Z",
+      "createdTS": 1475714477000,
+      "description": null,
+      "dockerCompose": null,
+      "environment": null,
+      "externalId": null,
+      "healthState": "healthy",
+      "kind": "environment",
+      "outputs": null,
+      "previousEnvironment": null,
+      "previousExternalId": null,
+      "rancherCompose": null,
+      "removed": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "uuid": "250c66f6-cd36-4c12-8767-deb5c35d0a05"
+    },
+    {
+      "id": "1e8",
+      "type": "environment",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/environments/1e8",
+        "account": "http://172.30.0.100:8080/v1/environments/1e8/account",
+        "services": "http://172.30.0.100:8080/v1/environments/1e8/services",
+        "composeConfig": "http://172.30.0.100:8080/v1/environments/1e8/composeconfig"
+      },
+      "actions": {
+        "upgrade": "http://172.30.0.100:8080/v1/environments/1e8/?action=upgrade",
+        "update": "http://172.30.0.100:8080/v1/environments/1e8/?action=update",
+        "remove": "http://172.30.0.100:8080/v1/environments/1e8/?action=remove",
+        "addoutputs": "http://172.30.0.100:8080/v1/environments/1e8/?action=addoutputs",
+        "activateservices": "http://172.30.0.100:8080/v1/environments/1e8/?action=activateservices",
+        "deactivateservices": "http://172.30.0.100:8080/v1/environments/1e8/?action=deactivateservices",
+        "exportconfig": "http://172.30.0.100:8080/v1/environments/1e8/?action=exportconfig"
+      },
+      "name": "oh-another",
+      "state": "active",
+      "accountId": "1a5",
+      "created": "2016-10-06T00:51:34Z",
+      "createdTS": 1475715094000,
+      "description": null,
+      "dockerCompose": null,
+      "environment": null,
+      "externalId": null,
+      "healthState": "healthy",
+      "kind": "environment",
+      "outputs": null,
+      "previousEnvironment": null,
+      "previousExternalId": null,
+      "rancherCompose": null,
+      "removed": null,
+      "startOnCreate": true,
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "uuid": "a777dd5e-e524-43c8-8783-d7bb14bcffb6"
+    }
+  ],
+  "sortLinks": {
+    "accountId": "http://172.30.0.100:8080/v1/environments?limit=6&sort=accountId",
+    "created": "http://172.30.0.100:8080/v1/environments?limit=6&sort=created",
+    "description": "http://172.30.0.100:8080/v1/environments?limit=6&sort=description",
+    "externalId": "http://172.30.0.100:8080/v1/environments?limit=6&sort=externalId",
+    "healthState": "http://172.30.0.100:8080/v1/environments?limit=6&sort=healthState",
+    "id": "http://172.30.0.100:8080/v1/environments?limit=6&sort=id",
+    "kind": "http://172.30.0.100:8080/v1/environments?limit=6&sort=kind",
+    "name": "http://172.30.0.100:8080/v1/environments?limit=6&sort=name",
+    "removeTime": "http://172.30.0.100:8080/v1/environments?limit=6&sort=removeTime",
+    "removed": "http://172.30.0.100:8080/v1/environments?limit=6&sort=removed",
+    "state": "http://172.30.0.100:8080/v1/environments?limit=6&sort=state",
+    "uuid": "http://172.30.0.100:8080/v1/environments?limit=6&sort=uuid"
+  },
+  "pagination": {
+    "first": null,
+    "previous": null,
+    "next": "http://172.30.0.100:8080/v1/environments?limit=6&marker=m6",
+    "limit": 6,
+    "total": null,
+    "partial": true
+  },
+  "sort": null,
+  "filters": {
+    "accountId": null,
+    "created": null,
+    "description": null,
+    "externalId": null,
+    "healthState": [
+      {
+        "modifier": "eq",
+        "value": "healthy"
+      }
+    ],    "id": null,
+    "kind": null,
+    "name": null,
+    "removeTime": null,
+    "removed": null,
+    "state": null,
+    "uuid": null
+  },
+  "createDefaults": {}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d179167a/libcloud/test/container/fixtures/rancher/ex_search_containers.json
----------------------------------------------------------------------
diff --git a/libcloud/test/container/fixtures/rancher/ex_search_containers.json b/libcloud/test/container/fixtures/rancher/ex_search_containers.json
new file mode 100644
index 0000000..8cd0565
--- /dev/null
+++ b/libcloud/test/container/fixtures/rancher/ex_search_containers.json
@@ -0,0 +1,212 @@
+{
+  "type": "collection",
+  "resourceType": "container",
+  "links": {
+    "self": "http://172.30.0.100:8080/v1/containers"
+  },
+  "createTypes": {
+    "container": "http://172.30.0.100:8080/v1/containers",
+    "launchConfig": "http://172.30.0.100:8080/v1/launchconfigs",
+    "virtualMachine": "http://172.30.0.100:8080/v1/virtualmachines"
+  },
+  "actions": {},
+  "data": [
+    {
+      "id": "1i2",
+      "type": "container",
+      "links": {
+        "self": "http://172.30.0.100:8080/v1/containers/1i2",
+        "account": "http://172.30.0.100:8080/v1/containers/1i2/account",
+        "credentials": "http://172.30.0.100:8080/v1/containers/1i2/credentials",
+        "healthcheckInstanceHostMaps": "http://172.30.0.100:8080/v1/containers/1i2/healthcheckinstancehostmaps",
+        "hosts": "http://172.30.0.100:8080/v1/containers/1i2/hosts",
+        "instanceLabels": "http://172.30.0.100:8080/v1/containers/1i2/instancelabels",
+        "instanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/instancelinks",
+        "instances": "http://172.30.0.100:8080/v1/containers/1i2/instances",
+        "mounts": "http://172.30.0.100:8080/v1/containers/1i2/mounts",
+        "ports": "http://172.30.0.100:8080/v1/containers/1i2/ports",
+        "serviceEvents": "http://172.30.0.100:8080/v1/containers/1i2/serviceevents",
+        "serviceExposeMaps": "http://172.30.0.100:8080/v1/containers/1i2/serviceexposemaps",
+        "services": "http://172.30.0.100:8080/v1/containers/1i2/services",
+        "targetInstanceLinks": "http://172.30.0.100:8080/v1/containers/1i2/targetinstancelinks",
+        "volumes": "http://172.30.0.100:8080/v1/containers/1i2/volumes",
+        "stats": "http://172.30.0.100:8080/v1/containers/1i2/stats",
+        "containerStats": "http://172.30.0.100:8080/v1/containers/1i2/containerstats"
+      },
+      "actions": {
+        "update": "http://172.30.0.100:8080/v1/containers/1i2/?action=update",
+        "stop": "http://172.30.0.100:8080/v1/containers/1i2/?action=stop",
+        "restart": "http://172.30.0.100:8080/v1/containers/1i2/?action=restart",
+        "migrate": "http://172.30.0.100:8080/v1/containers/1i2/?action=migrate",
+        "logs": "http://172.30.0.100:8080/v1/containers/1i2/?action=logs",
+        "setlabels": "http://172.30.0.100:8080/v1/containers/1i2/?action=setlabels",
+        "execute": "http://172.30.0.100:8080/v1/containers/1i2/?action=execute",
+        "proxy": "http://172.30.0.100:8080/v1/containers/1i2/?action=proxy"
+      },
+      "name": "Network Agent",
+      "state": "running",
+      "accountId": "1a5",
+      "blkioDeviceOptions": null,
+      "build": null,
+      "capAdd": null,
+      "capDrop": null,
+      "command": null,
+      "cpuSet": null,
+      "cpuShares": null,
+      "createIndex": null,
+      "created": "2016-09-22T17:58:57Z",
+      "createdTS": 1474567137000,
+      "dataVolumeMounts": {},
+      "dataVolumes": [
+        "/var/lib/rancher/etc:/var/lib/rancher/etc:ro"
+      ],
+      "dataVolumesFrom": null,
+      "deploymentUnitUuid": null,
+      "description": null,
+      "devices": null,
+      "dns": null,
+      "dnsSearch": null,
+      "domainName": null,
+      "entryPoint": null,
+      "environment": null,
+      "expose": null,
+      "externalId": "129c67adc9fa084fbc8e1f963db0180896b88af3dca69c7e8fe0493284e4651c",
+      "extraHosts": null,
+      "firstRunning": "2016-09-22T17:59:11Z",
+      "firstRunningTS": 1474567151000,
+      "healthCheck": null,
+      "healthState": null,
+      "hostId": "1h1",
+      "hostname": null,
+      "imageUuid": "docker:rancher/agent-instance:v0.8.3",
+      "kind": "container",
+      "labels": {
+        "io.rancher.container.system": "NetworkAgent",
+        "io.rancher.container.uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb",
+        "io.rancher.container.name": "Network Agent",
+        "io.rancher.container.agent_id": "2",
+        "io.rancher.container.ip": "10.42.247.188/16"
+      },
+      "logConfig": null,
+      "lxcConf": null,
+      "memory": null,
+      "memorySwap": null,
+      "nativeContainer": false,
+      "networkContainerId": null,
+      "networkIds": [],
+      "networkMode": null,
+      "pidMode": null,
+      "ports": null,
+      "primaryIpAddress": "10.42.247.188",
+      "privileged": true,
+      "publishAllPorts": false,
+      "readOnly": false,
+      "registryCredentialId": null,
+      "removed": null,
+      "requestedHostId": null,
+      "restartPolicy": null,
+      "securityOpt": null,
+      "startCount": 3,
+      "startOnCreate": true,
+      "stdinOpen": false,
+      "systemContainer": "NetworkAgent",
+      "transitioning": "no",
+      "transitioningMessage": null,
+      "transitioningProgress": null,
+      "tty": false,
+      "user": null,
+      "uuid": "b0f88089-d28b-4388-93a7-889b750cd7cb",
+      "version": "0",
+      "volumeDriver": null,
+      "workingDir": null
+    }
+  ],
+  "sortLinks": {
+    "accountId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=accountId",
+    "agentId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=agentId",
+    "allocationState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=allocationState",
+    "compute": "http://172.30.0.100:8080/v1/containers?limit=2&sort=compute",
+    "createIndex": "http://172.30.0.100:8080/v1/containers?limit=2&sort=createIndex",
+    "created": "http://172.30.0.100:8080/v1/containers?limit=2&sort=created",
+    "deploymentUnitUuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=deploymentUnitUuid",
+    "description": "http://172.30.0.100:8080/v1/containers?limit=2&sort=description",
+    "dnsInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsInternal",
+    "dnsSearchInternal": "http://172.30.0.100:8080/v1/containers?limit=2&sort=dnsSearchInternal",
+    "domain": "http://172.30.0.100:8080/v1/containers?limit=2&sort=domain",
+    "externalId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=externalId",
+    "firstRunning": "http://172.30.0.100:8080/v1/containers?limit=2&sort=firstRunning",
+    "healthState": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthState",
+    "healthUpdated": "http://172.30.0.100:8080/v1/containers?limit=2&sort=healthUpdated",
+    "hostname": "http://172.30.0.100:8080/v1/containers?limit=2&sort=hostname",
+    "id": "http://172.30.0.100:8080/v1/containers?limit=2&sort=id",
+    "imageId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=imageId",
+    "instanceTriggeredStop": "http://172.30.0.100:8080/v1/containers?limit=2&sort=instanceTriggeredStop",
+    "kind": "http://172.30.0.100:8080/v1/containers?limit=2&sort=kind",
+    "memoryMb": "http://172.30.0.100:8080/v1/containers?limit=2&sort=memoryMb",
+    "name": "http://172.30.0.100:8080/v1/containers?limit=2&sort=name",
+    "nativeContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=nativeContainer",
+    "networkContainerId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=networkContainerId",
+    "offeringId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=offeringId",
+    "registryCredentialId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=registryCredentialId",
+    "removeTime": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removeTime",
+    "removed": "http://172.30.0.100:8080/v1/containers?limit=2&sort=removed",
+    "serviceIndexId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=serviceIndexId",
+    "startCount": "http://172.30.0.100:8080/v1/containers?limit=2&sort=startCount",
+    "state": "http://172.30.0.100:8080/v1/containers?limit=2&sort=state",
+    "systemContainer": "http://172.30.0.100:8080/v1/containers?limit=2&sort=systemContainer",
+    "token": "http://172.30.0.100:8080/v1/containers?limit=2&sort=token",
+    "userdata": "http://172.30.0.100:8080/v1/containers?limit=2&sort=userdata",
+    "uuid": "http://172.30.0.100:8080/v1/containers?limit=2&sort=uuid",
+    "version": "http://172.30.0.100:8080/v1/containers?limit=2&sort=version",
+    "zoneId": "http://172.30.0.100:8080/v1/containers?limit=2&sort=zoneId"
+  },
+  "pagination": {
+    "first": null,
+    "previous": null,
+    "next": "http://172.30.0.100:8080/v1/containers?limit=2&marker=m2",
+    "limit": 2,
+    "total": null,
+    "partial": true
+  },
+  "sort": null,
+  "filters": {
+    "accountId": null,
+    "agentId": null,
+    "allocationState": null,
+    "compute": null,
+    "createIndex": null,
+    "created": null,
+    "deploymentUnitUuid": null,
+    "description": null,
+    "dnsInternal": null,
+    "dnsSearchInternal": null,
+    "domain": null,
+    "externalId": null,
+    "firstRunning": null,
+    "healthState": null,
+    "healthUpdated": null,
+    "hostname": null,
+    "id": null,
+    "imageId": null,
+    "instanceTriggeredStop": null,
+    "kind": null,
+    "memoryMb": null,
+    "name": null,
+    "nativeContainer": null,
+    "networkContainerId": null,
+    "offeringId": null,
+    "registryCredentialId": null,
+    "removeTime": null,
+    "removed": null,
+    "serviceIndexId": null,
+    "startCount": null,
+    "state": null,
+    "systemContainer": null,
+    "token": null,
+    "userdata": null,
+    "uuid": null,
+    "version": null,
+    "zoneId": null
+  },
+  "createDefaults": {}
+}
\ No newline at end of file


[04/27] libcloud git commit: properly parse_error now

Posted by an...@apache.org.
properly parse_error now


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/5b17bdf6
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/5b17bdf6
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/5b17bdf6

Branch: refs/heads/trunk
Commit: 5b17bdf6fb4fadbf37226302d47350e0701bae65
Parents: 4b497e6
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Oct 7 14:22:57 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/5b17bdf6/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index f627692..9bf810a 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -38,6 +38,10 @@ VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
 
 class RancherResponse(JsonResponse):
 
+    def parse_error(self):
+        parsed = super(RancherResponse, self).parse_error()
+        return "%s - %s" % (parsed['message'], parsed['detail'])
+
     def success(self):
         return self.status in VALID_RESPONSE_CODES
 
@@ -606,7 +610,10 @@ class RancherContainerDriver(ContainerDriver):
         """
         result = self.connection.request('%s/containers/%s' % (self.baseuri,
                                          container.id), method='DELETE')
-        return result.status in VALID_RESPONSE_CODES
+        if result.status in VALID_RESPONSE_CODES:
+            return self.get_container(container.id)
+        else:
+            raise RancherException(result.status, 'failed to stop container')
 
     def _gen_image(self, imageuuid):
         """


[13/27] libcloud git commit: kwargs, no more build_payload

Posted by an...@apache.org.
kwargs, no more build_payload


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0e5bb664
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0e5bb664
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0e5bb664

Branch: refs/heads/trunk
Commit: 0e5bb664b7222328c42fee748dc165ab3648ceca
Parents: 6a1d03d
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Sep 29 16:18:19 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 617 +++--------------------------
 1 file changed, 50 insertions(+), 567 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/0e5bb664/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 1e8e18b..e20b333 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -1,5 +1,4 @@
 import base64
-import shlex
 
 try:
     import simplejson as json
@@ -157,10 +156,10 @@ class RancherContainerDriver(ContainerDriver):
         return result['data']
 
     def ex_deploy_stack(self, name, description=None, dockercompose=None,
-                              environment=None, externalid=None, outputs=None,
-                              previousenvironment=None,
-                              previousexternalid=None, ranchercompose=None,
-                              start=True):
+                        environment=None, externalid=None, outputs=None,
+                        previousenvironment=None,
+                        previousexternalid=None, ranchercompose=None,
+                        start=True):
         """
         Deploy a new stack.
 
@@ -305,25 +304,24 @@ class RancherContainerDriver(ContainerDriver):
                           metadata=None, retainip=None, scale=None,
                           scalepolicy=None, secondarylaunchconfigs=None,
                           selectorcontainer=None, selectorlink=None,
-                          vip=None, datavolumesfromlaunchconfigs=None,
-                          disks=None, kind=None, memorymb=None,
-                          networklaunchconfig=None, requsetedipaddress=None,
-                          userdata=None, vcpu=None, **kwargs):
+                          vip=None, **kwargs):
         """
         Deploy a Rancher Service under a stack.
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/service/#create
 
-        :param name: The desired name of the service.
+        *Any further configuration passed applies to the ``launchConfig``*
+
+        :param name: The desired name of the service. (required)
         :type name: ``str``
 
-        :param image: The Image object to deploy.
+        :param image: The Image object to deploy. (required)
         :type image: :class:`libcloud.container.base.ContainerImage`
 
-        :param environmentid: The environment/stack ID this service is tied to.
+        :param environmentid: The stack ID this service is tied to. (required)
         :type environmentid: ``str``
 
-        :param start: Whether to start the service/container on creation.
+        :param start: Whether to start the service on creation.
         :type start: ``bool``
 
         :param assignserviceipaddress: The IP address to assign the service.
@@ -359,193 +357,21 @@ class RancherContainerDriver(ContainerDriver):
         :param vip: The VIP to assign to this service.
         :type vip: ``str``
 
-        :param datavolumesfromlaunchconfigs: The dataVolumesFromLaunchConfigs.
-        :type datavolumesfromlaunchconfigs: ``list``
-
-        :param disks: The disks to associate with this container/service.
-        :type disks: ``list``
-
-        :param kind: The kind of object to deploy.
-        :type kind: ``str``
-
-        :param memorymb: The memoryMb to allow this container/service.
-        :type memorymb: ``int``
-
-        :param networklaunchconfig: The networkLaunchConfig for this container.
-        :type networklaunchconfig: ``str``
-
-        :param requsetedipaddress: The requested IP address for this container.
-        :type requsetedipaddress: ``str``
-
-        :param userdata: User data to associate with this container.
-        :type userdata: ``str``
-
-        :param vcpu: Virtual host cpu's to assign to allow this container.
-        :type vcpu: ``int``
-
-        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
-        :type blkiodeviceoptions: ``dict``
-
-        :param build: Build details for the container.
-        :type build: ``dict``
-
-        :param capadd: Linux Capabilities to enable for this container.
-        :type capadd: ``list``
-
-        :param capdrop: Linux capabilities to disable for this container.
-        :type capdrop: ``list``
-
-        :param command: The command to execute when this container is run.
-        :type command: ``list``
-
-        :param count: The number of containers of this nature to launch.
-        :type count: ``int``
-
-        :param cpuset: Memory nodes in which to allow execution.
-        :type cpuset: ``str``
-
-        :param cpushares: Relative weight cpu shares to allow.
-        :type cpushares: ``int``
-
-        :param datavolumemounts: Data volume mountes this container should have
-        :type datavolumemounts: ``dict``
-
-        :param datavolumes: Data volumes to associate with this container.
-        :type datavolumes: ``list``
-
-        :param datavolumesfrom: Data volumes to inherit.
-        :type datavolumesfrom: ``list``
-
-        :param description: Description for this container.
-        :type description: ``str``
-
-        :param devices: Devices inside the container without privliged mode.
-        :type devices: ``list``
-
-        :param dns: DNS servers the container should utilize.
-        :type dns: ``list``
-
-        :param dnssearch: DNS search domains the container should utilize.
-        :type dnssearch: ``list``
-
-        :param domainname: The domain name the container should have.
-        :type domainname: ``str``
-
-        :param entrypoint: The entrypoint the container should have.
-        :type entrypoint: ``list``
-
-        :param environment: Environment variables the container should have.
-        :type environment: ``dict``
-
-        :param expose: Ports which should be exposed in the container.
-        :type expose: ``list``
-
-        :param extrahosts: Extra hosts file entries this container should have.
-        :type extrahosts: ``list``
-
-        :param healthcheck: Health check parameters for this container.
-        :type healthcheck: ``dict``
-
-        :param hostname: The hostname this container should have.
-        :type hostname: ``str``
-
-        :param instancelinks: Instance links the container should have.
-        :type instancelinks: ``dict``
-
-        :param labels: Labels to associate with this container.
-        :type labels: ``dict``
-
-        :param logconfig: Log configuration for this container.
-        :type logconfig: ``dict``
-
-        :param lxcconf: lxcConf specific to this container.
-        :type lxcconf: ``dict``
-
-        :param memory: The memory limit for this container.
-        :type memory: ``int``
-
-        :param memoryswap: Total memory limit for this container.
-        :type memoryswap: ``int``
-
-        :param networkcontainerrid: A Network container Id for this container.
-        :type networkcontainerrid: ``dict``
-
-        :param networkids: NetworkIds this container should contain.
-        :type networkids: ``list``
-
-        :param networkmode: The networkMode to enable for this container.
-        :type networkmode: ``str``
-
-        :param pidmode: The pidMode for this container.
-        :type pidmode: ``str``
-
-        :param ports: The ports to publicize for this container.
-        :type ports: ``list``
-
-        :param privileged: Whether to enable privileged mode for this container
-        :type privileged: ``bool``
-
-        :param publishallports: Publish all ports in container.
-        :type publishallports: ``bool``
-
-        :param readonly: Whether this container should be readOnly.
-        :type readonly: ``bool``
-
-        :param registrycredentialid: Registry credentials to use.
-        :type registrycredentialid: ``dict``
-
-        :param requestedhostid: Id of the requested host to run this container.
-        :type requestedhostid: ``dict``
-
-        :param restartpolicy: The container restart policy.
-        :type restartpolicy: ``dict``
-
-        :param securityopt: Security options to provide for this container.
-        :type securityopt: ``list``
-
-        :param stdinopen: Whether to keep stdin open.
-        :type stdinopen: ``bool``
-
-        :param tty: Enable a tty for this container.
-        :type tty: ``bool``
-
-        :param user: User this container should be tied to.
-        :type user: ``str``
-
-        :param volumedriver: The volume driver to use for this container.
-        :type volumedriver: ``str``
-
-        :param workingdir: The workingDir this container should start in.
-        :type workingdir: ``str``
-
         :return: The newly created service.
         :rtype: ``dict``
         """
 
-        service_specific_container_config = {
-            "dataVolumesFromLaunchConfigs": datavolumesfromlaunchconfigs,
-            "disks": disks,
-            "kind": kind,
-            "memoryMb": memorymb,
-            "networkLaunchConfig": networklaunchconfig,
-            "requestedIpAddress": requsetedipaddress,
-            "userdata": userdata,
-            "vcpu": vcpu
+        launchconfig = {
+            "imageUuid": self._degen_image(image),
+            **kwargs
         }
 
-        # Build the de-facto container payload
-        # Note that we don't need to remove "name" since its None by default.
-        launchconfig = self._build_payload(image, start, **kwargs)
-        # Add in extra service configuration
-        launchconfig.update(service_specific_container_config)
-        launchconfig = json.dumps({k: v for k, v in launchconfig.items()
-                                   if v is not None})
         service_payload = {
             "assignServiceIpAddress": assignserviceipaddress,
             "description": service_description,
             "environmentId": environmentid,
             "externalId": externalid,
-            "launchConfig": json.loads(launchconfig),
+            "launchConfig": launchconfig,
             "metadata": metadata,
             "name": name,
             "retainIp": retainip,
@@ -662,174 +488,48 @@ class RancherContainerDriver(ContainerDriver):
         - ``path`` = ``<hostname>:<port>/<namespace>/<imagename>``
         - ``version`` = ``<version>``
 
-        :param name: The desired name of the container.
+        *Any extra configuration can also be passed i.e. "environment"*
+
+        :param name: The desired name of the container. (required)
         :type name: ``str``
 
-        :param image: The Image object to deploy.
+        :param image: The Image object to deploy. (required)
         :type image: :class:`libcloud.container.base.ContainerImage`
 
         :param parameters: Container Image parameters (unused)
         :type  parameters: ``str``
 
-        :param start: Whether to start the container on creation.
+        :param start: Whether to start the container on creation(startOnCreate)
         :type start: ``bool``
 
-        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
-        :type blkiodeviceoptions: ``dict``
-
-        :param build: Build details for the container.
-        :type build: ``dict``
-
-        :param capadd: Linux Capabilities to enable for this container.
-        :type capadd: ``list``
-
-        :param capdrop: Linux capabilities to disable for this container.
-        :type capdrop: ``list``
-
-        :param command: The command to execute when this container is run.
-        :type command: ``list``
-
-        :param count: The number of containers of this nature to launch.
-        :type count: ``int``
-
-        :param cpuset: Memory nodes in which to allow execution.
-        :type cpuset: ``str``
-
-        :param cpushares: Relative weight cpu shares to allow.
-        :type cpushares: ``int``
-
-        :param datavolumemounts: Data volume mountes this container should have
-        :type datavolumemounts: ``dict``
-
-        :param datavolumes: Data volumes to associate with this container.
-        :type datavolumes: ``list``
-
-        :param datavolumesfrom: Data volumes to inherit.
-        :type datavolumesfrom: ``list``
-
-        :param description: Description for this container.
-        :type description: ``str``
-
-        :param devices: Devices inside the container without privliged mode.
-        :type devices: ``list``
-
-        :param dns: DNS servers the container should utilize.
-        :type dns: ``list``
-
-        :param dnssearch: DNS search domains the container should utilize.
-        :type dnssearch: ``list``
-
-        :param domainname: The domain name the container should have.
-        :type domainname: ``str``
-
-        :param entrypoint: The entrypoint the container should have.
-        :type entrypoint: ``list``
-
-        :param environment: Environment variables the container should have.
-        :type environment: ``dict``
-
-        :param expose: Ports which should be exposed in the container.
-        :type expose: ``list``
-
-        :param extrahosts: Extra hosts file entries this container should have.
-        :type extrahosts: ``list``
-
-        :param healthcheck: Health check parameters for this container.
-        :type healthcheck: ``dict``
-
-        :param hostname: The hostname this container should have.
-        :type hostname: ``str``
-
-        :param instancelinks: Instance links the container should have.
-        :type instancelinks: ``dict``
-
-        :param labels: Labels to associate with this container.
-        :type labels: ``dict``
-
-        :param logconfig: Log configuration for this container.
-        :type logconfig: ``dict``
-
-        :param lxcconf: lxcConf specific to this container.
-        :type lxcconf: ``dict``
-
-        :param memory: The memory limit for this container.
-        :type memory: ``int``
-
-        :param memoryswap: Total memory limit for this container.
-        :type memoryswap: ``int``
-
-        :param networkcontainerrid: A Network container Id for this container.
-        :type networkcontainerrid: ``dict``
-
-        :param networkids: NetworkIds this container should contain.
-        :type networkids: ``list``
-
-        :param networkmode: The networkMode to enable for this container.
-        :type networkmode: ``str``
-
-        :param pidmode: The pidMode for this container.
-        :type pidmode: ``str``
-
-        :param ports: The ports to publicize for this container.
-        :type ports: ``list``
-
-        :param privileged: Whether to enable privileged mode for this container
-        :type privileged: ``bool``
-
-        :param publishallports: Publish all ports in container.
-        :type publishallports: ``bool``
-
-        :param readonly: Whether this container should be readOnly.
-        :type readonly: ``bool``
-
-        :param registrycredentialid: Registry credentials to use.
-        :type registrycredentialid: ``dict``
-
-        :param requestedhostid: Id of the requested host to run this container.
-        :type requestedhostid: ``dict``
-
-        :param restartpolicy: The container restart policy.
-        :type restartpolicy: ``dict``
-
-        :param securityopt: Security options to provide for this container.
-        :type securityopt: ``list``
-
-        :param stdinopen: Whether to keep stdin open.
-        :type stdinopen: ``bool``
-
-        :param tty: Enable a tty for this container.
-        :type tty: ``bool``
-
-        :param user: User this container should be tied to.
-        :type user: ``str``
-
-        :param volumedriver: The volume driver to use for this container.
-        :type volumedriver: ``str``
-
-        :param workingdir: The workingDir this container should start in.
-        :type workingdir: ``str``
-
         :rtype: :class:`Container`
         """
-        payload = self._build_payload(name, image, start, **kwargs)
-        data = json.dumps({k: v for k, v in payload.items() if v is not None})
+
+        payload = {
+            "name": name,
+            "imageUuid": self._degen_image(image),
+            "startOnCreate": start,
+            **kwargs
+        }
+
+        data = json.dumps(payload)
 
         result = self.connection.request('%s/containers' % self.baseuri,
                                          data=data, method='POST').object
 
         return self._to_container(result)
 
-    def get_container(self, id):
+    def get_container(self, con_id):
         """
         Get a container by ID
 
-        :param id: The ID of the container to get
-        :type  id: ``str``
+        :param con_id: The ID of the container to get
+        :type  con_id: ``str``
 
         :rtype: :class:`libcloud.container.base.Container`
         """
         result = self.connection.request("%s/containers/%s" %
-                                         (self.baseuri, id)).object
+                                         (self.baseuri, con_id)).object
 
         return self._to_container(result)
 
@@ -913,6 +613,22 @@ class RancherContainerDriver(ContainerDriver):
             }
         )
 
+    def _degen_image(self, image):
+        """
+        Take in an image object to break down into an ``imageUuid``
+
+        :param image:
+        :return:
+        """
+
+        # Only supporting docker atm
+        image_type = "docker"
+
+        if image.version is not None:
+            return image_type + ':' + image.path + ':' + image.version
+        else:
+            return image_type + ':' + image.path
+
     def _to_container(self, data):
         """
         Convert container in proper Container instance object
@@ -936,7 +652,7 @@ class RancherContainerDriver(ContainerDriver):
             # A Removed container is purged after x amt of time.
             # Both of these render the container dead (can't be started later)
             state = ContainerState.TERMINATED
-        elif rancher_state.endswith('ing'):
+        elif data['transitioning'] == 'yes':
             # Best we can do for current actions
             state = ContainerState.PENDING
         else:
@@ -953,236 +669,3 @@ class RancherContainerDriver(ContainerDriver):
             state=state,
             driver=self.connection.driver,
             extra=extra)
-
-    def _build_payload(self, image, start=True, name=None, image_type="docker",
-                       blkiodeviceoptions=None, build=None,
-                       capadd=None,
-                       capdrop=None, command=None,
-                       count=None, cpuset=None, cpushares=None,
-                       datavolumemounts=None, datavolumes=None,
-                       datavolumesfrom=None, description=None, devices=None,
-                       dns=None, dnssearch=None, domainname=None,
-                       entrypoint=None, environment=None, expose=None,
-                       extrahosts=None, healthcheck=None, hostname=None,
-                       instancelinks=None, labels=None, logconfig=None,
-                       lxcconf=None, memory=None, memoryswap=None,
-                       networkcontainerrid=None, networkids=None,
-                       networkmode=None, pidmode=None, ports=None,
-                       privileged=None, publishallports=None,
-                       readonly=None, registrycredentialid=None,
-                       requestedhostid=None, restartpolicy=None,
-                       securityopt=None,
-                       stdinopen=None, tty=None, user=None,
-                       volumedriver=None, workingdir=None):
-        """
-
-        :param image: The Image object to deploy.
-        :type image: :class:`libcloud.container.base.ContainerImage`
-
-        :param start: Whether to start the container on creation.
-        :type start: ``bool``
-
-        :param name: The desired name of the container.
-        :type name: ``str``
-
-        :param image_type: The image format of the desired image to deploy.
-        :type image_type: ``str``
-
-        :param blkiodeviceoptions: The blkioDeviceOptions for the container.
-        :type blkiodeviceoptions: ``dict``
-
-        :param build: Build details for the container.
-        :type build: ``dict``
-
-        :param capadd: Linux Capabilities to enable for this container.
-        :type capadd: ``list``
-
-        :param capdrop: Linux capabilities to disable for this container.
-        :type capdrop: ``list``
-
-        :param command: The command to execute when this container is run.
-        :type command: ``list``
-
-        :param count: The number of containers of this nature to launch.
-        :type count: ``int``
-
-        :param cpuset: Memory nodes in which to allow execution.
-        :type cpuset: ``str``
-
-        :param cpushares: Relative weight cpu shares to allow.
-        :type cpushares: ``int``
-
-        :param datavolumemounts: Data volume mountes this container should have
-        :type datavolumemounts: ``dict``
-
-        :param datavolumes: Data volumes to associate with this container.
-        :type datavolumes: ``list``
-
-        :param datavolumesfrom: Data volumes to inherit.
-        :type datavolumesfrom: ``list``
-
-        :param description: Description for this container.
-        :type description: ``str``
-
-        :param devices: Devices inside the container without privliged mode.
-        :type devices: ``list``
-
-        :param dns: DNS servers the container should utilize.
-        :type dns: ``list``
-
-        :param dnssearch: DNS search domains the container should utilize.
-        :type dnssearch: ``list``
-
-        :param domainname: The domain name the container should have.
-        :type domainname: ``str``
-
-        :param entrypoint: The entrypoint the container should have.
-        :type entrypoint: ``list``
-
-        :param environment: Environment variables the container should have.
-        :type environment: ``dict``
-
-        :param expose: Ports which should be exposed in the container.
-        :type expose: ``list``
-
-        :param extrahosts: Extra hosts file entries this container should have.
-        :type extrahosts: ``list``
-
-        :param healthcheck: Health check parameters for this container.
-        :type healthcheck: ``dict``
-
-        :param hostname: The hostname this container should have.
-        :type hostname: ``str``
-
-        :param instancelinks: Instance links the container should have.
-        :type instancelinks: ``dict``
-
-        :param labels: Labels to associate with this container.
-        :type labels: ``dict``
-
-        :param logconfig: Log configuration for this container.
-        :type logconfig: ``dict``
-
-        :param lxcconf: lxcConf specific to this container.
-        :type lxcconf: ``dict``
-
-        :param memory: The memory limit for this container.
-        :type memory: ``int``
-
-        :param memoryswap: Total memory limit for this container.
-        :type memoryswap: ``int``
-
-        :param networkcontainerrid: A Network container Id for this container.
-        :type networkcontainerrid: ``dict``
-
-        :param networkids: NetworkIds this container should contain.
-        :type networkids: ``list``
-
-        :param networkmode: The networkMode to enable for this container.
-        :type networkmode: ``str``
-
-        :param pidmode: The pidMode for this container.
-        :type pidmode: ``str``
-
-        :param ports: The ports to publicize for this container.
-        :type ports: ``list``
-
-        :param privileged: Whether to enable privileged mode for this container
-        :type privileged: ``bool``
-
-        :param publishallports: Publish all ports in container.
-        :type publishallports: ``bool``
-
-        :param readonly: Whether this container should be readOnly.
-        :type readonly: ``bool``
-
-        :param registrycredentialid: Registry credentials to use.
-        :type registrycredentialid: ``dict``
-
-        :param requestedhostid: Id of the requested host to run this container.
-        :type requestedhostid: ``dict``
-
-        :param restartpolicy: The container restart policy.
-        :type restartpolicy: ``dict``
-
-        :param securityopt: Security options to provide for this container.
-        :type securityopt: ``list``
-
-        :param stdinopen: Whether to keep stdin open.
-        :type stdinopen: ``bool``
-
-        :param tty: Enable a tty for this container.
-        :type tty: ``bool``
-
-        :param user: User this container should be tied to.
-        :type user: ``str``
-
-        :param volumedriver: The volume driver to use for this container.
-        :type volumedriver: ``str``
-
-        :param workingdir: The workingDir this container should start in.
-        :type workingdir: ``str``
-
-        :return:
-        """
-
-        if command is not None:
-            command = shlex.split(str(command))
-
-        if image.version is not None:
-            imageuuid = image_type + ':' + image.path + ':' + image.version
-        else:
-            imageuuid = image_type + ':' + image.path
-
-        payload = {
-            "blkioDeviceOptions": blkiodeviceoptions,
-            "build": build,
-            "capAdd": capadd,
-            "capDrop": capdrop,
-            "command": command,
-            "count": count,
-            "cpuSet": cpuset,
-            "cpuShares": cpushares,
-            "dataVolumeMounts": datavolumemounts,
-            "dataVolumes": datavolumes,
-            "dataVolumesFrom": datavolumesfrom,
-            "description": description,
-            "devices": devices,
-            "dns": dns,
-            "dnsSearch": dnssearch,
-            "domainName": domainname,
-            "entryPoint": entrypoint,
-            "environment": environment,
-            "expose": expose,
-            "extraHosts": extrahosts,
-            "healthCheck": healthcheck,
-            "hostname": hostname,
-            "imageUuid": imageuuid,
-            "instanceLinks": instancelinks,
-            "labels": labels,
-            "logConfig": logconfig,
-            "lxcConf": lxcconf,
-            "memory": memory,
-            "memorySwap": memoryswap,
-            "name": name,
-            "networkContainerId": networkcontainerrid,
-            "networkIds": networkids,
-            "networkMode": networkmode,
-            "pidMode": pidmode,
-            "ports": ports,
-            "privileged": privileged,
-            "publishAllPorts": publishallports,
-            "readOnly": readonly,
-            "registryCredentialId": registrycredentialid,
-            "requestedHostId": requestedhostid,
-            "restartPolicy": restartpolicy,
-            "securityOpt": securityopt,
-            "startOnCreate": start,
-            "stdinOpen": stdinopen,
-            "tty": tty,
-            "user": user,
-            "volumeDriver": volumedriver,
-            "workingdir": workingdir
-        }
-
-        return payload


[18/27] libcloud git commit: docstring cleanup

Posted by an...@apache.org.
docstring cleanup


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d6590e99
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d6590e99
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d6590e99

Branch: refs/heads/trunk
Commit: d6590e99aa367cff46a8e67de50c945bfea6368a
Parents: d96fc83
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Wed Sep 28 23:33:24 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 41 ++++++++++++++++++++++--------
 1 file changed, 31 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d6590e99/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 62a88b5..261f9f8 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -89,14 +89,29 @@ class RancherContainerDriver(ContainerDriver):
 
     def __init__(self, key, secret, secure=False, host='localhost', port=80):
         """
+        Rancher Container driver class.
+
+        Example:
+
+        >>> from libcloud.container.providers import get_driver
+        >>> from libcloud.container.types import Provider
+
+        >>> driver = get_driver(Provider.RANCHER)
+        >>> connection = driver(key="ACCESS_KEY_HERE",
+        secret="SECRET_KEY_HERE", host="172.30.0.100", port=8080)
+
+        >>> image = ContainerImage("hastebin", "hastebin", "rlister/hastebin",
+        "latest", driver=None)
+        >>> newcontainer = connection.deploy_container("myawesomepastebin",
+        image, environment={"STORAGE_TYPE": "file"})
+
         :param    key: API key or username to used (required)
         :type     key: ``str``
 
         :param    secret: Secret password to be used (required)
         :type     secret: ``str``
 
-        :param    secure: Whether to use HTTPS or HTTP. Note: Some providers
-                only support HTTPS, and it is on by default.
+        :param    secure: Whether to use HTTPS or HTTP.
         :type     secure: ``bool``
 
         :param    host: Override hostname used for connections.
@@ -867,6 +882,19 @@ class RancherContainerDriver(ContainerDriver):
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/container/#create
 
+        **The following is the Image format used for ``ContainerImage``**
+
+        *For a ``imageuuid``*:
+
+        - ``docker:<hostname>:<port>/<namespace>/<imagename>:<version>``
+
+        *The following applies*:
+
+        - ``id`` = ``<imagename>``
+        - ``name`` = ``<imagename>``
+        - ``path`` = ``<hostname>:<port>/<namespace>/<imagename>``
+        - ``version`` = ``<version>``
+
         :param name: The desired name of the container.
         :type name: ``str``
 
@@ -1076,14 +1104,7 @@ class RancherContainerDriver(ContainerDriver):
         image object. Only supports docker based images hence `docker:` must
         prefix!!
 
-        For a ``imageuuid``:
-            ``docker:<hostname>:<port>/<namespace>/<imagename>:<version>``
-
-        The following applies:
-            ``id`` = ``<imagename>``
-            ``name`` = ``<imagename>``
-            ``path`` = ``<hostname>:<port>/<namespace>/<imagename>``
-            ``version`` = ``<version>``
+        Please see the deploy_container() for details on the format.
 
         :param imageuuid: A valid Rancher image string
             i.e. ``docker:rlister/hastebin:8.0``


[15/27] libcloud git commit: minor stuffs

Posted by an...@apache.org.
minor stuffs


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/5962ef06
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/5962ef06
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/5962ef06

Branch: refs/heads/trunk
Commit: 5962ef0606941fe13268da032fe02a887d54c3a7
Parents: 17e078e
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Sep 30 11:15:31 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/5962ef06/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 9ce8b5d..b60dd27 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -152,7 +152,7 @@ class RancherContainerDriver(ContainerDriver):
 
         http://docs.rancher.com/rancher/v1.2/en/api/api-resources/environment/#create
 
-        :param name: The desired name of the stack.
+        :param name: The desired name of the stack. (required)
         :type name: ``str``
 
         :param description: A desired description for the stack.


[27/27] libcloud git commit: changes for #876

Posted by an...@apache.org.
changes for #876


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/1a836148
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/1a836148
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/1a836148

Branch: refs/heads/trunk
Commit: 1a836148250ebf852a7f28e4d93007417ee7639d
Parents: 5f1d6bc
Author: Anthony Shaw <an...@apache.org>
Authored: Sat Oct 8 13:30:19 2016 +1100
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:30:19 2016 +1100

----------------------------------------------------------------------
 CHANGES.rst | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/1a836148/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 48e68cc..4ced494 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -59,6 +59,10 @@ Compute
 Container
 ~~~~~~~~~
 
+- Introduced new Racher driver
+  (GITHUB-876)
+  [Mario Loria]
+
 - Fixed bug in Docker util library for fetching images from the docker hub API. API
   was returning 301 and redirects were not being followed.
   (GITHUB-862)


[17/27] libcloud git commit: fixup kwargs config handling

Posted by an...@apache.org.
fixup kwargs config handling


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/5cd5f9d7
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/5cd5f9d7
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/5cd5f9d7

Branch: refs/heads/trunk
Commit: 5cd5f9d73203e97cad83ef5076d13df71cc0485f
Parents: ce9073d
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Wed Oct 5 18:51:35 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/5cd5f9d7/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index ae4d7c1..2a6b8d5 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -312,7 +312,7 @@ class RancherContainerDriver(ContainerDriver):
                           metadata=None, retain_ip=None, scale=None,
                           scale_policy=None, secondary_launch_configs=None,
                           selector_container=None, selector_link=None,
-                          vip=None, **kwargs):
+                          vip=None, **launch_conf):
         """
         Deploy a Rancher Service under a stack.
 
@@ -369,17 +369,14 @@ class RancherContainerDriver(ContainerDriver):
         :rtype: ``dict``
         """
 
-        launchconfig = {
-            "imageUuid": self._degen_image(image),
-            **kwargs
-        }
+        launch_conf['imageUuid'] = self._degen_image(image),
 
         service_payload = {
             "assignServiceIpAddress": assign_service_ip_address,
             "description": service_description,
             "environmentId": environment_id,
             "externalId": external_id,
-            "launchConfig": launchconfig,
+            "launchConfig": launch_conf,
             "metadata": metadata,
             "name": name,
             "retainIp": retain_ip,
@@ -497,7 +494,7 @@ class RancherContainerDriver(ContainerDriver):
         return containers
 
     def deploy_container(self, name, image, parameters=None, start=True,
-                         **kwargs):
+                         **config):
         """
         Deploy a new container.
 
@@ -537,10 +534,10 @@ class RancherContainerDriver(ContainerDriver):
             "name": name,
             "imageUuid": self._degen_image(image),
             "startOnCreate": start,
-            **kwargs
         }
+        config.update(payload)
 
-        data = json.dumps(payload)
+        data = json.dumps(config)
 
         result = self.connection.request('%s/containers' % self.baseuri,
                                          data=data, method='POST').object


[05/27] libcloud git commit: added search for stacks and services

Posted by an...@apache.org.
added search for stacks and services


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a58452c2
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a58452c2
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a58452c2

Branch: refs/heads/trunk
Commit: a58452c27dcc9697c932f75e17f08520d79f9401
Parents: 038411c
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Tue Oct 4 21:52:44 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 55 ++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/a58452c2/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index b4811ba..c064317 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -1,3 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 import base64
 
 try:
@@ -205,6 +220,26 @@ class RancherContainerDriver(ContainerDriver):
 
         return result
 
+    def ex_search_stacks(self, search_params):
+        """
+        Search for stacks matching certain filters
+
+        i.e. ``{ "name": "awesomestack"}``
+
+        :param search_params: A collection of search parameters to use.
+        :type search_params: ``dict``
+
+        :rtype: ``list``
+        """
+        search_list = []
+        for f, v in search_params.items():
+            search_list.append(f + '=' + v)
+        search_items = '&'.join(search_list)
+        result = self.connection.request("%s/environments?%s" % (
+            self.baseuri, search_items)).object
+
+        return result['data']
+
     def ex_destroy_stack(self, env_id):
         """
         Destroy a stack by ID
@@ -378,6 +413,26 @@ class RancherContainerDriver(ContainerDriver):
 
         return result
 
+    def ex_search_services(self, search_params):
+        """
+        Search for services matching certain filters
+
+        i.e. ``{ "name": "awesomesause", "environmentId": "1e2"}``
+
+        :param search_params: A collection of search parameters to use.
+        :type search_params: ``dict``
+
+        :rtype: ``list``
+        """
+        search_list = []
+        for f, v in search_params.items():
+            search_list.append(f + '=' + v)
+        search_items = '&'.join(search_list)
+        result = self.connection.request("%s/services?%s" % (
+            self.baseuri, search_items)).object
+
+        return result['data']
+
     def ex_destroy_service(self, service_id):
         """
         Destroy a service by ID


[24/27] libcloud git commit: cleanup comments on test

Posted by an...@apache.org.
cleanup comments on test


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/ceffaf9d
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/ceffaf9d
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/ceffaf9d

Branch: refs/heads/trunk
Commit: ceffaf9d077d84a8e8ecb974062fadc7313437f3
Parents: d179167
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Fri Oct 7 20:47:34 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/test/container/test_rancher.py | 2 --
 1 file changed, 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/ceffaf9d/libcloud/test/container/test_rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_rancher.py b/libcloud/test/container/test_rancher.py
index 2d1cc4d..743c2d3 100644
--- a/libcloud/test/container/test_rancher.py
+++ b/libcloud/test/container/test_rancher.py
@@ -56,13 +56,11 @@ class RancherContainerDriverTestCase(unittest.TestCase):
         self.assertEqual(stack['environment']['root_password'], "password")
 
     def test_ex_search_stacks(self):
-        # also uses ex_list_stacks.json
         stacks = self.driver.ex_search_stacks({"healthState": "healthy"})
         self.assertEqual(len(stacks), 6)
         self.assertEqual(stacks[0]['healthState'], "healthy")
 
     def test_ex_destroy_stack(self):
-        # Not sure how to do these with returns in mockhttp
         response = self.driver.ex_destroy_stack("1e10")
         self.assertEqual(response, True)
 


[14/27] libcloud git commit: remove unneeded stuffs

Posted by an...@apache.org.
remove unneeded stuffs


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/17e078e3
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/17e078e3
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/17e078e3

Branch: refs/heads/trunk
Commit: 17e078e3c614588b7b6c365336f44047c237e7bd
Parents: 0e5bb66
Author: Mario Loria <ma...@arroyonetworks.com>
Authored: Thu Sep 29 16:34:01 2016 -0400
Committer: Anthony Shaw <an...@apache.org>
Committed: Sat Oct 8 13:29:22 2016 +1100

----------------------------------------------------------------------
 libcloud/container/drivers/rancher.py | 13 -------------
 1 file changed, 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/17e078e3/libcloud/container/drivers/rancher.py
----------------------------------------------------------------------
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index e20b333..9ce8b5d 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -23,15 +23,6 @@ VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
 
 class RancherResponse(JsonResponse):
 
-    def parse_body(self):
-        if len(self.body) == 0 and not self.parse_zero_length_body:
-            return self.body
-        valid_content_types = ['application/json',
-                               'application/json; charset=utf-8']
-        content_type = self.headers.get('content-type')
-        if content_type in valid_content_types:
-            return json.loads(self.body)
-
     def parse_error(self):
         if self.status == 401:
             raise InvalidCredsError('Invalid credentials')
@@ -134,10 +125,6 @@ class RancherContainerDriver(ContainerDriver):
             if host.startswith(prefix):
                 host = host.strip(prefix)
 
-        self.connection.host = host
-        self.connection.port = port
-        self.connection.secure = secure
-
         # 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