[ARVADOS] updated: 1.1.3-167-g4dd3d86

Git user git at public.curoverse.com
Fri Mar 9 16:21:58 EST 2018


Summary of changes:
 services/api/app/models/container.rb               | 33 +++++++++++
 services/api/app/models/container_request.rb       | 13 +++-
 ...180228220311_add_secret_mounts_to_containers.rb |  1 +
 services/api/db/structure.sql                      |  7 +++
 services/api/test/fixtures/containers.yml          | 23 ++++++++
 .../v1/container_requests_controller_test.rb       | 69 ++++++++++++++++++----
 .../arvados/v1/containers_controller_test.rb       |  3 +-
 services/api/test/helpers/container_test_helper.rb |  6 +-
 services/api/test/unit/container_request_test.rb   | 28 ++++++---
 9 files changed, 159 insertions(+), 24 deletions(-)

  discards  0460fa8b94a6499aff1b816625d65101834b7a97 (commit)
       via  4dd3d867e590ff54b9e2c1abeea879bcdf87c529 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (0460fa8b94a6499aff1b816625d65101834b7a97)
            \
             N -- N -- N (4dd3d867e590ff54b9e2c1abeea879bcdf87c529)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 4dd3d867e590ff54b9e2c1abeea879bcdf87c529
Author: Tom Clegg <tclegg at veritasgenetics.com>
Date:   Fri Mar 9 15:52:16 2018 -0500

    13143: Add secret_mounts field to containers and container requests.
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg at veritasgenetics.com>

diff --git a/services/api/app/controllers/arvados/v1/containers_controller.rb b/services/api/app/controllers/arvados/v1/containers_controller.rb
index 8c63ea7..6ec92b0 100644
--- a/services/api/app/controllers/arvados/v1/containers_controller.rb
+++ b/services/api/app/controllers/arvados/v1/containers_controller.rb
@@ -60,4 +60,14 @@ class Arvados::V1::ContainersController < ApplicationController
       end
     end
   end
+
+  def secret_mounts
+    if @object &&
+       @object.auth_uuid &&
+       @object.auth_uuid == Thread.current[:api_client_authorization].uuid
+      send_json({"secret_mounts" => @object.secret_mounts})
+    else
+      send_error("Token is not associated with this container.", status: 403)
+    end
+  end
 end
diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb
index b013776..cff0658 100644
--- a/services/api/app/models/container.rb
+++ b/services/api/app/models/container.rb
@@ -20,6 +20,7 @@ class Container < ArvadosModel
   serialize :runtime_constraints, Hash
   serialize :command, Array
   serialize :scheduling_parameters, Hash
+  serialize :secret_mounts, Hash
 
   before_validation :fill_field_defaults, :if => :new_record?
   before_validation :set_timestamps
@@ -31,6 +32,8 @@ class Container < ArvadosModel
   validate :validate_output
   after_validation :assign_auth
   before_save :sort_serialized_attrs
+  before_save :update_secret_mounts_md5
+  before_save :scrub_secret_mounts
   after_save :handle_completed
   after_save :propagate_priority
 
@@ -79,6 +82,18 @@ class Container < ArvadosModel
     ["mounts"]
   end
 
+  def self.full_text_searchable_columns
+    super - ["secret_mounts", "secret_mounts_md5"]
+  end
+
+  def self.searchable_columns *args
+    super - ["secret_mounts_md5"]
+  end
+
+  def logged_attributes
+    super.except('secret_mounts')
+  end
+
   def state_transitions
     State_transitions
   end
@@ -121,6 +136,7 @@ class Container < ArvadosModel
       mounts: resolve_mounts(req.mounts),
       runtime_constraints: resolve_runtime_constraints(req.runtime_constraints),
       scheduling_parameters: req.scheduling_parameters,
+      secret_mounts: req.secret_mounts,
     }
     act_as_system_user do
       if req.use_existing && (reusable = find_reusable(c_attrs))
@@ -217,6 +233,9 @@ class Container < ArvadosModel
     candidates = candidates.where_serialized(:mounts, resolve_mounts(attrs[:mounts]))
     log_reuse_info(candidates) { "after filtering on mounts #{attrs[:mounts].inspect}" }
 
