summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-08 06:06:24 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-08 06:06:24 +0000
commit1ef4b65f55f4fc6524a47050b4f6d686beb81d3a (patch)
tree3efc2710e564b86e5e2420d65457f656454006bb /spec
parent18a102a5b95198b6bc8db2589de6353997a33543 (diff)
downloadgitlab-ce-1ef4b65f55f4fc6524a47050b4f6d686beb81d3a.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb47
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb52
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb52
-rw-r--r--spec/db/schema_spec.rb2
-rw-r--r--spec/features/projects/clusters/eks_spec.rb1
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js91
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js117
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/actions_spec.js94
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js59
-rw-r--r--spec/frontend/vue_shared/components/slot_switch_spec.js56
-rw-r--r--spec/helpers/clusters_helper_spec.rb56
-rw-r--r--spec/lib/gitlab/regex_spec.rb9
-rw-r--r--spec/models/application_setting_spec.rb31
-rw-r--r--spec/models/aws/role_spec.rb52
-rw-r--r--spec/presenters/group_clusterable_presenter_spec.rb6
-rw-r--r--spec/presenters/project_clusterable_presenter_spec.rb6
-rw-r--r--spec/requests/api/settings_spec.rb55
-rw-r--r--spec/services/clusters/aws/fetch_credentials_service_spec.rb12
18 files changed, 783 insertions, 15 deletions
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
index 233710b9fc3..d3192593a78 100644
--- a/spec/controllers/admin/clusters_controller_spec.rb
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -73,7 +73,7 @@ describe Admin::ClustersController do
end
describe 'GET #new' do
- def get_new(provider: 'gke')
+ def get_new(provider: 'gcp')
get :new, params: { provider: provider }
end
@@ -318,6 +318,51 @@ describe Admin::ClustersController do
end
end
+ describe 'POST authorize AWS role for EKS cluster' do
+ let(:role_arn) { 'arn:aws:iam::123456789012:role/role-name' }
+ let(:role_external_id) { '12345' }
+
+ let(:params) do
+ {
+ cluster: {
+ role_arn: role_arn,
+ role_external_id: role_external_id
+ }
+ }
+ end
+
+ def go
+ post :authorize_aws_role, params: params
+ end
+
+ it 'creates an Aws::Role record' do
+ expect { go }.to change { Aws::Role.count }
+
+ expect(response.status).to eq 201
+
+ role = Aws::Role.last
+ expect(role.user).to eq admin
+ expect(role.role_arn).to eq role_arn
+ expect(role.role_external_id).to eq role_external_id
+ end
+
+ context 'role cannot be created' do
+ let(:role_arn) { 'invalid-role' }
+
+ it 'does not create a record' do
+ expect { go }.not_to change { Aws::Role.count }
+
+ expect(response.status).to eq 422
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
describe 'GET #cluster_status' do
let(:cluster) { create(:cluster, :providing_by_gcp, :instance) }
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index 51a6dcca640..538a270f567 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -85,7 +85,7 @@ describe Groups::ClustersController do
end
describe 'GET new' do
- def go(provider: 'gke')
+ def go(provider: 'gcp')
get :new, params: { group_id: group, provider: provider }
end
@@ -372,6 +372,56 @@ describe Groups::ClustersController do
end
end
+ describe 'POST authorize AWS role for EKS cluster' do
+ let(:role_arn) { 'arn:aws:iam::123456789012:role/role-name' }
+ let(:role_external_id) { '12345' }
+
+ let(:params) do
+ {
+ cluster: {
+ role_arn: role_arn,
+ role_external_id: role_external_id
+ }
+ }
+ end
+
+ def go
+ post :authorize_aws_role, params: params.merge(group_id: group)
+ end
+
+ it 'creates an Aws::Role record' do
+ expect { go }.to change { Aws::Role.count }
+
+ expect(response.status).to eq 201
+
+ role = Aws::Role.last
+ expect(role.user).to eq user
+ expect(role.role_arn).to eq role_arn
+ expect(role.role_external_id).to eq role_external_id
+ end
+
+ context 'role cannot be created' do
+ let(:role_arn) { 'invalid-role' }
+
+ it 'does not create a record' do
+ expect { go }.not_to change { Aws::Role.count }
+
+ expect(response.status).to eq 422
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
describe 'GET cluster_status' do
let(:cluster) { create(:cluster, :providing_by_gcp, cluster_type: :group_type, groups: [group]) }
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index e1f6d571d27..1b6b0ff025e 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -79,7 +79,7 @@ describe Projects::ClustersController do
end
describe 'GET new' do
- def go(provider: 'gke')
+ def go(provider: 'gcp')
get :new, params: {
namespace_id: project.namespace,
project_id: project,
@@ -373,6 +373,56 @@ describe Projects::ClustersController do
end
end
+ describe 'POST authorize AWS role for EKS cluster' do
+ let(:role_arn) { 'arn:aws:iam::123456789012:role/role-name' }
+ let(:role_external_id) { '12345' }
+
+ let(:params) do
+ {
+ cluster: {
+ role_arn: role_arn,
+ role_external_id: role_external_id
+ }
+ }
+ end
+
+ def go
+ post :authorize_aws_role, params: params.merge(namespace_id: project.namespace, project_id: project)
+ end
+
+ it 'creates an Aws::Role record' do
+ expect { go }.to change { Aws::Role.count }
+
+ expect(response.status).to eq 201
+
+ role = Aws::Role.last
+ expect(role.user).to eq user
+ expect(role.role_arn).to eq role_arn
+ expect(role.role_external_id).to eq role_external_id
+ end
+
+ context 'role cannot be created' do
+ let(:role_arn) { 'invalid-role' }
+
+ it 'does not create a record' do
+ expect { go }.not_to change { Aws::Role.count }
+
+ expect(response.status).to eq 422
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(project) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(project) }
+ it { expect { go }.to be_denied_for(:developer).of(project) }
+ it { expect { go }.to be_denied_for(:reporter).of(project) }
+ it { expect { go }.to be_denied_for(:guest).of(project) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
describe 'GET cluster_status' do
let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) }
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index e4eddb87858..d340cec8b70 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -13,7 +13,7 @@ describe 'Database schema' do
# EE: edit the ee/spec/db/schema_support.rb
IGNORED_FK_COLUMNS = {
abuse_reports: %w[reporter_id user_id],
- application_settings: %w[performance_bar_allowed_group_id slack_app_id snowplow_site_id],
+ application_settings: %w[performance_bar_allowed_group_id slack_app_id snowplow_site_id eks_account_id eks_access_key_id],
approvers: %w[target_id user_id],
approvals: %w[user_id],
approver_groups: %w[target_id],
diff --git a/spec/features/projects/clusters/eks_spec.rb b/spec/features/projects/clusters/eks_spec.rb
index 9cb989b8004..e0ebccd85ac 100644
--- a/spec/features/projects/clusters/eks_spec.rb
+++ b/spec/features/projects/clusters/eks_spec.rb
@@ -10,6 +10,7 @@ describe 'AWS EKS Cluster', :js do
project.add_maintainer(user)
gitlab_sign_in(user)
allow(Projects::ClustersController).to receive(:STATUS_POLLING_INTERVAL) { 100 }
+ stub_application_setting(eks_integration_enabled: true)
end
context 'when user does not have a cluster and visits cluster index page' do
diff --git a/spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js b/spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js
new file mode 100644
index 00000000000..4bf3ac430f5
--- /dev/null
+++ b/spec/frontend/create_cluster/eks_cluster/components/create_eks_cluster_spec.js
@@ -0,0 +1,91 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+
+import CreateEksCluster from '~/create_cluster/eks_cluster/components/create_eks_cluster.vue';
+import EksClusterConfigurationForm from '~/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue';
+import ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('CreateEksCluster', () => {
+ let vm;
+ let state;
+ const gitlabManagedClusterHelpPath = 'gitlab-managed-cluster-help-path';
+ const accountAndExternalIdsHelpPath = 'account-and-external-id-help-path';
+ const createRoleArnHelpPath = 'role-arn-help-path';
+ const kubernetesIntegrationHelpPath = 'kubernetes-integration';
+ const externalLinkIcon = 'external-link';
+
+ beforeEach(() => {
+ state = { hasCredentials: false };
+ const store = new Vuex.Store({
+ state,
+ });
+
+ vm = shallowMount(CreateEksCluster, {
+ propsData: {
+ gitlabManagedClusterHelpPath,
+ accountAndExternalIdsHelpPath,
+ createRoleArnHelpPath,
+ externalLinkIcon,
+ kubernetesIntegrationHelpPath,
+ },
+ localVue,
+ store,
+ });
+ });
+ afterEach(() => vm.destroy());
+
+ describe('when credentials are provided', () => {
+ beforeEach(() => {
+ state.hasCredentials = true;
+ });
+
+ it('displays eks cluster configuration form when credentials are valid', () => {
+ expect(vm.find(EksClusterConfigurationForm).exists()).toBe(true);
+ });
+
+ describe('passes to the cluster configuration form', () => {
+ it('help url for kubernetes integration documentation', () => {
+ expect(vm.find(EksClusterConfigurationForm).props('gitlabManagedClusterHelpPath')).toBe(
+ gitlabManagedClusterHelpPath,
+ );
+ });
+
+ it('help url for gitlab managed cluster documentation', () => {
+ expect(vm.find(EksClusterConfigurationForm).props('kubernetesIntegrationHelpPath')).toBe(
+ kubernetesIntegrationHelpPath,
+ );
+ });
+ });
+ });
+
+ describe('when credentials are invalid', () => {
+ beforeEach(() => {
+ state.hasCredentials = false;
+ });
+
+ it('displays service credentials form', () => {
+ expect(vm.find(ServiceCredentialsForm).exists()).toBe(true);
+ });
+
+ describe('passes to the service credentials form', () => {
+ it('help url for account and external ids', () => {
+ expect(vm.find(ServiceCredentialsForm).props('accountAndExternalIdsHelpPath')).toBe(
+ accountAndExternalIdsHelpPath,
+ );
+ });
+
+ it('external link icon', () => {
+ expect(vm.find(ServiceCredentialsForm).props('externalLinkIcon')).toBe(externalLinkIcon);
+ });
+
+ it('help url to create a role ARN', () => {
+ expect(vm.find(ServiceCredentialsForm).props('createRoleArnHelpPath')).toBe(
+ createRoleArnHelpPath,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js b/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
new file mode 100644
index 00000000000..0be723b48f0
--- /dev/null
+++ b/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
@@ -0,0 +1,117 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+
+import ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+
+import eksClusterState from '~/create_cluster/eks_cluster/store/state';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('ServiceCredentialsForm', () => {
+ let vm;
+ let state;
+ let createRoleAction;
+ const accountId = 'accountId';
+ const externalId = 'externalId';
+
+ beforeEach(() => {
+ state = Object.assign(eksClusterState(), {
+ accountId,
+ externalId,
+ });
+ createRoleAction = jest.fn();
+
+ const store = new Vuex.Store({
+ state,
+ actions: {
+ createRole: createRoleAction,
+ },
+ });
+ vm = shallowMount(ServiceCredentialsForm, {
+ propsData: {
+ accountAndExternalIdsHelpPath: '',
+ createRoleArnHelpPath: '',
+ externalLinkIcon: '',
+ },
+ localVue,
+ store,
+ });
+ });
+ afterEach(() => vm.destroy());
+
+ const findAccountIdInput = () => vm.find('#gitlab-account-id');
+ const findCopyAccountIdButton = () => vm.find('.js-copy-account-id-button');
+ const findExternalIdInput = () => vm.find('#eks-external-id');
+ const findCopyExternalIdButton = () => vm.find('.js-copy-external-id-button');
+ const findInvalidCredentials = () => vm.find('.js-invalid-credentials');
+ const findSubmitButton = () => vm.find(LoadingButton);
+ const findForm = () => vm.find('form[name="service-credentials-form"]');
+
+ it('displays provided account id', () => {
+ expect(findAccountIdInput().attributes('value')).toBe(accountId);
+ });
+
+ it('allows to copy account id', () => {
+ expect(findCopyAccountIdButton().props('text')).toBe(accountId);
+ });
+
+ it('displays provided external id', () => {
+ expect(findExternalIdInput().attributes('value')).toBe(externalId);
+ });
+
+ it('allows to copy external id', () => {
+ expect(findCopyExternalIdButton().props('text')).toBe(externalId);
+ });
+
+ it('disables submit button when role ARN is not provided', () => {
+ expect(findSubmitButton().attributes('disabled')).toBeTruthy();
+ });
+
+ it('enables submit button when role ARN is not provided', () => {
+ vm.setData({ roleArn: '123' });
+
+ expect(findSubmitButton().attributes('disabled')).toBeFalsy();
+ });
+
+ it('dispatches createRole action when form is submitted', () => {
+ findForm().trigger('submit');
+
+ expect(createRoleAction).toHaveBeenCalled();
+ });
+
+ describe('when is creating role', () => {
+ beforeEach(() => {
+ vm.setData({ roleArn: '123' }); // set role ARN to enable button
+
+ state.isCreatingRole = true;
+ });
+
+ it('disables submit button', () => {
+ expect(findSubmitButton().props('disabled')).toBe(true);
+ });
+
+ it('sets submit button as loading', () => {
+ expect(findSubmitButton().props('loading')).toBe(true);
+ });
+
+ it('displays Authenticating label on submit button', () => {
+ expect(findSubmitButton().props('label')).toBe('Authenticating');
+ });
+ });
+
+ describe('when role can’t be created', () => {
+ beforeEach(() => {
+ state.createRoleError = 'Invalid credentials';
+ });
+
+ it('displays invalid role warning banner', () => {
+ expect(findInvalidCredentials().exists()).toBe(true);
+ });
+
+ it('displays invalid role error message', () => {
+ expect(findInvalidCredentials().text()).toContain(state.createRoleError);
+ });
+ });
+});
diff --git a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
index 1ed7f806804..99c8cdba296 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
@@ -13,7 +13,12 @@ import {
SET_ROLE,
SET_SECURITY_GROUP,
SET_GITLAB_MANAGED_CLUSTER,
+ REQUEST_CREATE_ROLE,
+ CREATE_ROLE_SUCCESS,
+ CREATE_ROLE_ERROR,
} from '~/create_cluster/eks_cluster/store/mutation_types';
+import axios from '~/lib/utils/axios_utils';
+import MockAdapter from 'axios-mock-adapter';
describe('EKS Cluster Store Actions', () => {
let clusterName;
@@ -26,6 +31,8 @@ describe('EKS Cluster Store Actions', () => {
let keyPair;
let securityGroup;
let gitlabManagedCluster;
+ let mock;
+ let state;
beforeEach(() => {
clusterName = 'my cluster';
@@ -38,6 +45,19 @@ describe('EKS Cluster Store Actions', () => {
keyPair = { name: 'key-pair-1' };
securityGroup = { name: 'default group' };
gitlabManagedCluster = true;
+
+ state = {
+ ...createState(),
+ createRolePath: '/clusters/roles/',
+ };
+ });
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
});
it.each`
@@ -55,6 +75,78 @@ describe('EKS Cluster Store Actions', () => {
`(`$action commits $mutation with $payloadDescription payload`, data => {
const { action, mutation, payload } = data;
- testAction(actions[action], payload, createState(), [{ type: mutation, payload }]);
+ testAction(actions[action], payload, state, [{ type: mutation, payload }]);
+ });
+
+ describe('createRole', () => {
+ const payload = {
+ roleArn: 'role_arn',
+ externalId: 'externalId',
+ };
+
+ describe('when request succeeds', () => {
+ beforeEach(() => {
+ mock
+ .onPost(state.createRolePath, {
+ role_arn: payload.roleArn,
+ role_external_id: payload.externalId,
+ })
+ .reply(201);
+ });
+
+ it('dispatches createRoleSuccess action', () =>
+ testAction(
+ actions.createRole,
+ payload,
+ state,
+ [],
+ [{ type: 'requestCreateRole' }, { type: 'createRoleSuccess' }],
+ ));
+ });
+
+ describe('when request fails', () => {
+ let error;
+
+ beforeEach(() => {
+ error = new Error('Request failed with status code 400');
+ mock
+ .onPost(state.createRolePath, {
+ role_arn: payload.roleArn,
+ role_external_id: payload.externalId,
+ })
+ .reply(400, error);
+ });
+
+ it('dispatches createRoleError action', () =>
+ testAction(
+ actions.createRole,
+ payload,
+ state,
+ [],
+ [{ type: 'requestCreateRole' }, { type: 'createRoleError', payload: { error } }],
+ ));
+ });
+ });
+
+ describe('requestCreateRole', () => {
+ it('commits requestCreaterole mutation', () => {
+ testAction(actions.requestCreateRole, null, state, [{ type: REQUEST_CREATE_ROLE }]);
+ });
+ });
+
+ describe('createRoleSuccess', () => {
+ it('commits createRoleSuccess mutation', () => {
+ testAction(actions.createRoleSuccess, null, state, [{ type: CREATE_ROLE_SUCCESS }]);
+ });
+ });
+
+ describe('createRoleError', () => {
+ it('commits createRoleError mutation', () => {
+ const payload = {
+ error: new Error(),
+ };
+
+ testAction(actions.createRoleError, payload, state, [{ type: CREATE_ROLE_ERROR, payload }]);
+ });
});
});
diff --git a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
index 81b65180fb5..2637b4822a5 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/mutations_spec.js
@@ -9,6 +9,9 @@ import {
SET_ROLE,
SET_SECURITY_GROUP,
SET_GITLAB_MANAGED_CLUSTER,
+ REQUEST_CREATE_ROLE,
+ CREATE_ROLE_SUCCESS,
+ CREATE_ROLE_ERROR,
} from '~/create_cluster/eks_cluster/store/mutation_types';
import createState from '~/create_cluster/eks_cluster/store/state';
import mutations from '~/create_cluster/eks_cluster/store/mutations';
@@ -59,4 +62,60 @@ describe('Create EKS cluster store mutations', () => {
mutations[mutation](state, payload);
expect(state[mutatedProperty]).toBe(expectedValue);
});
+
+ describe(`mutation ${REQUEST_CREATE_ROLE}`, () => {
+ beforeEach(() => {
+ mutations[REQUEST_CREATE_ROLE](state);
+ });
+
+ it('sets isCreatingRole to true', () => {
+ expect(state.isCreatingRole).toBe(true);
+ });
+
+ it('sets createRoleError to null', () => {
+ expect(state.createRoleError).toBe(null);
+ });
+
+ it('sets hasCredentials to false', () => {
+ expect(state.hasCredentials).toBe(false);
+ });
+ });
+
+ describe(`mutation ${CREATE_ROLE_SUCCESS}`, () => {
+ beforeEach(() => {
+ mutations[CREATE_ROLE_SUCCESS](state);
+ });
+
+ it('sets isCreatingRole to false', () => {
+ expect(state.isCreatingRole).toBe(false);
+ });
+
+ it('sets createRoleError to null', () => {
+ expect(state.createRoleError).toBe(null);
+ });
+
+ it('sets hasCredentials to false', () => {
+ expect(state.hasCredentials).toBe(true);
+ });
+ });
+
+ describe(`mutation ${CREATE_ROLE_ERROR}`, () => {
+ const error = new Error();
+
+ beforeEach(() => {
+ mutations[CREATE_ROLE_ERROR](state, { error });
+ });
+
+ it('sets isCreatingRole to false', () => {
+ expect(state.isCreatingRole).toBe(false);
+ });
+
+ it('sets createRoleError to the error object', () => {
+ expect(state.createRoleError).toBe(error);
+ });
+
+ it('sets hasCredentials to false', () => {
+ expect(state.hasCredentials).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/slot_switch_spec.js b/spec/frontend/vue_shared/components/slot_switch_spec.js
new file mode 100644
index 00000000000..cff955c05b2
--- /dev/null
+++ b/spec/frontend/vue_shared/components/slot_switch_spec.js
@@ -0,0 +1,56 @@
+import { shallowMount } from '@vue/test-utils';
+
+import SlotSwitch from '~/vue_shared/components/slot_switch';
+
+describe('SlotSwitch', () => {
+ const slots = {
+ first: '<a>AGP</a>',
+ second: '<p>PCI</p>',
+ };
+
+ let wrapper;
+
+ const createComponent = propsData => {
+ wrapper = shallowMount(SlotSwitch, {
+ propsData,
+ slots,
+ sync: false,
+ });
+ };
+
+ const getChildrenHtml = () => wrapper.findAll('* *').wrappers.map(c => c.html());
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ it('throws an error if activeSlotNames is missing', () => {
+ expect(createComponent).toThrow('[Vue warn]: Missing required prop: "activeSlotNames"');
+ });
+
+ it('renders no slots if activeSlotNames is empty', () => {
+ createComponent({
+ activeSlotNames: [],
+ });
+
+ expect(getChildrenHtml().length).toBe(0);
+ });
+
+ it('renders one slot if activeSlotNames contains single slot name', () => {
+ createComponent({
+ activeSlotNames: ['first'],
+ });
+
+ expect(getChildrenHtml()).toEqual([slots.first]);
+ });
+
+ it('renders multiple slots if activeSlotNames contains multiple slot names', () => {
+ createComponent({
+ activeSlotNames: Object.keys(slots),
+ });
+
+ expect(getChildrenHtml()).toEqual(Object.values(slots));
+ });
+});
diff --git a/spec/helpers/clusters_helper_spec.rb b/spec/helpers/clusters_helper_spec.rb
index 4ea0f76fc28..1ee638ddf04 100644
--- a/spec/helpers/clusters_helper_spec.rb
+++ b/spec/helpers/clusters_helper_spec.rb
@@ -30,4 +30,60 @@ describe ClustersHelper do
end
end
end
+
+ describe '#create_new_cluster_label' do
+ subject { helper.create_new_cluster_label(provider: provider) }
+
+ context 'GCP provider' do
+ let(:provider) { 'gcp' }
+
+ it { is_expected.to eq('Create new Cluster on GKE') }
+ end
+
+ context 'AWS provider' do
+ let(:provider) { 'aws' }
+
+ it { is_expected.to eq('Create new Cluster on EKS') }
+ end
+
+ context 'other provider' do
+ let(:provider) { 'other' }
+
+ it { is_expected.to eq('Create new Cluster') }
+ end
+
+ context 'no provider' do
+ let(:provider) { nil }
+
+ it { is_expected.to eq('Create new Cluster') }
+ end
+ end
+
+ describe '#render_new_provider_form' do
+ subject { helper.new_cluster_partial(provider: provider) }
+
+ context 'GCP provider' do
+ let(:provider) { 'gcp' }
+
+ it { is_expected.to eq('clusters/clusters/gcp/new') }
+ end
+
+ context 'AWS provider' do
+ let(:provider) { 'aws' }
+
+ it { is_expected.to eq('clusters/clusters/aws/new') }
+ end
+
+ context 'other provider' do
+ let(:provider) { 'other' }
+
+ it { is_expected.to eq('clusters/clusters/cloud_providers/cloud_provider_selector') }
+ end
+
+ context 'no provider' do
+ let(:provider) { nil }
+
+ it { is_expected.to eq('clusters/clusters/cloud_providers/cloud_provider_selector') }
+ end
+ end
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 4678adcd85f..1397add9f5a 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -66,6 +66,15 @@ describe Gitlab::Regex do
end
describe '.aws_account_id_regex' do
+ subject { described_class.aws_account_id_regex }
+
+ it { is_expected.to match('123456789012') }
+ it { is_expected.not_to match('12345678901') }
+ it { is_expected.not_to match('1234567890123') }
+ it { is_expected.not_to match('12345678901a') }
+ end
+
+ describe '.aws_arn_regex' do
subject { described_class.aws_arn_regex }
it { is_expected.to match('arn:aws:iam::123456789012:role/role-name') }
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index b6fc152e478..9d3f5b4b132 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -106,6 +106,37 @@ describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:lets_encrypt_notification_email) }
end
+ describe 'EKS integration' do
+ before do
+ setting.eks_integration_enabled = eks_enabled
+ end
+
+ context 'integration is disabled' do
+ let(:eks_enabled) { false }
+
+ it { is_expected.to allow_value(nil).for(:eks_account_id) }
+ it { is_expected.to allow_value(nil).for(:eks_access_key_id) }
+ it { is_expected.to allow_value(nil).for(:eks_secret_access_key) }
+ end
+
+ context 'integration is enabled' do
+ let(:eks_enabled) { true }
+
+ it { is_expected.to allow_value('123456789012').for(:eks_account_id) }
+ it { is_expected.not_to allow_value(nil).for(:eks_account_id) }
+ it { is_expected.not_to allow_value('123').for(:eks_account_id) }
+ it { is_expected.not_to allow_value('12345678901a').for(:eks_account_id) }
+
+ it { is_expected.to allow_value('access-key-id-12').for(:eks_access_key_id) }
+ it { is_expected.not_to allow_value('a' * 129).for(:eks_access_key_id) }
+ it { is_expected.not_to allow_value('short-key').for(:eks_access_key_id) }
+ it { is_expected.not_to allow_value(nil).for(:eks_access_key_id) }
+
+ it { is_expected.to allow_value('secret-access-key').for(:eks_secret_access_key) }
+ it { is_expected.not_to allow_value(nil).for(:eks_secret_access_key) }
+ end
+ end
+
describe 'default_artifacts_expire_in' do
it 'sets an error if it cannot parse' do
setting.update(default_artifacts_expire_in: 'a')
diff --git a/spec/models/aws/role_spec.rb b/spec/models/aws/role_spec.rb
index c40752e40a6..d4165567146 100644
--- a/spec/models/aws/role_spec.rb
+++ b/spec/models/aws/role_spec.rb
@@ -31,4 +31,56 @@ describe Aws::Role do
end
end
end
+
+ describe 'callbacks' do
+ describe '#ensure_role_external_id!' do
+ subject { role.validate }
+
+ context 'for a new record' do
+ let(:role) { build(:aws_role, role_external_id: nil) }
+
+ it 'calls #ensure_role_external_id!' do
+ expect(role).to receive(:ensure_role_external_id!)
+
+ subject
+ end
+ end
+
+ context 'for an existing record' do
+ let(:role) { create(:aws_role) }
+
+ it 'does not call #ensure_role_external_id!' do
+ expect(role).not_to receive(:ensure_role_external_id!)
+
+ subject
+ end
+ end
+ end
+ end
+
+ describe '#ensure_role_external_id!' do
+ let(:role) { build(:aws_role, role_external_id: external_id) }
+
+ subject { role.ensure_role_external_id! }
+
+ context 'role_external_id is blank' do
+ let(:external_id) { nil }
+
+ it 'generates an external ID and assigns it to the record' do
+ subject
+
+ expect(role.role_external_id).to be_present
+ end
+ end
+
+ context 'role_external_id is already set' do
+ let(:external_id) { 'external-id' }
+
+ it 'does not change the existing external id' do
+ subject
+
+ expect(role.role_external_id).to eq external_id
+ end
+ end
+ end
end
diff --git a/spec/presenters/group_clusterable_presenter_spec.rb b/spec/presenters/group_clusterable_presenter_spec.rb
index fa77273f6aa..11a8decc9cc 100644
--- a/spec/presenters/group_clusterable_presenter_spec.rb
+++ b/spec/presenters/group_clusterable_presenter_spec.rb
@@ -43,6 +43,12 @@ describe GroupClusterablePresenter do
it { is_expected.to eq(new_group_cluster_path(group)) }
end
+ describe '#authorize_aws_role_path' do
+ subject { presenter.authorize_aws_role_path }
+
+ it { is_expected.to eq(authorize_aws_role_group_clusters_path(group)) }
+ end
+
describe '#create_user_clusters_path' do
subject { presenter.create_user_clusters_path }
diff --git a/spec/presenters/project_clusterable_presenter_spec.rb b/spec/presenters/project_clusterable_presenter_spec.rb
index 6786a84243f..441c2a50fea 100644
--- a/spec/presenters/project_clusterable_presenter_spec.rb
+++ b/spec/presenters/project_clusterable_presenter_spec.rb
@@ -43,6 +43,12 @@ describe ProjectClusterablePresenter do
it { is_expected.to eq(new_project_cluster_path(project)) }
end
+ describe '#authorize_aws_role_path' do
+ subject { presenter.authorize_aws_role_path }
+
+ it { is_expected.to eq(authorize_aws_role_project_clusters_path(project)) }
+ end
+
describe '#create_user_clusters_path' do
subject { presenter.create_user_clusters_path }
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 760eafe33e4..5aba798f2c2 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -271,6 +271,61 @@ describe API::Settings, 'Settings' do
end
end
+ context 'EKS integration settings' do
+ let(:attribute_names) { settings.keys.map(&:to_s) }
+ let(:sensitive_attributes) { %w(eks_secret_access_key) }
+ let(:exposed_attributes) { attribute_names - sensitive_attributes }
+
+ let(:settings) do
+ {
+ eks_integration_enabled: true,
+ eks_account_id: '123456789012',
+ eks_access_key_id: 'access-key-id-12',
+ eks_secret_access_key: 'secret-access-key'
+ }
+ end
+
+ it 'includes attributes in the API' do
+ get api("/application/settings", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ exposed_attributes.each do |attribute|
+ expect(json_response.keys).to include(attribute)
+ end
+ end
+
+ it 'does not include sensitive attributes in the API' do
+ get api("/application/settings", admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ sensitive_attributes.each do |attribute|
+ expect(json_response.keys).not_to include(attribute)
+ end
+ end
+
+ it 'allows updating the settings' do
+ put api("/application/settings", admin), params: settings
+
+ expect(response).to have_gitlab_http_status(200)
+ settings.each do |attribute, value|
+ expect(ApplicationSetting.current.public_send(attribute)).to eq(value)
+ end
+ end
+
+ context 'EKS integration is enabled but params are blank' do
+ let(:settings) { Hash[eks_integration_enabled: true] }
+
+ it 'does not update the settings' do
+ put api("/application/settings", admin), params: settings
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['error']).to include('eks_account_id is missing')
+ expect(json_response['error']).to include('eks_access_key_id is missing')
+ expect(json_response['error']).to include('eks_secret_access_key is missing')
+ end
+ end
+ end
+
context "missing plantuml_url value when plantuml_enabled is true" do
it "returns a blank parameter error message" do
put api("/application/settings", admin), params: { plantuml_enabled: true }
diff --git a/spec/services/clusters/aws/fetch_credentials_service_spec.rb b/spec/services/clusters/aws/fetch_credentials_service_spec.rb
index 6476130ab32..09f3be0534d 100644
--- a/spec/services/clusters/aws/fetch_credentials_service_spec.rb
+++ b/spec/services/clusters/aws/fetch_credentials_service_spec.rb
@@ -13,15 +13,6 @@ describe Clusters::Aws::FetchCredentialsService do
let(:sts_client) { Aws::STS::Client.new(credentials: gitlab_credentials, region: provider.region) }
let(:assumed_role) { instance_double(Aws::AssumeRoleCredentials, credentials: assumed_role_credentials) }
- let(:kubernetes_provisioner_settings) do
- {
- aws: {
- access_key_id: gitlab_access_key_id,
- secret_access_key: gitlab_secret_access_key
- }
- }
- end
-
let(:assumed_role_credentials) { double }
subject { described_class.new(provider).execute }
@@ -30,7 +21,8 @@ describe Clusters::Aws::FetchCredentialsService do
let(:provision_role) { create(:aws_role, user: provider.created_by_user) }
before do
- stub_config(kubernetes: { provisioners: kubernetes_provisioner_settings })
+ stub_application_setting(eks_access_key_id: gitlab_access_key_id)
+ stub_application_setting(eks_secret_access_key: gitlab_secret_access_key)
expect(Aws::Credentials).to receive(:new)
.with(gitlab_access_key_id, gitlab_secret_access_key)