X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/9b0654adfffaac018395de29f6e441b843d46e85..9992a8816837bd03a1beecd0c0e8082bd913319a:/services/api/test/functional/arvados/v1/jobs_controller_test.rb diff --git a/services/api/test/functional/arvados/v1/jobs_controller_test.rb b/services/api/test/functional/arvados/v1/jobs_controller_test.rb index 8808a82c45..9298f23d54 100644 --- a/services/api/test/functional/arvados/v1/jobs_controller_test.rb +++ b/services/api/test/functional/arvados/v1/jobs_controller_test.rb @@ -1,173 +1,15 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + require 'test_helper' require 'helpers/git_test_helper' class Arvados::V1::JobsControllerTest < ActionController::TestCase - include GitTestHelper - - test "submit a job" do - authorize_with :active - post :create, job: { - script: "hash", - script_version: "master", - repository: "active/foo", - script_parameters: {} - } - assert_response :success - assert_not_nil assigns(:object) - new_job = JSON.parse(@response.body) - assert_not_nil new_job['uuid'] - assert_not_nil new_job['script_version'].match(/^[0-9a-f]{40}$/) - assert_equal 0, new_job['priority'] - end - - test "normalize output and log uuids when creating job" do - authorize_with :active - post :create, job: { - script: "hash", - script_version: "master", - script_parameters: {}, - repository: "active/foo", - started_at: Time.now, - finished_at: Time.now, - running: false, - success: true, - output: 'd41d8cd98f00b204e9800998ecf8427e+0+K@xyzzy', - log: 'd41d8cd98f00b204e9800998ecf8427e+0+K@xyzzy' - } - assert_response :success - assert_not_nil assigns(:object) - new_job = assigns(:object) - assert_equal 'd41d8cd98f00b204e9800998ecf8427e+0', new_job['log'] - assert_equal 'd41d8cd98f00b204e9800998ecf8427e+0', new_job['output'] - version = new_job['script_version'] - - # Make sure version doesn't get mangled by normalize - assert_not_nil version.match(/^[0-9a-f]{40}$/) - assert_equal 'master', json_response['supplied_script_version'] - end - - test "normalize output and log uuids when updating job" do - authorize_with :active - - foobar_job = jobs(:foobar) - - new_output = 'd41d8cd98f00b204e9800998ecf8427e+0+K@xyzzy' - new_log = 'd41d8cd98f00b204e9800998ecf8427e+0+K@xyzzy' - put :update, { - id: foobar_job['uuid'], - job: { - output: new_output, - log: new_log - } - } - - updated_job = json_response - assert_not_equal foobar_job['log'], updated_job['log'] - assert_not_equal new_log, updated_job['log'] # normalized during update - assert_equal new_log[0,new_log.rindex('+')], updated_job['log'] - assert_not_equal foobar_job['output'], updated_job['output'] - assert_not_equal new_output, updated_job['output'] # normalized during update - assert_equal new_output[0,new_output.rindex('+')], updated_job['output'] - end - - test "cancel a running job" do - # We need to verify that "cancel" creates a trigger file, so first - # let's make sure there is no stale trigger file. - begin - File.unlink(Rails.configuration.crunch_refresh_trigger) - rescue Errno::ENOENT - end - - authorize_with :active - put :update, { - id: jobs(:running).uuid, - job: { - cancelled_at: 4.day.ago - } - } - assert_response :success - assert_not_nil assigns(:object) - job = JSON.parse(@response.body) - assert_not_nil job['uuid'] - assert_not_nil job['cancelled_at'] - assert_not_nil job['cancelled_by_user_uuid'] - assert_not_nil job['cancelled_by_client_uuid'] - assert_equal(true, Time.parse(job['cancelled_at']) > 1.minute.ago, - 'server should correct bogus cancelled_at ' + - job['cancelled_at']) - assert_equal(true, - File.exist?(Rails.configuration.crunch_refresh_trigger), - 'trigger file should be created when job is cancelled') - end - - [ - [:put, :update, {job:{cancelled_at: Time.now}}, :success], - [:put, :update, {job:{cancelled_at: nil}}, :unprocessable_entity], - [:put, :update, {job:{state: 'Cancelled'}}, :success], - [:put, :update, {job:{state: 'Queued'}}, :unprocessable_entity], - [:put, :update, {job:{state: 'Running'}}, :unprocessable_entity], - [:put, :update, {job:{state: 'Failed'}}, :unprocessable_entity], - [:put, :update, {job:{state: 'Complete'}}, :unprocessable_entity], - [:post, :cancel, {}, :success], - ].each do |http_method, action, params, expected_response| - test "cancelled job stays cancelled after #{[http_method, action, params].inspect}" do - # We need to verify that "cancel" creates a trigger file, so first - # let's make sure there is no stale trigger file. - begin - File.unlink(Rails.configuration.crunch_refresh_trigger) - rescue Errno::ENOENT - end - - authorize_with :active - self.send http_method, action, { id: jobs(:cancelled).uuid }.merge(params) - assert_response expected_response - if expected_response == :success - job = json_response - assert_not_nil job['cancelled_at'], 'job cancelled again using #{attribute}=#{value} did not have cancelled_at value' - assert_equal job['state'], 'Cancelled', 'cancelled again job state changed when updated using using #{attribute}=#{value}' - end - # Verify database record still says Cancelled - assert_equal 'Cancelled', Job.find(jobs(:cancelled).id).state, 'job was un-cancelled' - end - end - - test "cancelled job updated to any other state change results in error" do - # We need to verify that "cancel" creates a trigger file, so first - # let's make sure there is no stale trigger file. - begin - File.unlink(Rails.configuration.crunch_refresh_trigger) - rescue Errno::ENOENT - end - - authorize_with :active - put :update, { - id: jobs(:running_cancelled).uuid, - job: { - cancelled_at: nil - } - } - assert_response 422 - end - - ['abc.py', 'hash.py'].each do |script| - test "update job script attribute to #{script} without failing script_version check" do - authorize_with :admin - put :update, { - id: jobs(:uses_nonexistent_script_version).uuid, - job: { - script: script - } - } - assert_response :success - resp = assigns(:object) - assert_equal jobs(:uses_nonexistent_script_version).script_version, resp['script_version'] - end - end - test "search jobs by uuid with >= query" do authorize_with :active - get :index, { + get :index, params: { filters: [['uuid', '>=', 'zzzzz-8i9sb-pshmckwoma9plh7']] } assert_response :success @@ -178,7 +20,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by uuid with <= query" do authorize_with :active - get :index, { + get :index, params: { filters: [['uuid', '<=', 'zzzzz-8i9sb-pshmckwoma9plh7']] } assert_response :success @@ -189,7 +31,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by uuid with >= and <= query" do authorize_with :active - get :index, { + get :index, params: { filters: [['uuid', '>=', 'zzzzz-8i9sb-pshmckwoma9plh7'], ['uuid', '<=', 'zzzzz-8i9sb-pshmckwoma9plh7']] } @@ -200,7 +42,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by uuid with < query" do authorize_with :active - get :index, { + get :index, params: { filters: [['uuid', '<', 'zzzzz-8i9sb-pshmckwoma9plh7']] } assert_response :success @@ -211,7 +53,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by uuid with like query" do authorize_with :active - get :index, { + get :index, params: { filters: [['uuid', 'like', '%hmckwoma9pl%']] } assert_response :success @@ -221,7 +63,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by uuid with 'in' query" do authorize_with :active - get :index, { + get :index, params: { filters: [['uuid', 'in', ['zzzzz-8i9sb-4cf0nhn6xte809j', 'zzzzz-8i9sb-pshmckwoma9plh7']]] } @@ -235,7 +77,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase exclude_uuids = [jobs(:running).uuid, jobs(:running_cancelled).uuid] authorize_with :active - get :index, { + get :index, params: { filters: [['uuid', 'not in', exclude_uuids]] } assert_response :success @@ -250,7 +92,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase ['output', nil]].each do |attr, operand| test "search jobs with #{attr} #{operator} #{operand.inspect} query" do authorize_with :active - get :index, { + get :index, params: { filters: [[attr, operator, operand]] } assert_response :success @@ -267,7 +109,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by started_at with < query" do authorize_with :active - get :index, { + get :index, params: { filters: [['started_at', '<', Time.now.to_s]] } assert_response :success @@ -277,7 +119,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by started_at with > query" do authorize_with :active - get :index, { + get :index, params: { filters: [['started_at', '>', Time.now.to_s]] } assert_response :success @@ -286,7 +128,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by started_at with >= query on metric date" do authorize_with :active - get :index, { + get :index, params: { filters: [['started_at', '>=', '2014-01-01']] } assert_response :success @@ -296,7 +138,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by started_at with >= query on metric date and time" do authorize_with :active - get :index, { + get :index, params: { filters: [['started_at', '>=', '2014-01-01 01:23:45']] } assert_response :success @@ -306,7 +148,7 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs with 'any' operator" do authorize_with :active - get :index, { + get :index, params: { where: { any: ['contains', 'pshmckw'] } } assert_response :success @@ -317,208 +159,33 @@ class Arvados::V1::JobsControllerTest < ActionController::TestCase test "search jobs by nonexistent column with < query" do authorize_with :active - get :index, { + get :index, params: { filters: [['is_borked', '<', 'fizzbuzz']] } assert_response 422 end - test "finish a job" do - authorize_with :active - put :update, { - id: jobs(:nearly_finished_job).uuid, - job: { - output: '551392cc37a317abf865b95f66f4ef94+101', - log: '9215de2a951a721f5f156bc08cf63ad7+93', - tasks_summary: {done: 1, running: 0, todo: 0, failed: 0}, - success: true, - running: false, - finished_at: Time.now.to_s - } - } - assert_response :success - end - [:spectator, :admin].each_with_index do |which_token, i| test "get job queue as #{which_token} user" do authorize_with which_token get :queue assert_response :success - assert_equal i, assigns(:objects).count - end - end - - test "get job queue as with a = filter" do - authorize_with :admin - get :queue, { filters: [['script','=','foo']] } - assert_response :success - assert_equal ['foo'], assigns(:objects).collect(&:script).uniq - assert_equal 0, assigns(:objects)[0].queue_position - end - - test "get job queue as with a != filter" do - authorize_with :admin - get :queue, { filters: [['script','!=','foo']] } - assert_response :success - assert_equal 0, assigns(:objects).count - end - - [:spectator, :admin].each do |which_token| - test "get queue_size as #{which_token} user" do - authorize_with which_token - get :queue_size - assert_response :success - assert_equal 1, JSON.parse(@response.body)["queue_size"] + assert_equal 0, assigns(:objects).count end end test "job includes assigned nodes" do authorize_with :active - get :show, {id: jobs(:nearly_finished_job).uuid} + get :show, params: {id: jobs(:nearly_finished_job).uuid} assert_response :success assert_equal([nodes(:busy).uuid], json_response["node_uuids"]) end - test "job lock success" do - authorize_with :active - post :lock, {id: jobs(:queued).uuid} - assert_response :success - job = Job.where(uuid: jobs(:queued).uuid).first - assert_equal "Running", job.state - end - - test "job lock conflict" do - authorize_with :active - post :lock, {id: jobs(:running).uuid} - assert_response 422 # invalid state transition - end - - test 'reject invalid commit in remote repository' do - authorize_with :active - url = "http://localhost:1/fake/fake.git" - fetch_remote_from_local_repo url, :foo - post :create, job: { - script: "hash", - script_version: "abc123", - repository: url, - script_parameters: {} - } - assert_response 422 - end - - test 'tag remote commit in internal repository' do - authorize_with :active - url = "http://localhost:1/fake/fake.git" - fetch_remote_from_local_repo url, :foo - post :create, job: { - script: "hash", - script_version: "master", - repository: url, - script_parameters: {} - } - assert_response :success - assert_equal('077ba2ad3ea24a929091a9e6ce545c93199b8e57', - internal_tag(json_response['uuid'])) - end - - test 'tag local commit in internal repository' do - authorize_with :active - post :create, job: { - script: "hash", - script_version: "master", - repository: "active/foo", - script_parameters: {} - } - assert_response :success - assert_equal('077ba2ad3ea24a929091a9e6ce545c93199b8e57', - internal_tag(json_response['uuid'])) - end - test 'get job with components' do authorize_with :active - get :show, {id: jobs(:running_job_with_components).uuid} + get :show, params: {id: jobs(:running_job_with_components).uuid} assert_response :success assert_not_nil json_response["components"] assert_equal ["component1", "component2"], json_response["components"].keys end - - [ - [:active, :success], - [:system_user, :success], - [:admin, 403], - ].each do |user, expected| - test "add components to job locked by active user as #{user} user and expect #{expected}" do - authorize_with user - put :update, { - id: jobs(:running).uuid, - job: { - components: {"component1" => "value1", "component2" => "value2"} - } - } - assert_response expected - if expected == :success - assert_not_nil json_response["components"] - keys = json_response["components"].keys - assert_equal ["component1", "component2"], keys - assert_equal "value1", json_response["components"][keys[0]] - end - end - end - - test 'get_delete components_get again for job with components' do - authorize_with :active - get :show, {id: jobs(:running_job_with_components).uuid} - assert_response :success - assert_not_nil json_response["components"] - assert_equal ["component1", "component2"], json_response["components"].keys - - # delete second component - @test_counter = 0 # Reset executed action counter - @controller = Arvados::V1::JobsController.new - put :update, { - id: jobs(:running_job_with_components).uuid, - job: { - components: {"component1" => "zzzzz-8i9sb-jobuuid00000001"} - } - } - assert_response :success - - @test_counter = 0 # Reset executed action counter - @controller = Arvados::V1::JobsController.new - get :show, {id: jobs(:running_job_with_components).uuid} - assert_response :success - assert_not_nil json_response["components"] - assert_equal ["component1"], json_response["components"].keys - - # delete all components - @test_counter = 0 # Reset executed action counter - @controller = Arvados::V1::JobsController.new - put :update, { - id: jobs(:running_job_with_components).uuid, - job: { - components: {} - } - } - assert_response :success - - @test_counter = 0 # Reset executed action counter - @controller = Arvados::V1::JobsController.new - get :show, {id: jobs(:running_job_with_components).uuid} - assert_response :success - assert_not_nil json_response["components"] - assert_equal [], json_response["components"].keys - end - - test 'jobs.create disabled in config' do - Rails.configuration.disable_api_methods = ["jobs.create", - "pipeline_instances.create"] - authorize_with :active - post :create, job: { - script: "hash", - script_version: "master", - repository: "active/foo", - script_parameters: {} - } - assert_response 404 - end end