From a95a8847071680f16dbd7c0c0511f6492d00fc45 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 23 Aug 2021 09:10:23 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .../clusters/agents/group_authorizations.rb | 10 +++ .../admin/admin_sees_background_migrations_spec.rb | 39 ++++++---- spec/frontend/lib/utils/text_markdown_spec.js | 19 ----- .../background_migration/batched_migration_spec.rb | 36 ++++++++++ spec/lib/sidebars/menu_spec.rb | 23 ++++++ .../sidebars/projects/menus/monitor_menu_spec.rb | 19 ----- ...ult_project_approval_rules_vuln_allowed_spec.rb | 35 +++++++++ spec/models/ci/build_spec.rb | 4 ++ spec/models/clusters/agent_spec.rb | 2 + .../clusters/agents/group_authorization_spec.rb | 10 +++ spec/models/internal_id_spec.rb | 44 ++++++++++-- .../admin/background_migrations_controller_spec.rb | 45 ++++++++++++ spec/requests/api/internal/kubernetes_spec.rb | 38 ++++++++++ .../agents/refresh_authorization_service_spec.rb | 84 ++++++++++++++++++++++ 14 files changed, 351 insertions(+), 57 deletions(-) create mode 100644 spec/factories/clusters/agents/group_authorizations.rb create mode 100644 spec/migrations/add_default_project_approval_rules_vuln_allowed_spec.rb create mode 100644 spec/models/clusters/agents/group_authorization_spec.rb create mode 100644 spec/requests/admin/background_migrations_controller_spec.rb create mode 100644 spec/services/clusters/agents/refresh_authorization_service_spec.rb (limited to 'spec') diff --git a/spec/factories/clusters/agents/group_authorizations.rb b/spec/factories/clusters/agents/group_authorizations.rb new file mode 100644 index 00000000000..6ea3668dc66 --- /dev/null +++ b/spec/factories/clusters/agents/group_authorizations.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :agent_group_authorization, class: 'Clusters::Agents::GroupAuthorization' do + association :agent, factory: :cluster_agent + group + + config { { default_namespace: 'production' } } + end +end diff --git a/spec/features/admin/admin_sees_background_migrations_spec.rb b/spec/features/admin/admin_sees_background_migrations_spec.rb index 11823195310..94fb3a0314f 100644 --- a/spec/features/admin/admin_sees_background_migrations_spec.rb +++ b/spec/features/admin/admin_sees_background_migrations_spec.rb @@ -10,7 +10,7 @@ RSpec.describe "Admin > Admin sees background migrations" do let_it_be(:finished_migration) { create(:batched_background_migration, table_name: 'finished', status: :finished) } before_all do - create(:batched_background_migration_job, batched_migration: failed_migration, batch_size: 30, status: :succeeded) + create(:batched_background_migration_job, batched_migration: failed_migration, batch_size: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3) end before do @@ -53,22 +53,35 @@ RSpec.describe "Admin > Admin sees background migrations" do end end - it 'can view failed migrations' do - visit admin_background_migrations_path + context 'when there are failed migrations' do + before do + allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class| + allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 10]) + end + end - within '#content-body' do - tab = find_link 'Failed' - tab.click + it 'can view and retry them' do + visit admin_background_migrations_path - expect(page).to have_current_path(admin_background_migrations_path(tab: 'failed')) - expect(tab[:class]).to include('gl-tab-nav-item-active', 'gl-tab-nav-item-active-indigo') + within '#content-body' do + tab = find_link 'Failed' + tab.click - expect(page).to have_selector('tbody tr', count: 1) + expect(page).to have_current_path(admin_background_migrations_path(tab: 'failed')) + expect(tab[:class]).to include('gl-tab-nav-item-active', 'gl-tab-nav-item-active-indigo') + + expect(page).to have_selector('tbody tr', count: 1) + + expect(page).to have_content(failed_migration.job_class_name) + expect(page).to have_content(failed_migration.table_name) + expect(page).to have_content('0.00%') + expect(page).to have_content(failed_migration.status.humanize) - expect(page).to have_content(failed_migration.job_class_name) - expect(page).to have_content(failed_migration.table_name) - expect(page).to have_content('30.00%') - expect(page).to have_content(failed_migration.status.humanize) + click_button('Retry') + expect(page).not_to have_content(failed_migration.job_class_name) + expect(page).not_to have_content(failed_migration.table_name) + expect(page).not_to have_content('0.00%') + end end end diff --git a/spec/frontend/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js index 9fe2780fde2..beedb9b2eba 100644 --- a/spec/frontend/lib/utils/text_markdown_spec.js +++ b/spec/frontend/lib/utils/text_markdown_spec.js @@ -70,25 +70,6 @@ describe('init markdown', () => { expect(textArea.value).toContain('# Does not parse the `$` currently.'); }); - it('inserts a new line correctly', () => { - const initialValue = ''; - - textArea.value = initialValue; - textArea.selectionStart = 0; - textArea.selectionEnd = 0; - - insertMarkdownText({ - textArea, - text: textArea.value, - tag: '```suggestion:-0+0\n{text}\n```', - blockTag: true, - selected: '# Does not parse the \\n currently.', - wrap: false, - }); - - expect(textArea.value).toContain('# Does not parse the \\n currently.'); - }); - it('inserts the tag on a new line if the current one is not empty', () => { const initialValue = 'some text'; diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb index 3207e97a639..a1c2634f59c 100644 --- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb +++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb @@ -234,6 +234,42 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m end end + describe '#retry_failed_jobs!' do + let(:batched_migration) { create(:batched_background_migration, status: 'failed') } + + subject(:retry_failed_jobs) { batched_migration.retry_failed_jobs! } + + context 'when there are failed migration jobs' do + let!(:batched_background_migration_job) { create(:batched_background_migration_job, batched_migration: batched_migration, batch_size: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3) } + + before do + allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class| + allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 10]) + end + end + + it 'moves the status of the migration to active' do + retry_failed_jobs + + expect(batched_migration.status).to eql 'active' + end + + it 'changes the number of attempts to 0' do + retry_failed_jobs + + expect(batched_background_migration_job.reload.attempts).to be_zero + end + end + + context 'when there are no failed migration jobs' do + it 'moves the status of the migration to active' do + retry_failed_jobs + + expect(batched_migration.status).to eql 'active' + end + end + end + describe '#job_class_name=' do it_behaves_like 'an attr_writer that demodulizes assigned class names', :job_class_name end diff --git a/spec/lib/sidebars/menu_spec.rb b/spec/lib/sidebars/menu_spec.rb index 1db80351e45..eb6a68f1afd 100644 --- a/spec/lib/sidebars/menu_spec.rb +++ b/spec/lib/sidebars/menu_spec.rb @@ -198,4 +198,27 @@ RSpec.describe Sidebars::Menu do end end end + + describe '#link' do + let(:foo_path) { '/foo_path'} + + let(:foo_menu) do + ::Sidebars::MenuItem.new( + title: 'foo', + link: foo_path, + active_routes: {}, + item_id: :foo + ) + end + + it 'returns first visible menu item link' do + menu.add_item(foo_menu) + + expect(menu.link).to eq foo_path + end + + it 'returns nil if there are no visible menu items' do + expect(menu.link).to be_nil + end + end end diff --git a/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb index 381842be5ab..77efe99aaa9 100644 --- a/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/monitor_menu_spec.rb @@ -49,25 +49,6 @@ RSpec.describe Sidebars::Projects::Menus::MonitorMenu do end end - describe '#link' do - let(:foo_path) { '/foo_path'} - - let(:foo_menu) do - ::Sidebars::MenuItem.new( - title: 'foo', - link: foo_path, - active_routes: {}, - item_id: :foo - ) - end - - it 'returns first visible item link' do - subject.insert_element_before(subject.renderable_items, subject.renderable_items.first.item_id, foo_menu) - - expect(subject.link).to eq foo_path - end - end - context 'Menu items' do subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } } diff --git a/spec/migrations/add_default_project_approval_rules_vuln_allowed_spec.rb b/spec/migrations/add_default_project_approval_rules_vuln_allowed_spec.rb new file mode 100644 index 00000000000..057e95eb158 --- /dev/null +++ b/spec/migrations/add_default_project_approval_rules_vuln_allowed_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe AddDefaultProjectApprovalRulesVulnAllowed do + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') } + let(:project) { projects.create!(name: 'project', path: 'project', namespace_id: namespace.id) } + let(:approval_project_rules) { table(:approval_project_rules) } + + it 'updates records when vulnerabilities_allowed is nil' do + records_to_migrate = 10 + + records_to_migrate.times do |i| + approval_project_rules.create!(name: "rule #{i}", project_id: project.id) + end + + expect { migrate! } + .to change { approval_project_rules.where(vulnerabilities_allowed: nil).count } + .from(records_to_migrate) + .to(0) + end + + it 'defaults vulnerabilities_allowed to 0' do + approval_project_rule = approval_project_rules.create!(name: "new rule", project_id: project.id) + + expect(approval_project_rule.vulnerabilities_allowed).to be_nil + + migrate! + + expect(approval_project_rule.reload.vulnerabilities_allowed).to eq(0) + end +end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 26abc98656e..290dc7df430 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -2632,6 +2632,10 @@ RSpec.describe Ci::Build do value: "#{Gitlab.host_with_port}/#{project.namespace.root_ancestor.path.downcase}#{DependencyProxy::URL_SUFFIX}", public: true, masked: false }, + { key: 'CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX', + value: "#{Gitlab.host_with_port}/#{project.namespace.full_path.downcase}#{DependencyProxy::URL_SUFFIX}", + public: true, + masked: false }, { key: 'CI_API_V4_URL', value: 'http://localhost/api/v4', public: true, masked: false }, { key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true, masked: false }, { key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true, masked: false }, diff --git a/spec/models/clusters/agent_spec.rb b/spec/models/clusters/agent_spec.rb index ea7a55480a8..c8fc09565a9 100644 --- a/spec/models/clusters/agent_spec.rb +++ b/spec/models/clusters/agent_spec.rb @@ -9,6 +9,8 @@ RSpec.describe Clusters::Agent do it { is_expected.to belong_to(:project).class_name('::Project') } it { is_expected.to have_many(:agent_tokens).class_name('Clusters::AgentToken') } it { is_expected.to have_many(:last_used_agent_tokens).class_name('Clusters::AgentToken') } + it { is_expected.to have_many(:group_authorizations).class_name('Clusters::Agents::GroupAuthorization') } + it { is_expected.to have_many(:authorized_groups).through(:group_authorizations) } it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_length_of(:name).is_at_most(63) } diff --git a/spec/models/clusters/agents/group_authorization_spec.rb b/spec/models/clusters/agents/group_authorization_spec.rb new file mode 100644 index 00000000000..2a99fb26e3f --- /dev/null +++ b/spec/models/clusters/agents/group_authorization_spec.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Clusters::Agents::GroupAuthorization do + it { is_expected.to belong_to(:agent).class_name('Clusters::Agent').required } + it { is_expected.to belong_to(:group).class_name('::Group').required } + + it { expect(described_class).to validate_jsonb_schema(['config']) } +end diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb index 6aba91d9471..a8a5ac98a5a 100644 --- a/spec/models/internal_id_spec.rb +++ b/spec/models/internal_id_spec.rb @@ -238,16 +238,48 @@ RSpec.describe InternalId do end end - context 'when the feature flag is disabled' do - stub_feature_flags(generate_iids_without_explicit_locking: false) + context 'when the explicit locking feature flag is disabled' do + before do + stub_feature_flags(generate_iids_without_explicit_locking: false) + end - it_behaves_like 'a monotonically increasing id generator' + context 'when the insert all feature flag is enabled' do + before do + stub_feature_flags(use_insert_all_in_internal_id: true) + end + + it_behaves_like 'a monotonically increasing id generator' + end + + context 'when the insert all feature flag is disabled' do + before do + stub_feature_flags(use_insert_all_in_internal_id: false) + end + + it_behaves_like 'a monotonically increasing id generator' + end end - context 'when the feature flag is enabled' do - stub_feature_flags(generate_iids_without_explicit_locking: true) + context 'when the explicit locking feature flag is enabled' do + before do + stub_feature_flags(generate_iids_without_explicit_locking: true) + end - it_behaves_like 'a monotonically increasing id generator' + context 'when the insert all feature flag is enabled' do + before do + stub_feature_flags(use_insert_all_in_internal_id: true) + end + + it_behaves_like 'a monotonically increasing id generator' + end + + context 'when the insert all feature flag is disabled' do + before do + stub_feature_flags(use_insert_all_in_internal_id: false) + end + + it_behaves_like 'a monotonically increasing id generator' + end end describe '#increment_and_save!' do diff --git a/spec/requests/admin/background_migrations_controller_spec.rb b/spec/requests/admin/background_migrations_controller_spec.rb new file mode 100644 index 00000000000..c7d5d5cae08 --- /dev/null +++ b/spec/requests/admin/background_migrations_controller_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Admin::BackgroundMigrationsController, :enable_admin_mode do + let(:admin) { create(:admin) } + + before do + sign_in(admin) + end + + describe 'POST #retry' do + let(:migration) { create(:batched_background_migration, status: 'failed') } + + before do + create(:batched_background_migration_job, batched_migration: migration, batch_size: 10, min_value: 6, max_value: 15, status: :failed, attempts: 3) + + allow_next_instance_of(Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy) do |batch_class| + allow(batch_class).to receive(:next_batch).with(anything, anything, batch_min_value: 6, batch_size: 5).and_return([6, 10]) + end + end + + subject(:retry_migration) { post retry_admin_background_migration_path(migration) } + + it 'redirects the user to the admin migrations page' do + retry_migration + + expect(response).to redirect_to(admin_background_migrations_path) + end + + it 'retries the migration' do + retry_migration + + expect(migration.reload.status).to eql 'active' + end + + context 'when the migration is not failed' do + let(:migration) { create(:batched_background_migration, status: 'paused') } + + it 'keeps the same migration status' do + expect { retry_migration }.not_to change { migration.reload.status } + end + end + end +end diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb index 2acf6951d50..14d5b8d4744 100644 --- a/spec/requests/api/internal/kubernetes_spec.rb +++ b/spec/requests/api/internal/kubernetes_spec.rb @@ -93,6 +93,44 @@ RSpec.describe API::Internal::Kubernetes do end end + describe 'POST /internal/kubernetes/agent_configuration' do + def send_request(headers: {}, params: {}) + post api('/internal/kubernetes/agent_configuration'), params: params, headers: headers.reverse_merge(jwt_auth_headers) + end + + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, namespace: group) } + let_it_be(:agent) { create(:cluster_agent, project: project) } + let_it_be(:config) do + { + ci_access: { + groups: [ + { id: group.full_path, default_namespace: 'production' } + ] + } + } + end + + include_examples 'authorization' + + context 'agent exists' do + it 'configures the agent and returns a 204' do + send_request(params: { agent_id: agent.id, agent_config: config }) + + expect(response).to have_gitlab_http_status(:no_content) + expect(agent.authorized_groups).to contain_exactly(group) + end + end + + context 'agent does not exist' do + it 'returns a 404' do + send_request(params: { agent_id: -1, agent_config: config }) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + describe 'GET /internal/kubernetes/agent_info' do def send_request(headers: {}, params: {}) get api('/internal/kubernetes/agent_info'), params: params, headers: headers.reverse_merge(jwt_auth_headers) diff --git a/spec/services/clusters/agents/refresh_authorization_service_spec.rb b/spec/services/clusters/agents/refresh_authorization_service_spec.rb new file mode 100644 index 00000000000..8a887b347bb --- /dev/null +++ b/spec/services/clusters/agents/refresh_authorization_service_spec.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Clusters::Agents::RefreshAuthorizationService do + describe '#execute' do + let_it_be(:root_ancestor) { create(:group) } + let_it_be(:removed_group) { create(:group, parent: root_ancestor) } + let_it_be(:modified_group) { create(:group, parent: root_ancestor) } + let_it_be(:added_group) { create(:group, parent: root_ancestor) } + + let(:project) { create(:project, namespace: root_ancestor) } + let(:agent) { create(:cluster_agent, project: project) } + + let(:config) do + { + ci_access: { + groups: [ + { id: added_group.full_path, default_namespace: 'default' }, + { id: modified_group.full_path, default_namespace: 'new-namespace' } + ] + } + }.deep_stringify_keys + end + + subject { described_class.new(agent, config: config).execute } + + before do + default_config = { default_namespace: 'default' } + + agent.group_authorizations.create!(group: removed_group, config: default_config) + agent.group_authorizations.create!(group: modified_group, config: default_config) + end + + it 'refreshes authorizations for the agent' do + expect(subject).to be_truthy + expect(agent.authorized_groups).to contain_exactly(added_group, modified_group) + + added_authorization = agent.group_authorizations.find_by(group: added_group) + expect(added_authorization.config).to eq({ 'default_namespace' => 'default' }) + + modified_authorization = agent.group_authorizations.find_by(group: modified_group) + expect(modified_authorization.config).to eq({ 'default_namespace' => 'new-namespace' }) + end + + context 'config contains no groups' do + let(:config) { {} } + + it 'removes all authorizations' do + expect(subject).to be_truthy + expect(agent.authorized_groups).to be_empty + end + end + + context 'config contains groups outside of the configuration project hierarchy' do + let(:project) { create(:project, namespace: create(:group)) } + + it 'removes all authorizations' do + expect(subject).to be_truthy + expect(agent.authorized_groups).to be_empty + end + end + + context 'configuration project does not belong to a group' do + let(:project) { create(:project) } + + it 'removes all authorizations' do + expect(subject).to be_truthy + expect(agent.authorized_groups).to be_empty + end + end + + context 'config contains too many groups' do + before do + stub_const("#{described_class}::AUTHORIZED_GROUP_LIMIT", 1) + end + + it 'authorizes groups up to the limit' do + expect(subject).to be_truthy + expect(agent.authorized_groups).to contain_exactly(added_group) + end + end + end +end -- cgit v1.2.3