You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by qu...@apache.org on 2017/09/25 04:03:21 UTC
libcloud git commit: Adding support for GCE node labels.
Repository: libcloud
Updated Branches:
refs/heads/trunk 29d1480ba -> a83130139
Adding support for GCE node labels.
Closes #1115
Signed-off-by: Quentin Pradet <qu...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a8313013
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a8313013
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a8313013
Branch: refs/heads/trunk
Commit: a831301394443399bdee613176d0e84d0154d14b
Parents: 29d1480
Author: maxlip <ma...@gmail.com>
Authored: Wed Sep 20 14:09:18 2017 -0700
Committer: Quentin Pradet <qu...@apache.org>
Committed: Mon Sep 25 07:52:49 2017 +0400
----------------------------------------------------------------------
CHANGES.rst | 2 +
libcloud/compute/drivers/gce.py | 60 +++++++++++++++++---
..._us_central1_a_node_name_setLabels_post.json | 15 +++++
...l1_a_instances_node_name_setLabels_post.json | 15 +++++
libcloud/test/compute/test_gce.py | 36 ++++++++++++
5 files changed, 119 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/a8313013/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index bc42ce5..1644367 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -16,6 +16,8 @@ Compute
- Update ProfitBricks driver and add support for the new API v4. (GITHUB-1103)
[Nurfet Becirevic]
+- [GCE] Support GCE node labels. (GITHUB-1115) [@maxlip]
+
Changes in Apache Libcloud 2.2.1
--------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/a8313013/libcloud/compute/drivers/gce.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py
index c9c3c17..7b052a2 100644
--- a/libcloud/compute/drivers/gce.py
+++ b/libcloud/compute/drivers/gce.py
@@ -1919,6 +1919,29 @@ class GCENodeDriver(NodeDriver):
self.connection.async_request(request, method='POST', data=body)
return True
+ def ex_set_node_labels(self, node, labels):
+ """
+ Set labels for the specified node.
+
+ :keyword node: The existing target Node (instance) for the request.
+ :type node: ``Node``
+
+ :keyword labels: Set (or clear with None) labels for this node.
+ :type labels: ``dict`` or ``None``
+
+ :return: True if successful
+ :rtype: ``bool``
+ """
+ if not isinstance(node, Node):
+ raise ValueError("Must specify a valid libcloud node object.")
+ node_name = node.name
+ zone_name = node.extra['zone'].name
+ current_fp = node.extra['labelFingerprint']
+ body = {'labels': labels, 'labelFingerprint': current_fp}
+ request = '/zones/%s/instances/%s/setLabels' % (zone_name, node_name)
+ self.connection.async_request(request, method='POST', data=body)
+ return True
+
def ex_get_serial_output(self, node):
"""
Fetch the console/serial port output from the node.
@@ -3699,7 +3722,7 @@ class GCENodeDriver(NodeDriver):
ex_service_accounts=None, description=None, ex_can_ip_forward=None,
ex_disks_gce_struct=None, ex_nic_gce_struct=None,
ex_on_host_maintenance=None, ex_automatic_restart=None,
- ex_preemptible=None, ex_image_family=None):
+ ex_preemptible=None, ex_image_family=None, ex_labels=None):
"""
Create a new node and return a node object for the node.
@@ -3820,6 +3843,9 @@ class GCENodeDriver(NodeDriver):
to use this keyword.
:type ex_image_family: ``str`` or ``None``
+ :keyword ex_labels: Labels dictionary for instance.
+ :type ex_labels: ``dict`` or ``None``
+
:return: A Node object for the new node.
:rtype: :class:`Node`
"""
@@ -3879,7 +3905,7 @@ class GCENodeDriver(NodeDriver):
ex_boot_disk, external_ip, ex_disk_type, ex_disk_auto_delete,
ex_service_accounts, description, ex_can_ip_forward,
ex_disks_gce_struct, ex_nic_gce_struct, ex_on_host_maintenance,
- ex_automatic_restart, ex_preemptible, ex_subnetwork)
+ ex_automatic_restart, ex_preemptible, ex_subnetwork, ex_labels)
self.connection.async_request(request, method='POST', data=node_data)
return self.ex_get_node(name, location.name)
@@ -4033,7 +4059,7 @@ class GCENodeDriver(NodeDriver):
service_accounts=None, on_host_maintenance=None,
automatic_restart=None, preemptible=None, tags=None, metadata=None,
description=None, disks_gce_struct=None, nic_gce_struct=None,
- use_selflinks=True):
+ use_selflinks=True, labels=None):
"""
Create the GCE instance properties needed for instance templates.
@@ -4143,6 +4169,9 @@ class GCENodeDriver(NodeDriver):
details.
:type nic_gce_struct: ``list`` or ``None``
+ :type labels: Labels dict for instance
+ :type labels: ``dict`` or ``None``
+
:return: A dictionary formatted for use with the GCE API.
:rtype: ``dict``
"""
@@ -4218,6 +4247,8 @@ class GCENodeDriver(NodeDriver):
if metadata:
instance_properties['metadata'] = self._format_metadata(
fingerprint='na', metadata=metadata)
+ if labels:
+ instance_properties['labels'] = labels
if can_ip_forward:
instance_properties['canIpForward'] = True
@@ -4566,7 +4597,7 @@ class GCENodeDriver(NodeDriver):
description=None, ex_can_ip_forward=None, ex_disks_gce_struct=None,
ex_nic_gce_struct=None, ex_on_host_maintenance=None,
ex_automatic_restart=None, ex_image_family=None,
- ex_preemptible=None):
+ ex_preemptible=None, ex_labels=None):
"""
Create multiple nodes and return a list of Node objects.
@@ -4702,6 +4733,9 @@ class GCENodeDriver(NodeDriver):
to use this keyword.
:type ex_image_family: ``str`` or ``None``
+ :param ex_labels: Label dict for node.
+ :type ex_labels: ``dict``
+
:return: A list of Node objects for the new nodes.
:rtype: ``list`` of :class:`Node`
@@ -4752,7 +4786,8 @@ class GCENodeDriver(NodeDriver):
'ex_nic_gce_struct': ex_nic_gce_struct,
'ex_on_host_maintenance': ex_on_host_maintenance,
'ex_automatic_restart': ex_automatic_restart,
- 'ex_preemptible': ex_preemptible}
+ 'ex_preemptible': ex_preemptible,
+ 'ex_labels': ex_labels}
# List for holding the status information for disk/node creation.
status_list = []
@@ -7644,7 +7679,7 @@ class GCENodeDriver(NodeDriver):
ex_service_accounts=None, description=None, ex_can_ip_forward=None,
ex_disks_gce_struct=None, ex_nic_gce_struct=None,
ex_on_host_maintenance=None, ex_automatic_restart=None,
- ex_preemptible=None, ex_subnetwork=None):
+ ex_preemptible=None, ex_subnetwork=None, ex_labels=None):
"""
Returns a request and body to create a new node.
@@ -7759,6 +7794,9 @@ class GCENodeDriver(NodeDriver):
:param ex_subnetwork: The network to associate with the node.
:type ex_subnetwork: :class:`GCESubnetwork`
+ :param ex_labels: Label dict for node.
+ :type ex_labels: ``dict`` or ``None``
+
:return: A tuple containing a request string and a node_data dict.
:rtype: ``tuple`` of ``str`` and ``dict``
"""
@@ -7786,8 +7824,8 @@ class GCENodeDriver(NodeDriver):
service_accounts=ex_service_accounts,
on_host_maintenance=ex_on_host_maintenance,
automatic_restart=ex_automatic_restart, preemptible=ex_preemptible,
- tags=tags, metadata=metadata, description=description,
- disks_gce_struct=ex_disks_gce_struct,
+ tags=tags, metadata=metadata, labels=ex_labels,
+ description=description, disks_gce_struct=ex_disks_gce_struct,
nic_gce_struct=ex_nic_gce_struct, use_selflinks=use_selflinks)
node_data['name'] = name
@@ -7891,7 +7929,9 @@ class GCENodeDriver(NodeDriver):
ex_on_host_maintenance=node_attrs['ex_on_host_maintenance'],
ex_automatic_restart=node_attrs['ex_automatic_restart'],
ex_subnetwork=node_attrs['subnetwork'],
- ex_preemptible=node_attrs['ex_preemptible'])
+ ex_preemptible=node_attrs['ex_preemptible'],
+ ex_labels=node_attrs['ex_labels']
+ )
try:
node_res = self.connection.request(request, method='POST',
@@ -8362,6 +8402,8 @@ class GCENodeDriver(NodeDriver):
extra['serviceAccounts'] = node.get('serviceAccounts', [])
extra['scheduling'] = node.get('scheduling', {})
extra['boot_disk'] = None
+ extra['labels'] = node.get('labels')
+ extra['labelFingerprint'] = node.get('labelFingerprint')
for disk in extra['disks']:
if disk.get('boot') and disk.get('type') == 'PERSISTENT':
http://git-wip-us.apache.org/repos/asf/libcloud/blob/a8313013/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setLabels_post.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setLabels_post.json b/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setLabels_post.json
new file mode 100644
index 0000000..f72e383
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/operations_operation_zones_us_central1_a_node_name_setLabels_post.json
@@ -0,0 +1,15 @@
+{
+ "endTime": "2013-06-26T10:05:07.630-07:00",
+ "id": "3681664092089171723",
+ "insertTime": "2013-06-26T10:05:03.271-07:00",
+ "kind": "compute#operation",
+ "name": "operation-setLabels_post",
+ "operationType": "insert",
+ "progress": 100,
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setLabels_post",
+ "startTime": "2013-06-26T10:05:03.315-07:00",
+ "status": "DONE",
+ "targetId": "16211908079305042870",
+ "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name/setLabels",
+ "user": "foo@developer.gserviceaccount.com"
+}
http://git-wip-us.apache.org/repos/asf/libcloud/blob/a8313013/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setLabels_post.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setLabels_post.json b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setLabels_post.json
new file mode 100644
index 0000000..e698a3c
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gce/zones_us_central1_a_instances_node_name_setLabels_post.json
@@ -0,0 +1,15 @@
+{
+ "endTime": "2013-06-26T10:05:07.630-07:00",
+ "id": "3681664092089171723",
+ "insertTime": "2013-06-26T10:05:03.271-07:00",
+ "kind": "compute#operation",
+ "name": "operation-setLabelspost",
+ "operationType": "insert",
+ "progress": 0,
+ "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/operations/operation-setLabels_post",
+ "startTime": "2013-06-26T10:05:03.315-07:00",
+ "status": "PENDING",
+ "targetId": "16211908079305042870",
+ "targetLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/instances/node-name/setLabels",
+ "user": "foo@developer.gserviceaccount.com"
+}
http://git-wip-us.apache.org/repos/asf/libcloud/blob/a8313013/libcloud/test/compute/test_gce.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py
index 8332f08..31a1bce 100644
--- a/libcloud/test/compute/test_gce.py
+++ b/libcloud/test/compute/test_gce.py
@@ -1216,6 +1216,21 @@ class GCENodeDriverTest(GoogleTestCase, TestCaseMixin):
self.assertEqual(data['metadata']['items'][0]['key'], 'k0')
self.assertEqual(data['metadata']['items'][0]['value'], 'v0')
+ def test_create_node_with_labels(self):
+ node_name = 'node-name'
+ image = self.driver.ex_get_image('debian-7')
+ size = self.driver.ex_get_size('n1-standard-1')
+ zone = self.driver.ex_get_zone('us-central1-a')
+
+ # labels is a dict
+ labels = {'label1': 'v1', 'label2': 'v2'}
+ request, data = self.driver._create_node_req(node_name, size, image,
+ zone, ex_labels=labels)
+ self.assertTrue(data['labels'] is not None)
+ self.assertEqual(len(data['labels']), 2)
+ self.assertEqual(data['labels']['label1'], 'v1')
+ self.assertEqual(data['labels']['label2'], 'v2')
+
def test_create_node_existing(self):
node_name = 'libcloud-demo-europe-np-node'
image = self.driver.ex_get_image('debian-7')
@@ -1862,6 +1877,15 @@ class GCENodeDriverTest(GoogleTestCase, TestCaseMixin):
'value': 'v2'}]}
self.driver.ex_set_node_metadata(node, gcedict)
+ def test_ex_set_node_labels(self):
+ node = self.driver.ex_get_node('node-name', 'us-central1-a')
+ # Test basic values
+ simplelabel = {'key': 'value'}
+ self.driver.ex_set_node_labels(node, simplelabel)
+ # Test multiple values
+ multilabels = {'item1': 'val1', 'item2': 'val2'}
+ self.driver.ex_set_node_labels(node, multilabels)
+
def test_ex_get_region(self):
region_name = 'us-central1'
region = self.driver.ex_get_region(region_name)
@@ -2079,6 +2103,12 @@ class GCEMockHttp(MockHttp):
'zones_us_central1_a_instances_node_name_setMetadata_post.json')
return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+ def _zones_us_central1_a_instances_node_name_setLabels(self, method, url,
+ body, headers):
+ body = self.fixtures.load(
+ 'zones_us_central1_a_instances_node_name_setLabels_post.json')
+ return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+
def _setCommonInstanceMetadata(self, method, url, body, headers):
if method == 'POST':
body = self.fixtures.load('setCommonInstanceMetadata_post.json')
@@ -2554,6 +2584,12 @@ class GCEMockHttp(MockHttp):
'operations_operation_zones_us_central1_a_node_name_setMetadata_post.json')
return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+ def _zones_us_central1_a_operations_operation_setLabels_post(
+ self, method, url, body, headers):
+ body = self.fixtures.load(
+ 'operations_operation_zones_us_central1_a_node_name_setLabels_post.json')
+ return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
+
def _zones_us_central1_a_operations_operation_zones_us_central1_a_targetInstances_post(
self, method, url, body, headers):
body = self.fixtures.load(