+    candidates = candidates.where('secret_mounts_md5 = ?', Digest::MD5.hexdigest(SafeJSON.dump(self.deep_sort_hash(attrs[:secret_mounts] || {}))))
+    log_reuse_info(candidates) { "after filtering on mounts #{attrs[:mounts].inspect}" }
+
     candidates = candidates.where_serialized(:runtime_constraints, resolve_runtime_constraints(attrs[:runtime_constraints]))
     log_reuse_info(candidates) { "after filtering on runtime_constraints #{attrs[:runtime_constraints].inspect}" }
 
@@ -378,7 +397,8 @@ class Container < ArvadosModel
     if self.new_record?
       permitted.push(:owner_uuid, :command, :container_image, :cwd,
                      :environment, :mounts, :output_path, :priority,
-                     :runtime_constraints, :scheduling_parameters)
+                     :runtime_constraints, :scheduling_parameters,
+                     :secret_mounts)
     end
 
     case self.state
@@ -487,6 +507,22 @@ class Container < ArvadosModel
     end
   end
 
+  def update_secret_mounts_md5
+    if self.secret_mounts_changed?
+      self.secret_mounts_md5 = Digest::MD5.hexdigest(
+        SafeJSON.dump(self.class.deep_sort_hash(self.secret_mounts)))
+    end
+  end
+
+  def scrub_secret_mounts
+    # this runs after update_secret_mounts_md5, so the
+    # secret_mounts_md5 will still reflect the secrets that are being
+    # scrubbed here.
+    if self.state_changed? && self.final?
+      self.secret_mounts = {}
+    end
+  end
+
   def handle_completed
     # This container is finished so finalize any associated container requests
     # that are associated with this container.
diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb
index bcca407..a1d5722 100644
--- a/services/api/app/models/container_request.rb
+++ b/services/api/app/models/container_request.rb
@@ -18,6 +18,7 @@ class ContainerRequest < ArvadosModel
   serialize :runtime_constraints, Hash
   serialize :command, Array
   serialize :scheduling_parameters, Hash
+  serialize :secret_mounts, Hash
 
   before_validation :fill_field_defaults, :if => :new_record?
   before_validation :validate_runtime_constraints
@@ -28,6 +29,7 @@ class ContainerRequest < ArvadosModel
   validates :priority, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 1000 }
   validate :validate_state_change
   validate :check_update_whitelist
+  before_save :scrub_secret_mounts
   after_save :update_priority
   after_save :finalize_if_needed
   before_create :set_requesting_container_uuid
@@ -79,12 +81,16 @@ class ContainerRequest < ArvadosModel
   :container_image, :cwd, :environment, :filters, :mounts,
   :output_path, :priority, :properties, :requesting_container_uuid,
   :runtime_constraints, :state, :container_uuid, :use_existing,
-  :scheduling_parameters, :output_name, :output_ttl]
+  :scheduling_parameters, :secret_mounts, :output_name, :output_ttl]
 
   def self.limit_index_columns_read
     ["mounts"]
   end
 
+  def logged_attributes
+    super.except('secret_mounts')
+  end
+
   def state_transitions
     State_transitions
   end
@@ -145,7 +151,7 @@ class ContainerRequest < ArvadosModel
   end
 
   def self.full_text_searchable_columns
-    super - ["mounts"]
+    super - ["mounts", "secret_mounts", "secret_mounts_md5"]
   end
 
   protected
@@ -216,7 +222,7 @@ class ContainerRequest < ArvadosModel
 
     if self.new_record? || self.state_was == Uncommitted
       # Allow create-and-commit in a single operation.
-      permitted.push *AttrsPermittedBeforeCommit
+      permitted.push(*AttrsPermittedBeforeCommit)
     end
 
     case self.state
@@ -253,6 +259,12 @@ class ContainerRequest < ArvadosModel
     super(permitted)
   end
 
+  def scrub_secret_mounts
+    if self.state == Final
+      self.secret_mounts = {}
+    end
+  end
+
   def update_priority
     if self.state_changed? or
         self.priority_changed? or
