Adding ability to unset fields with update calls
Adding a sentinel object that will be used as a default value in update methods. This object will allow to distinguish whether a field should be unset or should not be updated. Change-Id: Ie6679c8f64623e8570176b8009380b08de2be6a5 Closes-bug: #1534050
This commit is contained in:
@@ -64,6 +64,12 @@ def _check_items(obj, searches):
|
||||
return False
|
||||
|
||||
|
||||
class NotUpdated(object):
|
||||
"""A sentinel class to signal that parameter should not be updated."""
|
||||
def __repr__(self):
|
||||
return 'NotUpdated'
|
||||
|
||||
|
||||
class ResourceManager(object):
|
||||
resource_class = None
|
||||
|
||||
@@ -88,6 +94,11 @@ class ResourceManager(object):
|
||||
if var_value is not None:
|
||||
data[var_name] = var_value
|
||||
|
||||
def _copy_if_updated(self, data, **kwargs):
|
||||
for var_name, var_value in six.iteritems(kwargs):
|
||||
if not isinstance(var_value, NotUpdated):
|
||||
data[var_name] = var_value
|
||||
|
||||
def _create(self, url, data, response_key=None, dump_json=True):
|
||||
if dump_json:
|
||||
kwargs = {'json': data}
|
||||
|
||||
@@ -22,6 +22,7 @@ class ClusterTemplate(base.Resource):
|
||||
|
||||
class ClusterTemplateManager(base.ResourceManager):
|
||||
resource_class = ClusterTemplate
|
||||
NotUpdated = base.NotUpdated()
|
||||
|
||||
def create(self, name, plugin_name, hadoop_version, description=None,
|
||||
cluster_configs=None, node_groups=None, anti_affinity=None,
|
||||
@@ -49,15 +50,17 @@ class ClusterTemplateManager(base.ResourceManager):
|
||||
|
||||
return self._create('/cluster-templates', data, 'cluster_template')
|
||||
|
||||
def update(self, cluster_template_id, name=None, plugin_name=None,
|
||||
hadoop_version=None, description=None, cluster_configs=None,
|
||||
node_groups=None, anti_affinity=None, net_id=None,
|
||||
default_image_id=None, use_autoconfig=None, shares=None,
|
||||
is_public=None, is_protected=None):
|
||||
def update(self, cluster_template_id, name=NotUpdated,
|
||||
plugin_name=NotUpdated, hadoop_version=NotUpdated,
|
||||
description=NotUpdated, cluster_configs=NotUpdated,
|
||||
node_groups=NotUpdated, anti_affinity=NotUpdated,
|
||||
net_id=NotUpdated, default_image_id=NotUpdated,
|
||||
use_autoconfig=NotUpdated, shares=NotUpdated,
|
||||
is_public=NotUpdated, is_protected=NotUpdated):
|
||||
"""Update a Cluster Template."""
|
||||
|
||||
data = {}
|
||||
self._copy_if_defined(data, name=name,
|
||||
self._copy_if_updated(data, name=name,
|
||||
plugin_name=plugin_name,
|
||||
hadoop_version=hadoop_version,
|
||||
description=description,
|
||||
|
||||
@@ -24,6 +24,7 @@ class Cluster(base.Resource):
|
||||
|
||||
class ClusterManager(base.ResourceManager):
|
||||
resource_class = Cluster
|
||||
NotUpdated = base.NotUpdated()
|
||||
|
||||
def create(self, name, plugin_name, hadoop_version,
|
||||
cluster_template_id=None, default_image_id=None,
|
||||
@@ -116,12 +117,13 @@ class ClusterManager(base.ResourceManager):
|
||||
"""Delete a Cluster."""
|
||||
self._delete('/clusters/%s' % cluster_id)
|
||||
|
||||
def update(self, cluster_id, name=None, description=None, is_public=None,
|
||||
is_protected=None, shares=None):
|
||||
def update(self, cluster_id, name=NotUpdated, description=NotUpdated,
|
||||
is_public=NotUpdated, is_protected=NotUpdated,
|
||||
shares=NotUpdated):
|
||||
"""Update a Cluster."""
|
||||
|
||||
data = {}
|
||||
self._copy_if_defined(data, name=name, description=description,
|
||||
self._copy_if_updated(data, name=name, description=description,
|
||||
is_public=is_public, is_protected=is_protected,
|
||||
shares=shares)
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ class JobBinaryInternal(base.Resource):
|
||||
|
||||
class JobBinaryInternalsManager(base.ResourceManager):
|
||||
resource_class = JobBinaryInternal
|
||||
NotUpdated = base.NotUpdated()
|
||||
|
||||
def create(self, name, data):
|
||||
"""Create a Job Binary Internal.
|
||||
@@ -48,12 +49,12 @@ class JobBinaryInternalsManager(base.ResourceManager):
|
||||
"""Delete a Job Binary Internal."""
|
||||
self._delete('/job-binary-internals/%s' % job_binary_id)
|
||||
|
||||
def update(self, job_binary_id, name=None, is_public=None,
|
||||
is_protected=None):
|
||||
def update(self, job_binary_id, name=NotUpdated, is_public=NotUpdated,
|
||||
is_protected=NotUpdated):
|
||||
"""Update a Job Binary Internal."""
|
||||
|
||||
data = {}
|
||||
self._copy_if_defined(data, name=name, is_public=is_public,
|
||||
self._copy_if_updated(data, name=name, is_public=is_public,
|
||||
is_protected=is_protected)
|
||||
|
||||
return self._patch('/job-binary-internals/%s' % job_binary_id, data)
|
||||
|
||||
@@ -22,6 +22,7 @@ class JobExecution(base.Resource):
|
||||
|
||||
class JobExecutionsManager(base.ResourceManager):
|
||||
resource_class = JobExecution
|
||||
NotUpdated = base.NotUpdated()
|
||||
|
||||
def list(self, search_opts=None):
|
||||
"""Get a list of Job Executions."""
|
||||
@@ -52,10 +53,10 @@ class JobExecutionsManager(base.ResourceManager):
|
||||
|
||||
return self._create(url, data, 'job_execution')
|
||||
|
||||
def update(self, obj_id, is_public=None, is_protected=None):
|
||||
def update(self, obj_id, is_public=NotUpdated, is_protected=NotUpdated):
|
||||
"""Update a Job Execution."""
|
||||
|
||||
data = {}
|
||||
self._copy_if_defined(data, is_public=is_public,
|
||||
self._copy_if_updated(data, is_public=is_public,
|
||||
is_protected=is_protected)
|
||||
return self._patch('/job-executions/%s' % obj_id, data)
|
||||
|
||||
@@ -22,6 +22,7 @@ class Job(base.Resource):
|
||||
|
||||
class JobsManager(base.ResourceManager):
|
||||
resource_class = Job
|
||||
NotUpdated = base.NotUpdated()
|
||||
|
||||
def create(self, name, type, mains=None, libs=None, description=None,
|
||||
interface=None, is_public=None, is_protected=None):
|
||||
@@ -54,12 +55,12 @@ class JobsManager(base.ResourceManager):
|
||||
"""Delete a Job"""
|
||||
self._delete('/jobs/%s' % job_id)
|
||||
|
||||
def update(self, job_id, name=None, description=None, is_public=None,
|
||||
is_protected=None):
|
||||
def update(self, job_id, name=NotUpdated, description=NotUpdated,
|
||||
is_public=NotUpdated, is_protected=NotUpdated):
|
||||
"""Update a Job."""
|
||||
|
||||
data = {}
|
||||
self._copy_if_defined(data, name=name, description=description,
|
||||
self._copy_if_updated(data, name=name, description=description,
|
||||
is_public=is_public, is_protected=is_protected)
|
||||
|
||||
return self._patch('/jobs/%s' % job_id, data)
|
||||
|
||||
@@ -22,6 +22,7 @@ class NodeGroupTemplate(base.Resource):
|
||||
|
||||
class NodeGroupTemplateManager(base.ResourceManager):
|
||||
resource_class = NodeGroupTemplate
|
||||
NotUpdated = base.NotUpdated()
|
||||
|
||||
def create(self, name, plugin_name, hadoop_version, flavor_id,
|
||||
description=None, volumes_per_node=None, volumes_size=None,
|
||||
@@ -74,20 +75,22 @@ class NodeGroupTemplateManager(base.ResourceManager):
|
||||
return self._create('/node-group-templates', data,
|
||||
'node_group_template')
|
||||
|
||||
def update(self, ng_template_id, name=None, plugin_name=None,
|
||||
hadoop_version=None, flavor_id=None, description=None,
|
||||
volumes_per_node=None, volumes_size=None, node_processes=None,
|
||||
node_configs=None, floating_ip_pool=None, security_groups=None,
|
||||
auto_security_group=None, availability_zone=None,
|
||||
volumes_availability_zone=None, volume_type=None,
|
||||
image_id=None, is_proxy_gateway=None,
|
||||
volume_local_to_instance=None, use_autoconfig=None,
|
||||
shares=None, is_public=None, is_protected=None,
|
||||
volume_mount_prefix=None):
|
||||
def update(self, ng_template_id, name=NotUpdated, plugin_name=NotUpdated,
|
||||
hadoop_version=NotUpdated, flavor_id=NotUpdated,
|
||||
description=NotUpdated, volumes_per_node=NotUpdated,
|
||||
volumes_size=NotUpdated, node_processes=NotUpdated,
|
||||
node_configs=NotUpdated, floating_ip_pool=NotUpdated,
|
||||
security_groups=NotUpdated, auto_security_group=NotUpdated,
|
||||
availability_zone=NotUpdated,
|
||||
volumes_availability_zone=NotUpdated, volume_type=NotUpdated,
|
||||
image_id=NotUpdated, is_proxy_gateway=NotUpdated,
|
||||
volume_local_to_instance=NotUpdated, use_autoconfig=NotUpdated,
|
||||
shares=NotUpdated, is_public=NotUpdated,
|
||||
is_protected=NotUpdated, volume_mount_prefix=NotUpdated):
|
||||
"""Update a Node Group Template."""
|
||||
|
||||
data = {}
|
||||
self._copy_if_defined(
|
||||
self._copy_if_updated(
|
||||
data, name=name, plugin_name=plugin_name,
|
||||
hadoop_version=hadoop_version, flavor_id=flavor_id,
|
||||
description=description, volumes_per_node=volumes_per_node,
|
||||
|
||||
@@ -99,6 +99,7 @@ class ClusterTemplateTest(base.BaseTestCase):
|
||||
update_url = self.URL + '/cluster-templates/id'
|
||||
self.responses.put(update_url, status_code=202, json=self.update_json)
|
||||
|
||||
# check that all parameters will be updated
|
||||
updated = self.client.cluster_templates.update(
|
||||
"id",
|
||||
resp.name,
|
||||
@@ -115,3 +116,26 @@ class ClusterTemplateTest(base.BaseTestCase):
|
||||
|
||||
self.assertIsInstance(updated, ct.ClusterTemplate)
|
||||
self.assertFields(self.update_json["cluster_template"], updated)
|
||||
|
||||
# check that parameters will not be updated
|
||||
self.client.cluster_templates.update("id")
|
||||
self.assertEqual(update_url, self.responses.last_request.url)
|
||||
self.assertEqual({},
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that all parameters will be unset
|
||||
unset_json = {
|
||||
'anti_affinity': None, 'cluster_configs': None,
|
||||
'default_image_id': None, 'description': None,
|
||||
'hadoop_version': None, 'is_protected': None, 'is_public': None,
|
||||
'name': None, 'net_id': None,
|
||||
'node_groups': None, 'plugin_name': None, 'shares': None,
|
||||
'use_autoconfig': None}
|
||||
|
||||
req_json = unset_json.copy()
|
||||
req_json['neutron_management_network'] = req_json.pop('net_id')
|
||||
|
||||
self.client.cluster_templates.update("id", **unset_json)
|
||||
self.assertEqual(update_url, self.responses.last_request.url)
|
||||
self.assertEqual(req_json,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
@@ -167,6 +167,7 @@ class ClusterTest(base.BaseTestCase):
|
||||
|
||||
self.responses.patch(url, status_code=202, json=update_body)
|
||||
|
||||
# check that all parameters will be updated
|
||||
resp = self.client.clusters.update('id', name='new_name',
|
||||
description='descr')
|
||||
|
||||
@@ -175,6 +176,23 @@ class ClusterTest(base.BaseTestCase):
|
||||
self.assertEqual(update_body,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that parameters will not be updated
|
||||
self.client.clusters.update("id")
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual({},
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that all parameters will be unset
|
||||
unset_json = {
|
||||
"name": None, "description": None, "is_public": None,
|
||||
"is_protected": None, "shares": None
|
||||
}
|
||||
|
||||
self.client.clusters.update("id", **unset_json)
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual(unset_json,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
def test_clusters_update_share(self):
|
||||
url = self.URL + '/clusters/id'
|
||||
|
||||
|
||||
@@ -74,9 +74,26 @@ class JobBinaryInternalTest(base.BaseTestCase):
|
||||
|
||||
self.responses.patch(url, status_code=202, json=update_body)
|
||||
|
||||
# check that all parameters will be updated
|
||||
resp = self.client.job_binary_internals.update('id', name='new_name')
|
||||
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertIsInstance(resp, jbi.JobBinaryInternal)
|
||||
self.assertEqual(update_body,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that parameters will not be updated
|
||||
self.client.job_binary_internals.update("id")
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual({},
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that all parameters will be unset
|
||||
unset_json = {
|
||||
'name': None, "is_public": None, "is_protected": None
|
||||
}
|
||||
|
||||
self.client.job_binary_internals.update("id", **unset_json)
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual(unset_json,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
@@ -103,8 +103,25 @@ class JobExecutionTest(base.BaseTestCase):
|
||||
url = self.URL + '/job-executions/id'
|
||||
self.responses.patch(url, status_code=202, json=self.update_json)
|
||||
|
||||
# check that all parameters will be updated
|
||||
resp = self.client.job_executions.update("id", **self.update_json)
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertIsInstance(resp, je.JobExecution)
|
||||
self.assertEqual(self.update_json,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that parameters will not be updated
|
||||
self.client.job_executions.update("id")
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual({},
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that all parameters will be unset
|
||||
unset_json = {
|
||||
"is_public": None, "is_protected": None
|
||||
}
|
||||
|
||||
self.client.job_executions.update("id", **unset_json)
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual(unset_json,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
@@ -96,6 +96,7 @@ class JobTest(base.BaseTestCase):
|
||||
|
||||
self.responses.patch(url, status_code=202, json=update_body)
|
||||
|
||||
# check that all parameters will be updated
|
||||
resp = self.client.jobs.update('id', name='new_name',
|
||||
description='description')
|
||||
|
||||
@@ -103,3 +104,20 @@ class JobTest(base.BaseTestCase):
|
||||
self.assertIsInstance(resp, jobs.Job)
|
||||
self.assertEqual(update_body,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that parameters will not be updated
|
||||
self.client.jobs.update("id")
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual({},
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that all parameters will be unset
|
||||
unset_json = {
|
||||
"name": None, "description": None, "is_public": None,
|
||||
"is_protected": None
|
||||
}
|
||||
|
||||
self.client.jobs.update("id", **unset_json)
|
||||
self.assertEqual(url, self.responses.last_request.url)
|
||||
self.assertEqual(unset_json,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
@@ -96,6 +96,7 @@ class NodeGroupTemplateTest(base.BaseTestCase):
|
||||
update_url = self.URL + '/node-group-templates/id'
|
||||
self.responses.put(update_url, status_code=202, json=self.update_json)
|
||||
|
||||
# check that all parameters will be updated
|
||||
updated = self.client.node_group_templates.update(
|
||||
"id",
|
||||
resp.name,
|
||||
@@ -121,3 +122,26 @@ class NodeGroupTemplateTest(base.BaseTestCase):
|
||||
use_autoconfig=False)
|
||||
self.assertIsInstance(updated, ng.NodeGroupTemplate)
|
||||
self.assertFields(self.update_json["node_group_template"], updated)
|
||||
|
||||
# check that parameters will not be updated
|
||||
self.client.node_group_templates.update("id")
|
||||
self.assertEqual(update_url, self.responses.last_request.url)
|
||||
self.assertEqual({},
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
# check that all parameters will be unset
|
||||
unset_json = {
|
||||
'auto_security_group': None, 'availability_zone': None,
|
||||
'description': None, 'flavor_id': None, 'floating_ip_pool': None,
|
||||
'hadoop_version': None, 'image_id': None, 'is_protected': None,
|
||||
'is_proxy_gateway': None, 'is_public': None, 'name': None,
|
||||
'node_configs': None, 'node_processes': None, 'plugin_name': None,
|
||||
'security_groups': None, 'shares': None, 'use_autoconfig': None,
|
||||
'volume_local_to_instance': None, 'volume_mount_prefix': None,
|
||||
'volume_type': None, 'volumes_availability_zone': None,
|
||||
'volumes_per_node': None, 'volumes_size': None}
|
||||
|
||||
self.client.node_group_templates.update("id", **unset_json)
|
||||
self.assertEqual(update_url, self.responses.last_request.url)
|
||||
self.assertEqual(unset_json,
|
||||
json.loads(self.responses.last_request.body))
|
||||
|
||||
Reference in New Issue
Block a user