From a75553b3ca1a8c1d94a49f328f96ef9a1b634c70 Mon Sep 17 00:00:00 2001 From: Joffrey F Date: Thu, 11 Aug 2016 17:16:41 -0700 Subject: [PATCH] Add `nodes` and `inspect_node` methods Signed-off-by: Joffrey F --- docker/api/swarm.py | 15 ++++++++++ docs/api.md | 9 ++++++ docs/swarm.md | 52 ++++++++++++++++++++++++++++++++- tests/integration/swarm_test.py | 29 ++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/docker/api/swarm.py b/docker/api/swarm.py index 28f9336a..d0993645 100644 --- a/docker/api/swarm.py +++ b/docker/api/swarm.py @@ -29,6 +29,12 @@ class SwarmApiMixin(object): url = self._url('/swarm') return self._result(self._get(url), True) + @utils.check_resource + @utils.minimum_version('1.24') + def inspect_node(self, node_id): + url = self._url('/nodes/{0}', node_id) + return self._result(self._get(url), True) + @utils.minimum_version('1.24') def join_swarm(self, remote_addrs, join_token, listen_addr=None, advertise_addr=None): @@ -50,6 +56,15 @@ class SwarmApiMixin(object): self._raise_for_status(response) return True + @utils.minimum_version('1.24') + def nodes(self, filters=None): + url = self._url('/nodes') + params = {} + if filters: + params['filters'] = utils.convert_filters(filters) + + return self._result(self._get(url, params=params), True) + @utils.minimum_version('1.24') def update_swarm(self, version, swarm_spec=None, rotate_worker_token=False, rotate_manager_token=False): diff --git a/docs/api.md b/docs/api.md index 7748254a..ddfaffeb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -646,6 +646,11 @@ Retrieve network info by id. **Returns** (dict): Network information dictionary +## inspect_node + +Retrieve low-level information about a Swarm node. +See the [Swarm documentation](swarm.md#clientinspect_node). + ## inspect_swarm Retrieve information about the current Swarm. @@ -742,6 +747,10 @@ The above are combined to create a filters dict. **Returns** (dict): List of network objects. +## nodes + +List Swarm nodes. See the [Swarm documentation](swarm.md#clientnodes). + ## pause Pauses all processes within a container. diff --git a/docs/swarm.md b/docs/swarm.md index a9a1d1f5..0cd015a0 100644 --- a/docs/swarm.md +++ b/docs/swarm.md @@ -47,7 +47,6 @@ you will need to specify `force=True` to be able to leave. client.leave_swarm(force=False) ``` - ## Retrieving Swarm status You can retrieve information about your current Swarm status by calling @@ -57,6 +56,15 @@ You can retrieve information about your current Swarm status by calling client.inspect_swarm() ``` +## Listing Swarm nodes + +List all nodes that are part of the current Swarm using `Client.nodes`. +The `filters` argument allows to filter the results. + +```python +client.nodes(filters={'role': 'manager'}) +``` + ## Swarm API documentation ### Client.init_swarm @@ -123,6 +131,37 @@ Create a configuration dictionary for the `external_ca` argument in a * options (dict): An object with key/value pairs that are interpreted as protocol-specific options for the external CA driver. +### Client.inspect_node + +Retrieve low-level information about a Swarm node + +**Params:** + +* node_id (string): ID of the node to be inspected. + +**Returns:** A dictionary containing data about this node. See sample below. + +```python +{u'CreatedAt': u'2016-08-11T23:28:39.695834296Z', + u'Description': {u'Engine': {u'EngineVersion': u'1.12.0', + u'Plugins': [{u'Name': u'bridge', u'Type': u'Network'}, + {u'Name': u'host', u'Type': u'Network'}, + {u'Name': u'null', u'Type': u'Network'}, + {u'Name': u'overlay', u'Type': u'Network'}, + {u'Name': u'local', u'Type': u'Volume'}]}, + u'Hostname': u'dockerserv-1.local.net', + u'Platform': {u'Architecture': u'x86_64', u'OS': u'linux'}, + u'Resources': {u'MemoryBytes': 8052109312, u'NanoCPUs': 4000000000}}, + u'ID': u'1kqami616p23dz4hd7km35w63', + u'ManagerStatus': {u'Addr': u'10.0.131.127:2377', + u'Leader': True, + u'Reachability': u'reachable'}, + u'Spec': {u'Availability': u'active', u'Role': u'manager'}, + u'Status': {u'State': u'ready'}, + u'UpdatedAt': u'2016-08-11T23:28:39.979829529Z', + u'Version': {u'Index': 9}} + ``` + ### Client.inspect_swarm Retrieve information about the current Swarm. @@ -182,6 +221,17 @@ Leave a Swarm. **Returns:** `True` if the request went through. Raises an `APIError` if it fails. +### Client.nodes + +List Swarm nodes + +**Params:** + +* filters (dict): Filters to process on the nodes list. Valid filters: + `id`, `name`, `membership` and `role`. Default: `None` + +**Returns:** A list of dictionaries containing data about each swarm node. + ### Client.update_swarm Update the Swarm's configuration diff --git a/tests/integration/swarm_test.py b/tests/integration/swarm_test.py index b73f81c4..128628e6 100644 --- a/tests/integration/swarm_test.py +++ b/tests/integration/swarm_test.py @@ -114,3 +114,32 @@ class SwarmTest(helpers.BaseTestCase): swarm_info_2['Version']['Index'] ) assert swarm_info_2['Spec']['Name'] == 'reimuhakurei' + + @requires_api_version('1.24') + def test_list_nodes(self): + assert self.client.init_swarm('eth0') + nodes_list = self.client.nodes() + assert len(nodes_list) == 1 + node = nodes_list[0] + assert 'ID' in node + assert 'Spec' in node + assert node['Spec']['Role'] == 'manager' + + filtered_list = self.client.nodes(filters={ + 'id': node['ID'] + }) + assert len(filtered_list) == 1 + filtered_list = self.client.nodes(filters={ + 'role': 'worker' + }) + assert len(filtered_list) == 0 + + @requires_api_version('1.24') + def test_inspect_node(self): + assert self.client.init_swarm('eth0') + nodes_list = self.client.nodes() + assert len(nodes_list) == 1 + node = nodes_list[0] + node_data = self.client.inspect_node(node['ID']) + assert node['ID'] == node_data['ID'] + assert node['Version'] == node_data['Version']