diff --git a/services/api/config/initializers/lograge.rb b/services/api/config/initializers/lograge.rb
index 564f31a..db9b225 100644
--- a/services/api/config/initializers/lograge.rb
+++ b/services/api/config/initializers/lograge.rb
@@ -15,6 +15,18 @@ Server::Application.configure do
     }
     exceptions = %w(controller action format id)
     params = event.payload[:params].except(*exceptions)
+
+    # Omit secret_mounts field if supplied in create/update request
+    # body.
+    [
+      ['container', 'secret_mounts'],
+      ['container_request', 'secret_mounts'],
+    ].each do |resource, field|
+      if params[resource].is_a? Hash
+        params[resource] = params[resource].except(field)
+      end
+    end
+
     params_s = SafeJSON.dump(params)
     if params_s.length > Rails.configuration.max_request_log_params_size
       payload[:params_truncated] = params_s[0..Rails.configuration.max_request_log_params_size] + "[...]"
diff --git a/services/api/config/routes.rb b/services/api/config/routes.rb
index fcd5c34..ad2406a 100644
--- a/services/api/config/routes.rb
+++ b/services/api/config/routes.rb
@@ -39,6 +39,7 @@ Server::Application.routes.draw do
         get 'auth', on: :member
         post 'lock', on: :member
         post 'unlock', on: :member
+        get 'secret_mounts', on: :member
         get 'current', on: :collection
       end
       resources :container_requests
diff --git a/services/api/db/migrate/20180228220311_add_secret_mounts_to_containers.rb b/services/api/db/migrate/20180228220311_add_secret_mounts_to_containers.rb
new file mode 100644
index 0000000..c56b7dc
--- /dev/null
+++ b/services/api/db/migrate/20180228220311_add_secret_mounts_to_containers.rb
@@ -0,0 +1,8 @@
+class AddSecretMountsToContainers < ActiveRecord::Migration
+  def change
+    add_column :container_requests, :secret_mounts, :jsonb, default: {}
+    add_column :containers, :secret_mounts, :jsonb, default: {}
+    add_column :containers, :secret_mounts_md5, :string, default: "99914b932bd37a50b983c5e7c90ae93b"
+    add_index :containers, :secret_mounts_md5
+  end
+end
diff --git a/services/api/db/structure.sql b/services/api/db/structure.sql
index 357e95c..798c020 100644
--- a/services/api/db/structure.sql
+++ b/services/api/db/structure.sql
@@ -299,7 +299,8 @@ CREATE TABLE container_requests (
     output_uuid character varying(255),
     log_uuid character varying(255),
     output_name character varying(255) DEFAULT NULL::character varying,
-    output_ttl integer DEFAULT 0 NOT NULL
+    output_ttl integer DEFAULT 0 NOT NULL,
+    secret_mounts jsonb DEFAULT '{}'::jsonb
 );
 
 
@@ -352,7 +353,9 @@ CREATE TABLE containers (
     exit_code integer,
     auth_uuid character varying(255),
     locked_by_uuid character varying(255),
-    scheduling_parameters text
+    scheduling_parameters text,
+    secret_mounts jsonb DEFAULT '{}'::jsonb,
+    secret_mounts_md5 character varying DEFAULT '99914b932bd37a50b983c5e7c90ae93b'::character varying
 );
 
 
