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) _enforce_volume_driver_types(cluster_template_dict) 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 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_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, 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('ClusterTemplate', baymodel_ident) policy.enforce(context, 'baymodel:update', baymodel.as_dict(), 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.ClusterTemplate.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 apply_jsonpatch(doc, patch): for p in patch: if p['op'] == 'add' and p['path'].count('/') == 1: attr = p['path'].lstrip('/') if attr not in doc: msg = _("Adding a new attribute %s to the root of " "the resource is not allowed.") % p['path'] raise wsme.exc.ClientSideError(msg) if doc[attr] is not None: msg = _("The attribute %s has existed, please use " "'replace' operation instead.") % p['path'] raise wsme.exc.ClientSideError(msg) if p['op'] == 'replace' and p['path'] == '/labels': try: val = p['value'] dict_val = val if type(val) == dict else ast.literal_eval(val) p['value'] = dict_val except (SyntaxError, ValueError, AssertionError) as e: raise exception.PatchError(patch=patch, reason=e) return jsonpatch.apply_patch(doc, patch)
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, rc_uuid, patch): """Update an existing rc. :param rc_uuid: UUID of a ReplicationController. :param patch: a json PATCH document to apply to this rc. """ if self.from_rcs: raise exception.OperationNotPermitted rpc_rc = objects.ReplicationController.get_by_uuid( pecan.request.context, rc_uuid) try: rc_dict = rpc_rc.as_dict() rc = ReplicationController(**api_utils.apply_jsonpatch(rc_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.ReplicationController.fields: # ignore manifest_url as it was used for create rc if field == 'manifest_url': continue # ignore manifest as it was used for create rc if field == 'manifest': continue try: patch_val = getattr(rc, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_rc[field] != patch_val: rpc_rc[field] = patch_val rpc_rc.save() return ReplicationController.convert_with_links(rpc_rc)
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. """ rpc_rc = api_utils.get_rpc_resource('ReplicationController', rc_ident) # Init manifest and manifest_url field because we don't store them # in database. rpc_rc['manifest'] = None rpc_rc['manifest_url'] = None try: rc_dict = rpc_rc.as_dict() 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) # Update only the fields that have changed for field in objects.ReplicationController.fields: try: patch_val = getattr(rc, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_rc[field] != patch_val: rpc_rc[field] = patch_val if rc.manifest or rc.manifest_url: pecan.request.rpcapi.rc_update(rpc_rc) else: rpc_rc.save() 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. """ rpc_pod = api_utils.get_rpc_resource('Pod', pod_ident) # Init manifest and manifest_url field because we don't store them # in database. rpc_pod['manifest'] = None rpc_pod['manifest_url'] = None try: pod_dict = rpc_pod.as_dict() 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) # Update only the fields that have changed for field in objects.Pod.fields: try: patch_val = getattr(pod, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_pod[field] != patch_val: rpc_pod[field] = patch_val if pod.manifest or pod.manifest_url: pecan.request.rpcapi.pod_update(rpc_pod) else: rpc_pod.save() return Pod.convert_with_links(rpc_pod)
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, service_ident, patch): """Update an existing service. :param service_ident: UUID or logical name of a service. :param patch: a json PATCH document to apply to this service. """ rpc_service = api_utils.get_rpc_resource('Service', service_ident) # Init manifest and manifest_url field because we don't store them # in database. rpc_service['manifest'] = None rpc_service['manifest_url'] = None try: service_dict = rpc_service.as_dict() 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) # Update only the fields that have changed for field in objects.Service.fields: try: patch_val = getattr(service, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_service[field] != patch_val: rpc_service[field] = patch_val if service.manifest or service.manifest_url: pecan.request.rpcapi.service_update(rpc_service) else: rpc_service.save() return Service.convert_with_links(rpc_service)
def patch(self, service_uuid, patch): """Update an existing service. :param service_uuid: UUID of a service. :param patch: a json PATCH document to apply to this service. """ if self.from_services: raise exception.OperationNotPermitted rpc_service = objects.Service.get_by_uuid(pecan.request.context, service_uuid) try: service_dict = rpc_service.as_dict() service = Service(**api_utils.apply_jsonpatch(service_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.Service.fields: # ignore manifest_url as it was used for create service if field == 'manifest_url': continue if field == 'manifest': continue try: patch_val = getattr(service, field) except AttributeError: # Ignore fields that aren't exposed in the API continue if patch_val == wtypes.Unset: patch_val = None if rpc_service[field] != patch_val: rpc_service[field] = patch_val rpc_service.save() return Service.convert_with_links(rpc_service)
def test_PatchError(self): self.assertRaises(exception.PatchError, lambda: self.raise_(exception.PatchError()))