18691: Disallow freezing projects with active container requests.
authorTom Clegg <tom@curii.com>
Thu, 17 Mar 2022 19:55:11 +0000 (15:55 -0400)
committerTom Clegg <tom@curii.com>
Thu, 17 Mar 2022 19:55:11 +0000 (15:55 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

services/api/app/models/group.rb
services/api/test/unit/group_test.rb

index f56c3281d7ac5392af325932f737d756dfe28cc5..b1b2e942c60c4bc79c13dbe731ad9bc1112684d2 100644 (file)
@@ -176,6 +176,18 @@ class Group < ArvadosModel
       "Group.update_frozen.select",
       [[nil, self.uuid],
        [nil, !self.frozen_by_uuid.nil?]])
+    if frozen_by_uuid
+      rows = ActiveRecord::Base.connection.exec_query(
+        "select cr.uuid, cr.state from container_requests cr, #{temptable} frozen " +
+        "where cr.owner_uuid = frozen.uuid and frozen.is_frozen " +
+        "and cr.state not in ($1, $2) limit 1",
+        "Group.update_frozen.check_container_requests",
+        [[nil, ContainerRequest::Uncommitted],
+         [nil, ContainerRequest::Final]])
+      if rows.any?
+        raise ArgumentError.new("cannot freeze project containing container request #{rows.first['uuid']} with state = #{rows.first['state']}")
+      end
+    end
     ActiveRecord::Base.connection.exec_delete(
       "delete from frozen_groups where uuid in (select uuid from #{temptable} where not is_frozen)",
       "Group.update_frozen.delete")
index 1f1d379084f18318485a934c958267860fe55951..7a16962402c7a4609bfea6dddd5703526a4a2cbc 100644 (file)
@@ -317,6 +317,18 @@ update links set tail_uuid='#{g5}' where uuid='#{l1.uuid}'
   test "freeze project" do
     act_as_user users(:active) do
       Rails.configuration.API.UnfreezeProjectRequiresAdmin = false
+
+      test_cr_attrs = {
+        command: ["echo", "foo"],
+        container_image: links(:docker_image_collection_tag).name,
+        cwd: "/tmp",
+        environment: {},
+        mounts: {"/out" => {"kind" => "tmp", "capacity" => 1000000}},
+        output_path: "/out",
+        runtime_constraints: {"vcpus" => 1, "ram" => 2},
+        name: "foo",
+        description: "bar",
+      }
       parent = Group.create!(group_class: 'project', name: 'freeze-test-parent', owner_uuid: users(:active).uuid)
       proj = Group.create!(group_class: 'project', name: 'freeze-test', owner_uuid: parent.uuid)
       proj_inner = Group.create!(group_class: 'project', name: 'freeze-test-inner', owner_uuid: proj.uuid)
@@ -398,18 +410,7 @@ update links set tail_uuid='#{g5}' where uuid='#{l1.uuid}'
         assert_raises do
           Group.create!(owner_uuid: frozen.uuid, group_class: 'project', name: 'inside-frozen-project')
         end
-        cr = ContainerRequest.new(
-          command: ["echo", "foo"],
-          container_image: links(:docker_image_collection_tag).name,
-          cwd: "/tmp",
-          environment: {},
-          mounts: {"/out" => {"kind" => "tmp", "capacity" => 1000000}},
-          output_path: "/out",
-          runtime_constraints: {"vcpus" => 1, "ram" => 2},
-          name: "foo",
-          description: "bar",
-          owner_uuid: frozen.uuid,
-        )
+        cr = ContainerRequest.new(test_cr_attrs.merge(owner_uuid: frozen.uuid))
         assert_raises ArvadosModel::PermissionDeniedError do
           cr.save
         end
@@ -509,6 +510,22 @@ update links set tail_uuid='#{g5}' where uuid='#{l1.uuid}'
         # Admin can unfreeze.
         assert proj.update_attributes(frozen_by_uuid: nil), proj.errors.messages
       end
+
+      # Cannot freeze a project if it contains container requests in
+      # Committed state (this would cause operations on the relevant
+      # Containers to fail when syncing container request state)
+      creq_uncommitted = ContainerRequest.create!(test_cr_attrs.merge(owner_uuid: proj_inner.uuid))
+      creq_committed = ContainerRequest.create!(test_cr_attrs.merge(owner_uuid: proj_inner.uuid, state: 'Committed'))
+      err = assert_raises do
+        proj.update_attributes!(frozen_by_uuid: users(:active).uuid)
+      end
+      assert_match /container request zzzzz-xvhdp-.* with state = Committed/, err.inspect
+      proj.reload
+
+      # Can freeze once all container requests are in Uncommitted or
+      # Final state
+      creq_committed.update_attributes!(state: ContainerRequest::Final)
+      assert proj.update_attributes(frozen_by_uuid: users(:active).uuid)
     end
   end
 end