async def post(self, request, tid): """ Publish a draft into production """ try: tmpl_dict = await self.nyuki.storage.get_template(tid, draft=True) except AutoReconnect: return Response(status=503) if not tmpl_dict: return Response(status=404) try: # Set template ID from url template = WorkflowTemplate.from_dict(tmpl_dict) except TemplateGraphError as exc: return Response(status=400, body={'error': str(exc)}) errors = self.errors_from_validation(template) if errors is not None: return Response(errors, status=400) # Update draft into a new template await self.nyuki.storage.publish_draft(tid) tmpl_dict['state'] = TemplateState.ACTIVE.value return Response(tmpl_dict)
async def post(self, request, tid): """ Publish a draft into production """ try: tmpl = await self.nyuki.storage.templates.get(tid, draft=True) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) draft = {**tmpl[0], 'draft': False} try: # Set template ID from url template = WorkflowTemplate.from_dict({**draft, 'draft': False}) except TemplateGraphError as exc: return Response(status=400, body={'error': str(exc)}) errors = self.errors_from_validation(template) if errors is not None: return Response(status=400, body=errors) await self.nyuki.engine.load(template) # Update draft into a new template await self.nyuki.storage.templates.publish_draft(tid) return Response(draft)
async def put(self, request): """ Create a workflow DAG from JSON """ request = await request.json() if 'id' in request: del request['id'] if 'title' not in request: return Response(status=400, body={'error': "workflow 'title' is mandatory"}) if self.nyuki.DEFAULT_POLICY is not None and 'policy' not in request: request['policy'] = self.nyuki.DEFAULT_POLICY try: template = WorkflowTemplate.from_dict(request) except TemplateGraphError as exc: return Response(status=400, body={'error': str(exc)}) try: tmpl_dict = await self.upsert_draft(template, request) except DuplicateKeyError as exc: return Response(status=409, body={'error': exc}) tmpl_dict['errors'] = self.errors_from_validation(template) return Response(tmpl_dict)
async def post(self, request, iid): """ Suspend/resume a runnning workflow. """ try: wf = self.nyuki.running_workflows[iid] except KeyError: return Response(status=404) request = await request.json() try: action = request['action'] except KeyError: return Response(status=400, body={'action parameter required'}) # Should we return 409 Conflict if the status is already set ? if action == 'suspend': wf.instance.suspend() elif action == 'resume': wf.instance.resume() else: return Response(status=400, body={"action must be 'suspend' or 'resume'"}) return Response(wf.report())
async def put(self, request): """ Upload a trigger form file """ data = await request.post() try: form = data['form'] tid = data['tid'] except KeyError: return Response( status=400, body={'error': "'form' and 'tid' are mandatory parameters"}) if not isinstance(form, FileField): return Response( status=400, body={'error': "'form' field must be a file content"}) content = form.file.read().decode('utf-8') try: tmpl = await self.nyuki.storage.templates.get(tid) if not tmpl: return Response(status=404) trigger = await self.nyuki.storage.triggers.insert(tid, content) except AutoReconnect: return Response(status=503) return Response(trigger)
async def patch(self, request, tid): """ Modify the template's draft """ try: tmpl = await self.nyuki.storage.templates.get(tid, draft=True) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) request = await request.json() try: # Set template ID from url template = WorkflowTemplate.from_dict({**request, 'id': tid}) except TemplateGraphError as exc: return Response(status=400, body={'error': str(exc)}) try: tmpl_dict = await self.update_draft(template, request) except ConflictError as exc: return Response(status=409, body={'error': str(exc)}) metadata = await self.nyuki.storage.templates.get_metadata(template.uid ) metadata = metadata[0] return Response({ **tmpl_dict, **metadata, 'errors': self.errors_from_validation(template) })
async def patch(self, request, tid): """ Modify the template's draft """ try: tmpl = await self.nyuki.storage.get_template(tid, draft=True) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) request = await request.json() try: # Set template ID from url template = WorkflowTemplate.from_dict({**request, 'id': tid}) except TemplateGraphError as exc: return Response(status=400, body={'error': str(exc)}) try: tmpl_dict = await self.upsert_draft(template, request) except DuplicateKeyError as exc: return Response(status=409, body={'error': str(exc)}) tmpl_dict['errors'] = self.errors_from_validation(template) return Response(tmpl_dict)
async def patch(self, request, regex_id): """ Modify an existing regex """ try: regex = await self.nyuki.storage.regexes.get_one(regex_id) except AutoReconnect: return Response(status=503) if not regex: return Response(status=404) request = await request.json() try: regex = new_regex( request.get('title', regex['title']), request.get('pattern', regex['pattern']), regex_id=regex_id ) except re_error as exc: return Response(status=400, body={ 'error': 'invalid regular expression {}'.format(exc), 'error_code': 'invalid_regex' }) await self.nyuki.storage.regexes.insert(regex) return Response(regex)
async def get(self, request, iid): """ Return a workflow instance """ try: return Response(self.nyuki.running_workflows[iid].report()) except KeyError: return Response(status=404)
async def get(self, request, uid, task_id): try: task = await self.nyuki.storage.get_instance_task_data(task_id) except AutoReconnect: return Response(status=503) if not task: return Response(status=404) return Response(task)
async def get(self, request, uid): try: workflow = await self.nyuki.storage.instances.get_one(uid) except AutoReconnect: return Response(status=503) if not workflow: return Response(status=404) return Response(workflow)
async def get(self, request): """ Return the list of all lookups """ try: lookups = await self.nyuki.storage.lookups.get() except AutoReconnect: return Response(status=503) return Response(lookups)
async def get(self, request, uid): try: workflow = await self.nyuki.storage.get_instance( uid, (request.GET.get('full') == '1')) except AutoReconnect: return Response(status=503) if not workflow: return Response(status=404) return Response(workflow)
async def get(self, request): """ Return the list of all regexes """ try: regexes = await self.nyuki.storage.regexes.get() except AutoReconnect: return Response(status=503) return Response(regexes)
async def get(self, request): """ Return the list of all trigger forms """ try: triggers = await self.nyuki.storage.triggers.get_all() except AutoReconnect: return Response(status=503) return Response(triggers)
async def delete(self, request): """ Delete all regexes and return the list """ try: rules = await self.nyuki.storage.regexes.get() except AutoReconnect: return Response(status=503) await self.nyuki.storage.regexes.delete() return Response(rules)
async def get(self, request): """ Return available workflows' DAGs """ try: templates = await self.nyuki.storage.get_templates( full=(request.GET.get('full') == '1'), ) except AutoReconnect: return Response(status=503) return Response(templates)
async def delete(self, request): """ Delete all lookups and return the list """ try: lookups = await self.nyuki.storage.lookups.get() except AutoReconnect: return Response(status=503) await self.nyuki.storage.lookups.delete() return Response(lookups)
async def get(self, request, lookup_id): """ Return the lookup table for id `lookup_id` """ try: lookup = await self.nyuki.storage.lookups.get_one(lookup_id) except AutoReconnect: return Response(status=503) if not lookup: return Response(status=404) return Response(lookup)
async def get(self, request, tid): """ Return a single trigger form """ try: trigger = await self.nyuki.storage.triggers.get(tid) except AutoReconnect: return Response(status=503) if not trigger: return Response(status=404) return Response(trigger)
async def get(self, request, regex_id): """ Return the regex for id `regex_id` """ try: regex = await self.nyuki.storage.regexes.get_one(regex_id) except AutoReconnect: return Response(status=503) if not regex: return Response(status=404) return Response(regex)
async def get(self, request, tid): """ Return the latest version of the template """ try: tmpl = await self.nyuki.storage.get_templates(tid, full=True) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) return Response(tmpl)
async def get(self, request, tid): """ Return the template's draft, if any """ try: tmpl = await self.nyuki.storage.get_template(tid, draft=True) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) return Response(tmpl)
async def get(self, request, tid, version): """ Return the template's given version """ try: tmpl = await self.nyuki.storage.get_template(tid, version=version) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) return Response(tmpl)
async def get(self, request, iid, tid): """ Return all the current reporting data for this task. """ try: workflow = self.nyuki.running_workflows[iid].instance for task in workflow.tasks: if task.uid == tid: return Response(task.holder.report() or {}) else: return Response(status=404) except KeyError: return Response(status=404)
async def delete(self, request, lookup_id): """ Delete the lookup table with id `lookup_id` """ try: lookup = await self.nyuki.storage.lookups.get_one(lookup_id) except AutoReconnect: return Response(status=503) if not lookup: return Response(status=404) await self.nyuki.storage.lookups.delete(lookup_id) return Response(lookup)
async def delete(self, request, tid): """ Delete a trigger form """ try: trigger = await self.nyuki.storage.triggers.get_one(tid) except AutoReconnect: return Response(status=503) if not trigger: return Response(status=404) await self.nyuki.storage.triggers.delete(tid) return Response(trigger)
async def delete(self, request, regex_id): """ Delete the regex with id `regex_id` """ try: regex = await self.nyuki.storage.regexes.get_one(regex_id) except AutoReconnect: return Response(status=503) if not regex: return Response(status=404) await self.nyuki.storage.regexes.delete(regex_id) return Response(regex)
async def delete(self, request, tid, version): """ Delete a template with given version """ try: tmpl = await self.nyuki.storage.templates.get(tid) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) await self.nyuki.storage.templates.delete(tid, version) return Response(tmpl[0])
async def delete(self, request, tid): """ Delete the template's draft """ try: tmpl = await self.nyuki.storage.templates.get(tid, draft=True) except AutoReconnect: return Response(status=503) if not tmpl: return Response(status=404) await self.nyuki.storage.templates.delete(tid, draft=True) return Response(tmpl[0])