def _step_delete_secret_and_build_delta( workflow: Workflow, step: Step, param: str) -> Optional[clientside.Update]: """Write a new secret (or `None`) to `step`, or raise. Return a `clientside.Update`, or `None` if the database is not modified. Raise Workflow.DoesNotExist if the Workflow was deleted. """ with workflow.cooperative_lock(): # raises Workflow.DoesNotExist try: step.refresh_from_db() except Step.DoesNotExist: return None # no-op if step.secrets.get(param) is None: return None # no-op step.secrets = dict(step.secrets) # shallow copy del step.secrets[param] step.save(update_fields=["secrets"]) return clientside.Update( steps={ step.id: clientside.StepUpdate(secrets=step.secret_metadata) })
def _step_set_secret_and_build_delta( workflow: Workflow, step: Step, param: str, secret: str) -> Optional[clientside.Update]: """Write a new secret to `step`, or raise. Return a `clientside.Update`, or `None` if the database is not modified. Raise Workflow.DoesNotExist if the Workflow was deleted. """ with workflow.cooperative_lock(): # raises Workflow.DoesNotExist try: step.refresh_from_db() except Step.DoesNotExist: return None # no-op if step.secrets.get(param, {}).get("secret") == secret: return None # no-op try: module_zipfile = MODULE_REGISTRY.latest(step.module_id_name) except KeyError: raise HandlerError( f"BadRequest: ModuleZipfile {step.module_id_name} does not exist" ) module_spec = module_zipfile.get_spec() if not any(p.type == "secret" and p.secret_logic.provider == "string" for p in module_spec.param_fields): raise HandlerError( f"BadRequest: param is not a secret string parameter") created_at = datetime.datetime.now() created_at_str = ( created_at.strftime("%Y-%m-%dT%H:%M:%S") + "." + created_at.strftime("%f")[0:3] # milliseconds + "Z") step.secrets = { **step.secrets, param: { "name": created_at_str, "secret": secret }, } step.save(update_fields=["secrets"]) return clientside.Update( steps={ step.id: clientside.StepUpdate(secrets=step.secret_metadata) })
def _locked_step(workflow_id: int, step: Step): """Refresh step from database and yield with workflow lock. Raise Workflow.DoesNotExist or Step.DoesNotExist in the event of a race. (Even soft-deleted Step or Tab raises Step.DoesNotExist, to simulate hard deletion -- because sooner or later soft-delete won't be a thing any more.) """ # raise Workflow.DoesNotExist with Workflow.lookup_and_cooperative_lock(id=workflow_id): # raise Step.DoesNotExist step.refresh_from_db() if step.is_deleted or step.tab.is_deleted: raise Step.DoesNotExist("soft-deleted") yield