def patch(self, cluster_ident, patch): """Update an existing bay. :param cluster_ident: UUID or logical name of a bay. :param patch: a json PATCH document to apply to this bay. """ context = pecan.request.context cluster = api_utils.get_resource('Bay', cluster_ident) policy.enforce(context, 'cluster:update', cluster, action='cluster:update') try: cluster_dict = cluster.as_dict() new_cluster = Cluster(**api_utils.apply_jsonpatch(cluster_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Bay.fields: try: patch_val = getattr(new_cluster, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if cluster[field] != patch_val: cluster[field] = patch_val delta = cluster.obj_what_changed() validate_bay_properties(delta) pecan.request.rpcapi.bay_update_async(cluster) return ClusterID(cluster.uuid)
def _patch(self, cluster_ident, patch): context = pecan.request.context cluster = api_utils.get_resource('Cluster', cluster_ident) policy.enforce(context, 'cluster:update', cluster.as_dict(), action='cluster:update') try: cluster_dict = cluster.as_dict() new_cluster = Cluster( **api_utils.apply_jsonpatch(cluster_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # NOTE(ttsiouts): magnum.objects.Cluster.node_count will be a # property so we won't be able to store it in the object. So # instead of object_what_changed compare the new and the old # clusters. delta = set() for field in new_cluster.fields: if getattr(cluster, field) != getattr(new_cluster, field): delta.add(field) validation.validate_cluster_properties(delta) return cluster, new_cluster.node_count
def _patch(self, cluster_uuid, nodegroup_id, patch): context = pecan.request.context policy.enforce(context, 'nodegroup:update', action='nodegroup:update') nodegroup = objects.NodeGroup.get(context, cluster_uuid, nodegroup_id) try: ng_dict = nodegroup.as_dict() new_nodegroup = NodeGroup(**api_utils.apply_jsonpatch(ng_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.NodeGroup.fields: try: patch_val = getattr(new_nodegroup, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if nodegroup[field] != patch_val: nodegroup[field] = patch_val _validate_node_count(nodegroup) return nodegroup
def patch(self, container_ident, patch): """Update an existing container. :param container_ident: UUID or name of a container. :param patch: a json PATCH document to apply to this container. """ rpc_container = api_utils.get_rpc_resource('Container', container_ident) try: container_dict = rpc_container.as_dict() container = Container( **api_utils.apply_jsonpatch(container_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Container.fields: try: patch_val = getattr(container, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_container[field] != patch_val: rpc_container[field] = patch_val rpc_container.save() return Container.convert_with_links(rpc_container)
def _patch(self, federation_ident, patch): context = pecan.request.context federation = api_utils.get_resource('Federation', federation_ident) policy.enforce(context, 'federation:update', federation.as_dict(), action='federation:update') # NOTE(clenimar): Magnum does not allow one to append items to existing # fields through an `add` operation using HTTP PATCH (please check # `magnum.api.utils.apply_jsonpatch`). In order to perform the join # and unjoin operations, intercept the original JSON PATCH document # and change the operation from either `add` or `remove` to `replace`. patch_path = patch[0].get('path') patch_value = patch[0].get('value') patch_op = patch[0].get('op') if patch_path == '/member_ids': if patch_op == 'add' and patch_value is not None: patch = self._join_wrapper(federation_ident, patch) elif patch_op == 'remove' and patch_value is not None: patch = self._unjoin_wrapper(federation_ident, patch) try: federation_dict = federation.as_dict() new_federation = Federation( **api_utils.apply_jsonpatch(federation_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Retrieve only what changed after the patch. delta = self._update_changed_fields(federation, new_federation) validation.validate_federation_properties(delta) return federation
def patch(self, node_uuid, patch): """Update an existing node. :param node_uuid: UUID of a node. :param patch: a json PATCH document to apply to this node. """ rpc_node = objects.Node.get_by_uuid(pecan.request.context, node_uuid) try: node_dict = rpc_node.as_dict() node = Node(**api_utils.apply_jsonpatch(node_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Node.fields: try: patch_val = getattr(node, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_node[field] != patch_val: rpc_node[field] = patch_val rpc_node.save() return Node.convert_with_links(rpc_node)
def _patch(self, bay_ident, patch): context = pecan.request.context bay = api_utils.get_resource('Cluster', bay_ident) policy.enforce(context, 'bay:update', bay.as_dict(), action='bay:update') try: bay_dict = bay.as_dict() new_bay = Bay(**api_utils.apply_jsonpatch(bay_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Cluster.fields: try: patch_val = getattr(new_bay, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if bay[field] != patch_val: bay[field] = patch_val delta = bay.obj_what_changed() validate_cluster_properties(delta) return bay
def patch(self, bay_ident, patch): """Update an existing bay. :param bay_ident: UUID or logical name of a bay. :param patch: a json PATCH document to apply to this bay. """ context = pecan.request.context bay = api_utils.get_resource('Bay', bay_ident) policy.enforce(context, 'bay:update', bay, action='bay:update') try: bay_dict = bay.as_dict() new_bay = Bay(**api_utils.apply_jsonpatch(bay_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Bay.fields: try: patch_val = getattr(new_bay, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if bay[field] != patch_val: bay[field] = patch_val delta = bay.obj_what_changed() validate_bay_properties(delta) res_bay = pecan.request.rpcapi.bay_update(bay) return Bay.convert_with_links(res_bay)
def _patch(self, bay_ident, patch): context = pecan.request.context bay = api_utils.get_resource('Cluster', bay_ident) policy.enforce(context, 'bay:update', bay.as_dict(), action='bay:update') bay_to_cluster_attrs = { 'baymodel_id': 'cluster_template_id', 'bay_create_timeout': 'create_timeout' } try: bay_dict = bay.as_dict() new_bay = Bay(**api_utils.apply_jsonpatch(bay_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # NOTE(ttsiouts): magnum.objects.Cluster.node_count will be a # property so we won't be able to store it in the object. So # instead of object_what_changed compare the new and the old # clusters. delta = set() for field in new_bay.fields: cluster_field = field if cluster_field in bay_to_cluster_attrs: cluster_field = bay_to_cluster_attrs[field] if cluster_field not in bay_dict: continue if getattr(new_bay, field) != bay_dict[cluster_field]: delta.add(cluster_field) validate_cluster_properties(delta) return bay, new_bay.node_count
def _patch(self, bay_ident, patch): context = pecan.request.context bay = api_utils.get_resource('Bay', bay_ident) policy.enforce(context, 'bay:update', bay, action='bay:update') try: bay_dict = bay.as_dict() new_bay = Bay(**api_utils.apply_jsonpatch(bay_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Bay.fields: try: patch_val = getattr(new_bay, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if bay[field] != patch_val: bay[field] = patch_val delta = bay.obj_what_changed() validate_bay_properties(delta) return bay
def _patch(self, cluster_ident, patch): context = pecan.request.context cluster = api_utils.get_resource('Cluster', cluster_ident) policy.enforce(context, 'cluster:update', cluster.as_dict(), action='cluster:update') try: cluster_dict = cluster.as_dict() new_cluster = Cluster(**api_utils.apply_jsonpatch(cluster_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Cluster.fields: try: patch_val = getattr(new_cluster, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if cluster[field] != patch_val: cluster[field] = patch_val delta = cluster.obj_what_changed() validation.validate_cluster_properties(delta) return cluster
def patch(self, container_ident, patch): """Update an existing container. :param container_ident: UUID or name of a container. :param patch: a json PATCH document to apply to this container. """ rpc_container = api_utils.get_rpc_resource('Container', container_ident) try: container_dict = rpc_container.as_dict() container = Container(**api_utils.apply_jsonpatch( container_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Container.fields: try: patch_val = getattr(container, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_container[field] != patch_val: rpc_container[field] = patch_val rpc_container.save() return Container.convert_with_links(rpc_container)
def patch(self, cluster_template_ident, patch): """Update an existing ClusterTemplate. :param cluster_template_ident: UUID or logic name of a ClusterTemplate. :param patch: a json PATCH document to apply to this ClusterTemplate. """ context = pecan.request.context if context.is_admin: policy.enforce(context, 'clustertemplate:update_all_projects', action='clustertemplate:update_all_projects') context.all_tenants = True cluster_template = api_utils.get_resource('ClusterTemplate', cluster_template_ident) policy.enforce(context, 'clustertemplate:update', cluster_template.as_dict(), action='clustertemplate:update') try: cluster_template_dict = cluster_template.as_dict() new_cluster_template = ClusterTemplate( **api_utils.apply_jsonpatch(cluster_template_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) new_cluster_template_dict = new_cluster_template.as_dict() attr_validator.validate_os_resources(context, new_cluster_template_dict) # check permissions when updating ClusterTemplate public or hidden flag if (cluster_template.public != new_cluster_template.public or cluster_template.hidden != new_cluster_template.hidden): if not policy.enforce( context, "clustertemplate:publish", None, do_raise=False): raise exception.ClusterTemplatePublishDenied() # Update only the fields that have changed for field in objects.ClusterTemplate.fields: try: patch_val = getattr(new_cluster_template, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if cluster_template[field] != patch_val: cluster_template[field] = patch_val if (cluster_template.docker_storage_driver in ('devicemapper', 'overlay')): warnings.warn(self._devicemapper_overlay_deprecation_note, DeprecationWarning) LOG.warning(self._devicemapper_overlay_deprecation_note) cluster_template.save() return ClusterTemplate.convert_with_links(cluster_template)
def wrapper(func, *args, **kwargs): baymodel_ident = args[1] patch = args[2] baymodel = api_utils.get_rpc_resource('BayModel', baymodel_ident) try: baymodel_dict = api_utils.apply_jsonpatch(baymodel.as_dict(), patch) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) _enforce_volume_driver_types(baymodel_dict) return func(*args, **kwargs)
def wrapper(func, *args, **kwargs): baymodel_ident = args[1] patch = args[2] baymodel = api_utils.get_resource('BayModel', baymodel_ident) try: baymodel_dict = api_utils.apply_jsonpatch(baymodel.as_dict(), patch) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) _enforce_volume_driver_types(baymodel_dict) return func(*args, **kwargs)
def wrapper(func, *args, **kwargs): cluster_template_ident = args[1] patch = args[2] cluster_template = api_utils.get_resource('ClusterTemplate', cluster_template_ident) try: cluster_template_dict = api_utils.apply_jsonpatch( cluster_template.as_dict(), patch) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) _enforce_volume_driver_types(cluster_template_dict) return func(*args, **kwargs)
def wrapper(func, *args, **kwargs): baymodel_ident = args[1] patch = args[2] baymodel = api_utils.get_rpc_resource('BayModel', baymodel_ident) try: baymodel_dict = api_utils.apply_jsonpatch(baymodel.as_dict(), patch) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) baymodel = objects.BayModel(pecan.request.context, **baymodel_dict) _enforce_network_driver_types(baymodel) return func(*args, **kwargs)
def wrapper(func, *args, **kwargs): cluster_template_ident = args[1] patch = args[2] cluster_template = api_utils.get_resource('ClusterTemplate', cluster_template_ident) try: cluster_template_dict = api_utils.apply_jsonpatch( cluster_template.as_dict(), patch) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) cluster_template = objects.ClusterTemplate(pecan.request.context, **cluster_template_dict) _enforce_network_driver_types(cluster_template) return func(*args, **kwargs)
def patch(self, cluster_template_ident, patch): """Update an existing ClusterTemplate. :param cluster_template_ident: UUID or logic name of a ClusterTemplate. :param patch: a json PATCH document to apply to this ClusterTemplate. """ context = pecan.request.context if context.is_admin: policy.enforce(context, 'clustertemplate:update_all_projects', action='clustertemplate:update_all_projects') context.all_tenants = True cluster_template = api_utils.get_resource('ClusterTemplate', cluster_template_ident) policy.enforce(context, 'clustertemplate:update', cluster_template.as_dict(), action='clustertemplate:update') try: cluster_template_dict = cluster_template.as_dict() new_cluster_template = ClusterTemplate(**api_utils.apply_jsonpatch( cluster_template_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) new_cluster_template_dict = new_cluster_template.as_dict() attr_validator.validate_os_resources(context, new_cluster_template_dict) # check permissions when updating ClusterTemplate public or hidden flag if (cluster_template.public != new_cluster_template.public or cluster_template.hidden != new_cluster_template.hidden): if not policy.enforce(context, "clustertemplate:publish", None, do_raise=False): raise exception.ClusterTemplatePublishDenied() # Update only the fields that have changed for field in objects.ClusterTemplate.fields: try: patch_val = getattr(new_cluster_template, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if cluster_template[field] != patch_val: cluster_template[field] = patch_val cluster_template.save() return ClusterTemplate.convert_with_links(cluster_template)
def _patch(self, cluster_ident, patch): context = pecan.request.context if context.is_admin: policy.enforce(context, "cluster:update_all_projects", action="cluster:update_all_projects") context.all_tenants = True cluster = api_utils.get_resource('Cluster', cluster_ident) policy.enforce(context, 'cluster:update', cluster.as_dict(), action='cluster:update') policy.enforce(context, "cluster:update_health_status", action="cluster:update_health_status") try: cluster_dict = cluster.as_dict() new_cluster = Cluster( **api_utils.apply_jsonpatch(cluster_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # NOTE(ttsiouts): magnum.objects.Cluster.node_count will be a # property so we won't be able to store it in the object. So # instead of object_what_changed compare the new and the old # clusters. delta = set() for field in new_cluster.fields: if getattr(cluster, field) != getattr(new_cluster, field): delta.add(field) validation.validate_cluster_properties(delta) # NOTE(brtknr): cluster.node_count is the size of the whole cluster # which includes non-default nodegroups. However cluster_update expects # node_count to be the size of the default_ng_worker therefore return # this value unless the patch object says otherwise. node_count = cluster.default_ng_worker.node_count for p in patch: if p['path'] == '/node_count': node_count = p.get('value') or new_cluster.node_count return (cluster, node_count, new_cluster.health_status, new_cluster.health_status_reason)
def patch(self, cluster_template_ident, patch): """Update an existing ClusterTemplate. :param cluster_template_ident: UUID or logic name of a ClusterTemplate. :param patch: a json PATCH document to apply to this ClusterTemplate. """ context = pecan.request.context cluster_template = api_utils.get_resource('ClusterTemplate', cluster_template_ident) policy.enforce(context, 'clustertemplate:update', cluster_template.as_dict(), action='clustertemplate:update') try: cluster_template_dict = cluster_template.as_dict() new_cluster_template = ClusterTemplate(**api_utils.apply_jsonpatch( cluster_template_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) new_cluster_template_dict = new_cluster_template.as_dict() attr_validator.validate_os_resources(context, new_cluster_template_dict) # check permissions when updating ClusterTemplate public flag if cluster_template.public != new_cluster_template.public: if not policy.enforce(context, "clustertemplate:publish", None, do_raise=False): raise exception.ClusterTemplatePublishDenied() # Update only the fields that have changed for field in objects.ClusterTemplate.fields: try: patch_val = getattr(new_cluster_template, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if cluster_template[field] != patch_val: cluster_template[field] = patch_val cluster_template.save() return ClusterTemplate.convert_with_links(cluster_template)
def patch(self, rc_ident, bay_ident, patch): """Update an existing rc. :param rc_ident: UUID or logical name of a ReplicationController. :param bay_ident: UUID or logical name of the Bay. :param patch: a json PATCH document to apply to this rc. """ rc_dict = {} rc_dict["manifest"] = None rc_dict["manifest_url"] = None try: rc = ReplicationController(**api_utils.apply_jsonpatch(rc_dict, patch)) if rc.manifest or rc.manifest_url: rc.parse_manifest() except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) rpc_rc = pecan.request.rpcapi.rc_update(rc_ident, bay_ident, rc.manifest) return ReplicationController.convert_with_links(rpc_rc)
def patch(self, pod_ident, bay_ident, patch): """Update an existing pod. :param pod_ident: UUID or logical name of a pod. :param bay_ident: UUID or logical name of the Bay. :param patch: a json PATCH document to apply to this pod. """ pod_dict = {} pod_dict['manifest'] = None pod_dict['manifest_url'] = None try: pod = Pod(**api_utils.apply_jsonpatch(pod_dict, patch)) if pod.manifest or pod.manifest_url: pod.parse_manifest() except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) rpc_pod = pecan.request.rpcapi.pod_update(pod_ident, bay_ident, pod.manifest) return Pod.convert_with_links(rpc_pod)
def patch(self, service_ident, bay_ident, patch): """Update an existing service. :param service_ident: UUID or logical name of a service. :param bay_ident: UUID or logical name of the Bay. :param patch: a json PATCH document to apply to this service. """ service_dict = {} service_dict['manifest'] = None service_dict['manifest_url'] = None try: service = Service(**api_utils.apply_jsonpatch(service_dict, patch)) if service.manifest or service.manifest_url: service.parse_manifest() except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) rpc_service = pecan.request.rpcapi.service_update( service_ident, bay_ident, service.manifest) return Service.convert_with_links(rpc_service)
def patch(self, baymodel_ident, patch): """Update an existing baymodel. :param baymodel_ident: UUID or logic name of a baymodel. :param patch: a json PATCH document to apply to this baymodel. """ context = pecan.request.context baymodel = api_utils.get_resource('BayModel', baymodel_ident) policy.enforce(context, 'baymodel:update', baymodel, action='baymodel:update') try: baymodel_dict = baymodel.as_dict() new_baymodel = BayModel( **api_utils.apply_jsonpatch(baymodel_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) new_baymodel_dict = new_baymodel.as_dict() attr_validator.validate_os_resources(context, new_baymodel_dict) # check permissions when updating baymodel public flag if baymodel.public != new_baymodel.public: if not policy.enforce( context, "baymodel:publish", None, do_raise=False): raise exception.BaymodelPublishDenied() # Update only the fields that have changed for field in objects.BayModel.fields: try: patch_val = getattr(new_baymodel, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if baymodel[field] != patch_val: baymodel[field] = patch_val baymodel.save() return BayModel.convert_with_links(baymodel)
def patch(self, service_ident, bay_ident, patch): """Update an existing service. :param service_ident: UUID or logical name of a service. :param bay_ident: UUID or logical name of the Bay. :param patch: a json PATCH document to apply to this service. """ service_dict = {} service_dict['manifest'] = None service_dict['manifest_url'] = None try: service = Service(**api_utils.apply_jsonpatch(service_dict, patch)) if service.manifest or service.manifest_url: service.parse_manifest() except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) rpc_service = pecan.request.rpcapi.service_update(service_ident, bay_ident, service.manifest) return Service.convert_with_links(rpc_service)
def patch(self, baymodel_ident, patch): """Update an existing baymodel. :param baymodel_ident: UUID or logic name of a baymodel. :param patch: a json PATCH document to apply to this baymodel. """ context = pecan.request.context baymodel = api_utils.get_resource('BayModel', baymodel_ident) policy.enforce(context, 'baymodel:update', baymodel, action='baymodel:update') try: baymodel_dict = baymodel.as_dict() new_baymodel = BayModel(**api_utils.apply_jsonpatch( baymodel_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) new_baymodel_dict = new_baymodel.as_dict() attr_validator.validate_os_resources(context, new_baymodel_dict) # check permissions when updating baymodel public flag if baymodel.public != new_baymodel.public: if not policy.enforce(context, "baymodel:publish", None, do_raise=False): raise exception.ClusterTemplatePublishDenied() # Update only the fields that have changed for field in objects.BayModel.fields: try: patch_val = getattr(new_baymodel, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if baymodel[field] != patch_val: baymodel[field] = patch_val baymodel.save() return BayModel.convert_with_links(baymodel)
def patch(self, rc_ident, bay_ident, patch): """Update an existing rc. :param rc_ident: UUID or logical name of a ReplicationController. :param bay_ident: UUID or logical name of the Bay. :param patch: a json PATCH document to apply to this rc. """ rc_dict = {} rc_dict['manifest'] = None rc_dict['manifest_url'] = None try: rc = ReplicationController(**api_utils.apply_jsonpatch(rc_dict, patch)) if rc.manifest or rc.manifest_url: rc.parse_manifest() except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) rpc_rc = pecan.request.rpcapi.rc_update(rc_ident, bay_ident, rc.manifest) return ReplicationController.convert_with_links(rpc_rc)
def patch(self, cluster_ident, patch): """Update an existing bay. :param cluster_ident: UUID or logical name of a bay. :param patch: a json PATCH document to apply to this bay. """ context = pecan.request.context cluster = api_utils.get_resource('Bay', cluster_ident) policy.enforce(context, 'cluster:update', cluster, action='cluster:update') try: cluster_dict = cluster.as_dict() new_cluster = Cluster( **api_utils.apply_jsonpatch(cluster_dict, patch)) except api_utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Update only the fields that have changed for field in objects.Bay.fields: try: patch_val = getattr(new_cluster, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if cluster[field] != patch_val: cluster[field] = patch_val delta = cluster.obj_what_changed() validate_bay_properties(delta) pecan.request.rpcapi.bay_update_async(cluster) return ClusterID(cluster.uuid)
def test_apply_jsonpatch(self, mock_jsonpatch): doc = {'cluster_uuid': 'id', 'node_count': 1} patch = [{"path": "/node_count", "value": 2, "op": "replace"}] utils.apply_jsonpatch(doc, patch) mock_jsonpatch.assert_called_once_with(doc, patch)
def test_apply_jsonpatch(self, mock_jsonpatch): doc = {'bay_uuid': 'id', 'node_count': 1} patch = [{"path": "/node_count", "value": 2, "op": "replace"}] utils.apply_jsonpatch(doc, patch) mock_jsonpatch.assert_called_once_with(doc, patch)