diff --git a/dci/api/v1/files.py b/dci/api/v1/files.py index 485ee9ddd..97bb9a6c5 100644 --- a/dci/api/v1/files.py +++ b/dci/api/v1/files.py @@ -193,7 +193,8 @@ def create_files(user): result = {"file": new_file} # Update job duration if it's jobstate's file - base.update_resource_orm(job, {"duration": get_job_duration(job)}) + if values.get("jobstate_id"): + base.update_resource_orm(job, {"duration": get_job_duration(job)}) gc.collect() if new_file["mime"] == "application/junit": @@ -203,6 +204,13 @@ def create_files(user): except xml.etree.ElementTree.ParseError as xmlerror: raise dci_exc.DCIException(message="Invalid XML: " + xmlerror.msg) + job.etag = utils.gen_etag() + try: + flask.g.session.commit() + except Exception as e: + flask.g.session.rollback() + raise dci_exc.DCIException(message=str(e), status_code=409) + return flask.Response(json.dumps(result), 201, content_type="application/json") @@ -277,8 +285,16 @@ def delete_file_by_id(user, file_id): if not user.is_in_team(file.team_id): raise dci_exc.Unauthorized() - base.update_resource_orm(file, {"state": "archived"}) + + job = base.get_resource_orm(models2.Job, file.job_id) + job.etag = utils.gen_etag() + try: + flask.g.session.commit() + except Exception as e: + flask.g.session.rollback() + raise dci_exc.DCIException(message=str(e), status_code=409) + return flask.Response(None, 204, content_type="application/json") diff --git a/dci/api/v1/jobs_kv.py b/dci/api/v1/jobs_kv.py index 835ae7e97..58ae0344f 100644 --- a/dci/api/v1/jobs_kv.py +++ b/dci/api/v1/jobs_kv.py @@ -28,6 +28,7 @@ create_job_kv_schema, delete_job_kv_schema, ) +from dci.common import utils from dci.db import models2 @@ -47,6 +48,13 @@ def add_kv_to_job(user, job_id): values["job_id"] = job_id jkv = base.create_resource_orm(models2.JobKeyValue, values) + job.etag = utils.gen_etag() + + try: + flask.g.session.commit() + except Exception as e: + flask.g.session.rollback() + raise dci_exc.DCIException(message=str(e), status_code=409) return flask.Response( json.dumps({"kv": jkv}), @@ -66,6 +74,8 @@ def delete_kv_from_job(user, job_id): if user.is_not_in_team(job.team_id) and user.is_not_epm(): raise dci_exc.Unauthorized() + job.etag = utils.gen_etag() + try: flask.g.session.query(models2.JobKeyValue).filter( sql.and_( diff --git a/tests/api/v1/test_files.py b/tests/api/v1/test_files.py index b6bf5033d..60d9d3056 100644 --- a/tests/api/v1/test_files.py +++ b/tests/api/v1/test_files.py @@ -45,6 +45,25 @@ def test_create_files(user, jobstate_user_id): assert file["size"] == 7 +def test_job_update_on_creation_deletion_file(user, job_user_id): + job = user.get("/api/v1/jobs/%s" % job_user_id).data["job"] + job_updated_at = job["updated_at"] + + file_id = t_utils.create_file( + user, job_user_id, "name", content="c", content_type="text/plain" + )["id"] + + job = user.get("/api/v1/jobs/%s" % job_user_id).data["job"] + assert job_updated_at != job["updated_at"] + + job_updated_at = job["updated_at"] + + user.delete("/api/v1/files/%s" % str(file_id)) + + job = user.get("/api/v1/jobs/%s" % job_user_id).data["job"] + assert job_updated_at != job["updated_at"] + + def test_create_files_jobstate_id_and_job_id_missing(admin): file = admin.post("/api/v1/files", headers={"DCI-NAME": "file"}, data="content") assert file.status_code == 400 diff --git a/tests/api/v1/test_jobs_kv.py b/tests/api/v1/test_jobs_kv.py index c85336e00..f0d7fba53 100644 --- a/tests/api/v1/test_jobs_kv.py +++ b/tests/api/v1/test_jobs_kv.py @@ -82,3 +82,27 @@ def test_delete_from_job(remoteci_context, components_user_ids, topic_user_id): job = remoteci_context.get("/api/v1/jobs/%s" % job_id) job = job.data["job"] assert job["keys_values"] == [] + + +def test_job_updated_when_kv_added_deleted(remoteci_context, job_user_id): + job = remoteci_context.get("/api/v1/jobs/%s" % job_user_id).data["job"] + job_updated_at = job["updated_at"] + + r = remoteci_context.post( + "/api/v1/jobs/%s/kv" % job_user_id, + data={"key": "mykey", "value": 123.123}, + ) + r.status_code == 201 + + job = remoteci_context.get("/api/v1/jobs/%s" % job_user_id).data["job"] + assert job["updated_at"] != job_updated_at + + job_updated_at = job["updated_at"] + r = remoteci_context.delete( + "/api/v1/jobs/%s/kv" % job_user_id, + data={"key": "mykey"}, + ) + r.status_code == 204 + + job = remoteci_context.get("/api/v1/jobs/%s" % job_user_id).data["job"] + assert job["updated_at"] != job_updated_at