def test_tags_validation_error(self): for agent_foobar in self.models(limit=1): tag = Tag() tag.agents = [agent_foobar] tag.tag = None with self.assertRaises(DatabaseError): db.session.add(tag) db.session.commit()
def put(self, tagname=None): """ A ``PUT`` to this endpoint will create a new tag under the given URI. If a tag already exists under that URI, it will be deleted, then recreated. Note that when overwriting a tag like that, all relations that are not explicitly specified here will be deleted You can optionally specify a list of agents or jobs relations as integers in the request data. You should only call this by id for overwriting an existing tag or if you have a reserved tag id. There is currently no way to reserve a tag id. .. http:put:: /api/v1/tags/<str:tagname> HTTP/1.1 **Request** .. sourcecode:: http PUT /api/v1/tags/interesting HTTP/1.1 Accept: application/json { "tag": "interesting" } **Response** .. sourcecode:: http HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1, "tag": "interesting" } **Request** .. sourcecode:: http PUT /api/v1/tags/interesting HTTP/1.1 Accept: application/json { "tag": "interesting", "agents": [1] "jobs": [] } **Response** .. sourcecode:: http HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1, "tag": "interesting" } :statuscode 201: a new tag was created :statuscode 400: there was something wrong with the request (such as invalid columns being included) :statuscode 404: a referenced agent or job does not exist """ if isinstance(tagname, int): tag = Tag.query.filter_by(id=tagname).first() if "tag" in g.json and g.json["tag"] != tag.tag: error = "tag name retrieved for %s does not match tag " \ "name in request" % tagname return jsonify(error=error), BAD_REQUEST g.json.setdefault("tag", tag.tag) elif isinstance(tagname, STRING_TYPES): g.json.setdefault("tag", tagname) if g.json["tag"] != tagname: return jsonify(error="`tag` in data must be equal to the " "tag in the requested url"), BAD_REQUEST tag = Tag.query.filter_by(tag=g.json["tag"]).first() # If tag exists, delete it before recreating it if tag: logger.debug( "tag %s will be replaced with %r on commit", tag.tag, g.json) db.session.delete(tag) db.session.flush() agents = [] if "agents" in g.json: agent_ids = g.json.pop("agents", []) if not isinstance(agent_ids, list): return jsonify(error="agents must be a list"), BAD_REQUEST try: agent_ids = list(map(UUID, agent_ids)) except (ValueError, AttributeError): return jsonify(error="All agent ids must be UUIDs"), BAD_REQUEST # find all models matching the request id(s) agents = Agent.query.filter(Agent.id.in_(agent_ids)).all() # make sure all those ids were actually found missing_agents = set(agent_ids) - set(agent.id for agent in agents) if missing_agents: return jsonify( error="agent(s) not found: %s" % missing_agents), NOT_FOUND jobs = [] if "jobs" in g.json: job_ids = g.json.pop("jobs", []) if not isinstance(job_ids, list): return jsonify(error="jobs must be a list"), BAD_REQUEST # make sure all ids provided are ints if not all(isinstance(job_id, int) for job_id in job_ids): return jsonify( error="all job ids must be integers"), BAD_REQUEST # find all models matching the request id(s) jobs = Job.query.filter(Agent.id.in_(job_ids)).all() # make sure all those ids were actually found missing_jobs = set(job_ids) - set(job.id for job in jobs) if missing_jobs: return jsonify( error="job(s) not found: %s" % missing_jobs), NOT_FOUND new_tag = Tag(**g.json) if isinstance(tagname, int): new_tag.id = tagname new_tag.agents = agents new_tag.jobs = jobs logger.info("creating tag %s: %r", new_tag.tag, new_tag.to_dict()) db.session.add(new_tag) db.session.commit() return (jsonify(new_tag.to_dict(unpack_relationships=("agents", "jobs"))), CREATED)