@@ -1889,6 +1892,13 @@ CREATE INDEX index_containers_on_owner_uuid ON containers USING btree (owner_uui
 
 
 --
+-- Name: index_containers_on_secret_mounts_md5; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_containers_on_secret_mounts_md5 ON containers USING btree (secret_mounts_md5);
+
+
+--
 -- Name: index_containers_on_uuid; Type: INDEX; Schema: public; Owner: -
 --
 
@@ -3054,3 +3064,5 @@ INSERT INTO schema_migrations (version) VALUES ('20171212153352');
 
 INSERT INTO schema_migrations (version) VALUES ('20180216203422');
 
+INSERT INTO schema_migrations (version) VALUES ('20180228220311');
+
diff --git a/services/api/test/fixtures/containers.yml b/services/api/test/fixtures/containers.yml
index 3995791..a13cd32 100644
--- a/services/api/test/fixtures/containers.yml
+++ b/services/api/test/fixtures/containers.yml
@@ -39,6 +39,11 @@ running:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts:
+    /secret/6x9:
+      kind: text
+      content: "42\n"
+  secret_mounts_md5: <%= Digest::MD5.hexdigest(SafeJSON.dump({'/secret/6x9' => {'kind' => 'text', 'content' => "42\n"}})) %>
   auth_uuid: zzzzz-gj3su-077z32aux8dg2s2
 
 running_older:
@@ -56,6 +61,8 @@ running_older:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 locked:
   uuid: zzzzz-dz642-lockedcontainer
@@ -72,6 +79,8 @@ locked:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 completed:
   uuid: zzzzz-dz642-compltcontainer
@@ -92,6 +101,8 @@ completed:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 completed_older:
   uuid: zzzzz-dz642-compltcontainr2
@@ -111,6 +122,8 @@ completed_older:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 requester:
   uuid: zzzzz-dz642-requestingcntnr
@@ -128,6 +141,8 @@ requester:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 requester_container:
   uuid: zzzzz-dz642-requestercntnr1
@@ -145,6 +160,8 @@ requester_container:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 failed_container:
   uuid: zzzzz-dz642-failedcontainr1
@@ -162,6 +179,8 @@ failed_container:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 ancient_container_with_logs:
   uuid: zzzzz-dz642-logscontainer01
@@ -181,6 +200,8 @@ ancient_container_with_logs:
   finished_at: <%= 2.year.ago.to_s(:db) %>
   log: ea10d51bcf88862dbcc36eb292017dfd+45
   output: test
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 previous_container_with_logs:
   uuid: zzzzz-dz642-logscontainer02
@@ -200,6 +221,8 @@ previous_container_with_logs:
   finished_at: <%= 1.month.ago.to_s(:db) %>
   log: ea10d51bcf88862dbcc36eb292017dfd+45
   output: test
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 running_container_with_logs:
   uuid: zzzzz-dz642-logscontainer03
@@ -215,6 +238,8 @@ running_container_with_logs:
   runtime_constraints:
     ram: 12000000000
     vcpus: 4
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
 
 running_to_be_deleted:
   uuid: zzzzz-dz642-runnincntrtodel
@@ -232,3 +257,5 @@ running_to_be_deleted:
     ram: 12000000000
     vcpus: 4
   auth_uuid: zzzzz-gj3su-ty6lvu9d7u7c2sq
+  secret_mounts: {}
+  secret_mounts_md5: 99914b932bd37a50b983c5e7c90ae93b
diff --git a/services/api/test/functional/arvados/v1/container_requests_controller_test.rb b/services/api/test/functional/arvados/v1/container_requests_controller_test.rb
index 4ebda97..b2cd366 100644
--- a/services/api/test/functional/arvados/v1/container_requests_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/container_requests_controller_test.rb
@@ -5,22 +5,80 @@
 require 'test_helper'
 
 class Arvados::V1::ContainerRequestsControllerTest < ActionController::TestCase
+  def minimal_cr
+    {
+      command: ['echo', 'hello'],
+      container_image: 'test',
+      output_path: 'test',
+    }
+  end
+
   test 'create with scheduling parameters' do
-    authorize_with :system_user
+    authorize_with :active
 
     sp = {'partitions' => ['test1', 'test2']}
     post :create, {
-      container_request: {
-        command: ['echo', 'hello'],
-        container_image: 'test',
-        output_path: 'test',
-        scheduling_parameters: sp,
-      },
-    }
+           container_request: minimal_cr.merge(scheduling_parameters: sp.dup)
+         }
     assert_response :success
 
     cr = JSON.parse(@response.body)
     assert_not_nil cr, 'Expected container request'
     assert_equal sp, cr['scheduling_parameters']
   end
+
+  test "secret_mounts not in #create responses" do
+    authorize_with :active
+
+    post :create, {
+           container_request: minimal_cr.merge(
+             secret_mounts: {'/foo' => {'type' => 'json', 'content' => 'bar'}}),
+         }
+    assert_response :success
+
+    resp = JSON.parse(@response.body)
+    refute resp.has_key?('secret_mounts')
+
+    req = ContainerRequest.where(uuid: resp['uuid']).first
+    assert_equal 'bar', req.secret_mounts['/foo']['content']
+  end
+
+  test "update with secret_mounts" do
+    authorize_with :active
+    req = container_requests(:uncommitted)
+
+    patch :update, {
+            id: req.uuid,
+            container_request: {
+              secret_mounts: {'/foo' => {'type' => 'json', 'content' => 'bar'}},
+            },
+          }
+    assert_response :success
+
+    resp = JSON.parse(@response.body)
+    refute resp.has_key?('secret_mounts')
+
+    req.reload
+    assert_equal 'bar', req.secret_mounts['/foo']['content']
+  end
+
+  test "update without deleting secret_mounts" do
+    authorize_with :active
+    req = container_requests(:uncommitted)
+    req.update_attributes!(secret_mounts: {'/foo' => {'type' => 'json', 'content' => 'bar'}})
+
+    patch :update, {
+            id: req.uuid,
+            container_request: {
+              command: ['echo', 'test'],
+            },
+          }
+    assert_response :success
+
+    resp = JSON.parse(@response.body)
+    refute resp.has_key?('secret_mounts')
+
+    req.reload
+    assert_equal 'bar', req.secret_mounts['/foo']['content']
+  end
 end
diff --git a/services/api/test/functional/arvados/v1/containers_controller_test.rb b/services/api/test/functional/arvados/v1/containers_controller_test.rb
index 5510e90..8e2002c 100644
--- a/services/api/test/functional/arvados/v1/containers_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/containers_controller_test.rb
@@ -45,13 +45,14 @@ class Arvados::V1::ContainersControllerTest < ActionController::TestCase
     assert_equal 'arvados#apiClientAuthorization', json_response['kind']
   end
 
-  test 'no auth in container response' do
+  test 'no auth or secret_mounts in container response' do
     authorize_with :dispatch1
     c = containers(:queued)
     assert c.lock, show_errors(c)
     get :show, id: c.uuid
     assert_response :success
     assert_nil json_response['auth']
+    assert_nil json_response['secret_mounts']
   end
 
   test "lock container" do
@@ -106,7 +107,7 @@ class Arvados::V1::ContainersControllerTest < ActionController::TestCase
     [:running, :lock, 422, 'Running'],
     [:running, :unlock, 422, 'Running'],
   ].each do |fixture, action, response, state|
-    test "state transitions from #{fixture } to #{action}" do
+    test "state transitions from #{fixture} to #{action}" do
       authorize_with :dispatch1
       uuid = containers(fixture).uuid
       post action, {id: uuid}
@@ -133,4 +134,21 @@ class Arvados::V1::ContainersControllerTest < ActionController::TestCase
     assert_response 401
   end
 
+  [
+    [true, :running_container_auth],
+    [false, :dispatch2],
+    [false, :admin],
+    [false, :active],
+  ].each do |expect_success, auth|
+    test "get secret_mounts with #{auth} token" do
+      authorize_with auth
+      get :secret_mounts, {id: containers(:running).uuid}
+      if expect_success
+        assert_response :success
+        assert_equal "42\n", json_response["secret_mounts"]["/secret/6x9"]["content"]
+      else
+        assert_response 403
+      end
+    end
+  end
 end
diff --git a/services/api/test/helpers/container_test_helper.rb b/services/api/test/helpers/container_test_helper.rb
new file mode 100644
index 0000000..88de724
--- /dev/null
+++ b/services/api/test/helpers/container_test_helper.rb
@@ -0,0 +1,15 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+module ContainerTestHelper
+  def secret_string
+    'UNGU3554BL3'
+  end
+
+  def assert_no_secrets_logged
+    Log.all.map(&:properties).each do |props|
+      refute_match /secret\/6x9|#{secret_string}/, SafeJSON.dump(props)
+    end
+  end
+end
diff --git a/services/api/test/unit/container_request_test.rb b/services/api/test/unit/container_request_test.rb
index 0edc0f4..70bcc74 100644
--- a/services/api/test/unit/container_request_test.rb
+++ b/services/api/test/unit/container_request_test.rb
@@ -3,11 +3,13 @@
 # SPDX-License-Identifier: AGPL-3.0
 
 require 'test_helper'
+require 'helpers/container_test_helper'
 require 'helpers/docker_migration_helper'
 
 class ContainerRequestTest < ActiveSupport::TestCase
   include DockerMigrationHelper
   include DbCurrentTime
+  include ContainerTestHelper
 
   def create_minimal_req! attrs={}
     defaults = {
@@ -836,4 +838,70 @@ class ContainerRequestTest < ActiveSupport::TestCase
     end
   end
 
+  test "reuse container with same secret_mounts" do
+    set_user_from_auth :active
+    cr1 = create_minimal_req!(state: "Committed", priority: 1)
+    cr1.save!
+    cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: {})
+    cr2.save!
+    assert_not_nil cr1.container_uuid
+    assert_equal cr1.container_uuid, cr2.container_uuid
+  end
+
+  secrets = {"/foo" => {"kind" => "binary"}}
+  [
+    [true, nil, nil],
+    [true, nil, {}],
+    [true, {}, {}],
+    [true, secrets, secrets],
+    [false, nil, secrets],
+    [false, {}, secrets],
+  ].each do |expect_reuse, sm1, sm2|
+    test "container reuse secret_mounts #{sm1.inspect}, #{sm2.inspect}" do
+      set_user_from_auth :active
+      cr1 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm1)
+      cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm2)
+      assert_not_nil cr1.container_uuid
+      assert_not_nil cr2.container_uuid
+      if expect_reuse
+        assert_equal cr1.container_uuid, cr2.container_uuid
+      else
+        assert_not_equal cr1.container_uuid, cr2.container_uuid
+      end
+    end
+  end
+
+  test "scrub secret_mounts but reuse container for request with identical secret_mounts" do
+    set_user_from_auth :active
+    sm = {'/secret/foo' => {'kind' => 'text', 'content' => secret_string}}
+    cr1 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm.dup)
+    run_container(cr1)
+    cr1.reload
+
+    # secret_mounts scrubbed from db
+    c = Container.where(uuid: cr1.container_uuid).first
+    assert_equal({}, c.secret_mounts)
+    assert_equal({}, cr1.secret_mounts)
+
+    # can reuse container if secret_mounts match
+    cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: sm.dup)
+    assert_equal cr1.container_uuid, cr2.container_uuid
+
+    # don't reuse container if secret_mounts don't match
+    cr3 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: {})
+    assert_not_equal cr1.container_uuid, cr3.container_uuid
+
+    assert_no_secrets_logged
+  end
+
+  test "not reuse container with different secret_mounts" do
+    secrets = {"/foo" => {"kind" => "binary"}}
+    set_user_from_auth :active
+    cr1 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: secrets.dup)
+    cr1.save!
+    cr2 = create_minimal_req!(state: "Committed", priority: 1, secret_mounts: secrets.dup)
+    cr2.save!
+    assert_not_nil cr1.container_uuid
+    assert_equal cr1.container_uuid, cr2.container_uuid
+  end
 end
diff --git a/services/api/test/unit/container_test.rb b/services/api/test/unit/container_test.rb
index 0e13ee9..bd07a88 100644
--- a/services/api/test/unit/container_test.rb
+++ b/services/api/test/unit/container_test.rb
@@ -3,9 +3,11 @@
 # SPDX-License-Identifier: AGPL-3.0
 
 require 'test_helper'
+require 'helpers/container_test_helper'
 
 class ContainerTest < ActiveSupport::TestCase
   include DbCurrentTime
+  include ContainerTestHelper
 
   DEFAULT_ATTRS = {
     command: ['echo', 'foo'],
@@ -621,4 +623,12 @@ class ContainerTest < ActiveSupport::TestCase
     end
   end
 
+  [
+    Container::Complete,
+    Container::Cancelled,
+  ].each do |final_state|
+    test "secret_mounts is null after container is #{final_state}" do
+      assert_no_secrets_logged
+    end
+  end
 end

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list