diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-13 06:06:38 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-13 06:06:38 +0000 |
commit | 213ce7805856f2cc1d019a03c76ae0d098337c26 (patch) | |
tree | e97e9e02515dd83a2a5decd66ae8553ebb93b350 /spec | |
parent | d41c040fa25a8b4092843b84bf7d839591b6ee09 (diff) | |
download | gitlab-ce-213ce7805856f2cc1d019a03c76ae0d098337c26.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/admin/clusters_controller_spec.rb | 84 | ||||
-rw-r--r-- | spec/controllers/groups/clusters_controller_spec.rb | 94 | ||||
-rw-r--r-- | spec/controllers/projects/clusters_controller_spec.rb | 94 | ||||
-rw-r--r-- | spec/factories/clusters/providers/aws.rb | 1 | ||||
-rw-r--r-- | spec/features/projects/clusters/gcp_spec.rb | 6 | ||||
-rw-r--r-- | spec/models/clusters/cluster_spec.rb | 23 | ||||
-rw-r--r-- | spec/models/clusters/providers/aws_spec.rb | 25 | ||||
-rw-r--r-- | spec/models/clusters/providers/gcp_spec.rb | 16 | ||||
-rw-r--r-- | spec/models/project_services/data_fields_spec.rb | 18 | ||||
-rw-r--r-- | spec/presenters/instance_clusterable_presenter_spec.rb | 37 | ||||
-rw-r--r-- | spec/requests/api/services_spec.rb | 4 | ||||
-rw-r--r-- | spec/services/clusters/aws/fetch_credentials_service_spec.rb | 29 | ||||
-rw-r--r-- | spec/services/clusters/aws/provision_service_spec.rb | 13 | ||||
-rw-r--r-- | spec/services/clusters/aws/proxy_service_spec.rb | 210 |
14 files changed, 602 insertions, 52 deletions
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb index d3192593a78..e6decd24f0a 100644 --- a/spec/controllers/admin/clusters_controller_spec.rb +++ b/spec/controllers/admin/clusters_controller_spec.rb @@ -248,6 +248,69 @@ describe Admin::ClustersController do end end + describe 'POST #create_aws' do + let(:params) do + { + cluster: { + name: 'new-cluster', + provider_aws_attributes: { + key_name: 'key', + role_arn: 'arn:role', + region: 'region', + vpc_id: 'vpc', + instance_type: 'instance type', + num_nodes: 3, + security_group_id: 'security group', + subnet_ids: %w(subnet1 subnet2) + } + } + } + end + + def post_create_aws + post :create_aws, params: params + end + + it 'creates a new cluster' do + expect(ClusterProvisionWorker).to receive(:perform_async) + expect { post_create_aws }.to change { Clusters::Cluster.count } + .and change { Clusters::Providers::Aws.count } + + cluster = Clusters::Cluster.instance_type.first + + expect(response.status).to eq(201) + expect(response.location).to eq(admin_cluster_path(cluster)) + expect(cluster).to be_aws + expect(cluster).to be_kubernetes + end + + context 'params are invalid' do + let(:params) do + { + cluster: { name: '' } + } + end + + it 'does not create a cluster' do + expect { post_create_aws }.not_to change { Clusters::Cluster.count } + + expect(response.status).to eq(422) + expect(response.content_type).to eq('application/json') + expect(response.body).to include('is invalid') + end + end + + describe 'security' do + before do + allow(WaitForClusterCreationWorker).to receive(:perform_in) + end + + it { expect { post_create_aws }.to be_allowed_for(:admin) } + it { expect { post_create_aws }.to be_denied_for(:user) } + it { expect { post_create_aws }.to be_denied_for(:external) } + end + end + describe 'POST #create_user' do let(:params) do { @@ -363,6 +426,27 @@ describe Admin::ClustersController do end end + describe 'DELETE revoke AWS role for EKS cluster' do + let!(:role) { create(:aws_role, user: admin) } + + def go + delete :revoke_aws_role + end + + it 'deletes the Aws::Role record' do + expect { go }.to change { Aws::Role.count } + + expect(response.status).to eq 204 + expect(admin.reload_aws_role).to be_nil + 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 538a270f567..d027405703b 100644 --- a/spec/controllers/groups/clusters_controller_spec.rb +++ b/spec/controllers/groups/clusters_controller_spec.rb @@ -372,6 +372,74 @@ describe Groups::ClustersController do end end + describe 'POST #create_aws' do + let(:params) do + { + cluster: { + name: 'new-cluster', + provider_aws_attributes: { + key_name: 'key', + role_arn: 'arn:role', + region: 'region', + vpc_id: 'vpc', + instance_type: 'instance type', + num_nodes: 3, + security_group_id: 'security group', + subnet_ids: %w(subnet1 subnet2) + } + } + } + end + + def post_create_aws + post :create_aws, params: params.merge(group_id: group) + end + + it 'creates a new cluster' do + expect(ClusterProvisionWorker).to receive(:perform_async) + expect { post_create_aws }.to change { Clusters::Cluster.count } + .and change { Clusters::Providers::Aws.count } + + cluster = group.clusters.first + + expect(response.status).to eq(201) + expect(response.location).to eq(group_cluster_path(group, cluster)) + expect(cluster).to be_aws + expect(cluster).to be_kubernetes + end + + context 'params are invalid' do + let(:params) do + { + cluster: { name: '' } + } + end + + it 'does not create a cluster' do + expect { post_create_aws }.not_to change { Clusters::Cluster.count } + + expect(response.status).to eq(422) + expect(response.content_type).to eq('application/json') + expect(response.body).to include('is invalid') + end + end + + describe 'security' do + before do + allow(WaitForClusterCreationWorker).to receive(:perform_in) + end + + it { expect { post_create_aws }.to be_allowed_for(:admin) } + it { expect { post_create_aws }.to be_allowed_for(:owner).of(group) } + it { expect { post_create_aws }.to be_allowed_for(:maintainer).of(group) } + it { expect { post_create_aws }.to be_denied_for(:developer).of(group) } + it { expect { post_create_aws }.to be_denied_for(:reporter).of(group) } + it { expect { post_create_aws }.to be_denied_for(:guest).of(group) } + it { expect { post_create_aws }.to be_denied_for(:user) } + it { expect { post_create_aws }.to be_denied_for(:external) } + 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' } @@ -422,6 +490,32 @@ describe Groups::ClustersController do end end + describe 'DELETE revoke AWS role for EKS cluster' do + let!(:role) { create(:aws_role, user: user) } + + def go + delete :revoke_aws_role, params: { group_id: group } + end + + it 'deletes the Aws::Role record' do + expect { go }.to change { Aws::Role.count } + + expect(response.status).to eq 204 + expect(user.reload_aws_role).to be_nil + 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 1b6b0ff025e..5a0512a042e 100644 --- a/spec/controllers/projects/clusters_controller_spec.rb +++ b/spec/controllers/projects/clusters_controller_spec.rb @@ -373,6 +373,74 @@ describe Projects::ClustersController do end end + describe 'POST #create_aws' do + let(:params) do + { + cluster: { + name: 'new-cluster', + provider_aws_attributes: { + key_name: 'key', + role_arn: 'arn:role', + region: 'region', + vpc_id: 'vpc', + instance_type: 'instance type', + num_nodes: 3, + security_group_id: 'security group', + subnet_ids: %w(subnet1 subnet2) + } + } + } + end + + def post_create_aws + post :create_aws, params: params.merge(namespace_id: project.namespace, project_id: project) + end + + it 'creates a new cluster' do + expect(ClusterProvisionWorker).to receive(:perform_async) + expect { post_create_aws }.to change { Clusters::Cluster.count } + .and change { Clusters::Providers::Aws.count } + + cluster = project.clusters.first + + expect(response.status).to eq(201) + expect(response.location).to eq(project_cluster_path(project, cluster)) + expect(cluster).to be_aws + expect(cluster).to be_kubernetes + end + + context 'params are invalid' do + let(:params) do + { + cluster: { name: '' } + } + end + + it 'does not create a cluster' do + expect { post_create_aws }.not_to change { Clusters::Cluster.count } + + expect(response.status).to eq(422) + expect(response.content_type).to eq('application/json') + expect(response.body).to include('is invalid') + end + end + + describe 'security' do + before do + allow(WaitForClusterCreationWorker).to receive(:perform_in) + end + + it { expect { post_create_aws }.to be_allowed_for(:admin) } + it { expect { post_create_aws }.to be_allowed_for(:owner).of(project) } + it { expect { post_create_aws }.to be_allowed_for(:maintainer).of(project) } + it { expect { post_create_aws }.to be_denied_for(:developer).of(project) } + it { expect { post_create_aws }.to be_denied_for(:reporter).of(project) } + it { expect { post_create_aws }.to be_denied_for(:guest).of(project) } + it { expect { post_create_aws }.to be_denied_for(:user) } + it { expect { post_create_aws }.to be_denied_for(:external) } + 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' } @@ -423,6 +491,32 @@ describe Projects::ClustersController do end end + describe 'DELETE revoke AWS role for EKS cluster' do + let!(:role) { create(:aws_role, user: user) } + + def go + delete :revoke_aws_role, params: { namespace_id: project.namespace, project_id: project } + end + + it 'deletes the Aws::Role record' do + expect { go }.to change { Aws::Role.count } + + expect(response.status).to eq 204 + expect(user.reload_aws_role).to be_nil + 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/factories/clusters/providers/aws.rb b/spec/factories/clusters/providers/aws.rb index dc18762607b..e4b10aa5f33 100644 --- a/spec/factories/clusters/providers/aws.rb +++ b/spec/factories/clusters/providers/aws.rb @@ -3,7 +3,6 @@ FactoryBot.define do factory :cluster_provider_aws, class: Clusters::Providers::Aws do association :cluster, platform_type: :kubernetes, provider_type: :aws - created_by_user factory: :user role_arn { 'arn:aws:iam::123456789012:role/role-name' } vpc_id { 'vpc-00000000000000000' } diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index b5ab9faa14b..bdc946a9c98 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -67,17 +67,17 @@ describe 'Gcp Cluster', :js do it 'user sees a cluster details page and creation status' do subject - expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...') + expect(page).to have_content('Kubernetes cluster is being created...') Clusters::Cluster.last.provider.make_created! - expect(page).to have_content('Kubernetes cluster was successfully created on Google Kubernetes Engine') + expect(page).to have_content('Kubernetes cluster was successfully created') end it 'user sees a error if something wrong during creation' do subject - expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...') + expect(page).to have_content('Kubernetes cluster is being created...') Clusters::Cluster.last.provider.make_errored!('Something wrong!') diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index 198a3dfd37a..253866c8425 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -29,6 +29,7 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do it { is_expected.to delegate_method(:status).to(:provider) } it { is_expected.to delegate_method(:status_reason).to(:provider) } it { is_expected.to delegate_method(:on_creation?).to(:provider) } + it { is_expected.to delegate_method(:knative_pre_installed?).to(:provider) } it { is_expected.to delegate_method(:active?).to(:platform_kubernetes).with_prefix } it { is_expected.to delegate_method(:rbac?).to(:platform_kubernetes).with_prefix } it { is_expected.to delegate_method(:available?).to(:application_helm).with_prefix } @@ -916,26 +917,4 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do end end end - - describe '#knative_pre_installed?' do - subject { cluster.knative_pre_installed? } - - context 'with a GCP provider without cloud_run' do - let(:cluster) { create(:cluster, :provided_by_gcp) } - - it { is_expected.to be_falsey } - end - - context 'with a GCP provider with cloud_run' do - let(:cluster) { create(:cluster, :provided_by_gcp, :cloud_run_enabled) } - - it { is_expected.to be_truthy } - end - - context 'with a user provider' do - let(:cluster) { create(:cluster, :provided_by_user) } - - it { is_expected.to be_falsey } - end - end end diff --git a/spec/models/clusters/providers/aws_spec.rb b/spec/models/clusters/providers/aws_spec.rb index 95549d015c8..05d6e63288e 100644 --- a/spec/models/clusters/providers/aws_spec.rb +++ b/spec/models/clusters/providers/aws_spec.rb @@ -4,7 +4,6 @@ require 'spec_helper' describe Clusters::Providers::Aws do it { is_expected.to belong_to(:cluster) } - it { is_expected.to belong_to(:created_by_user) } it { is_expected.to validate_length_of(:key_name).is_at_least(1).is_at_most(255) } it { is_expected.to validate_length_of(:region).is_at_least(1).is_at_most(255) } @@ -108,4 +107,28 @@ describe Clusters::Providers::Aws do it { is_expected.to eq credentials } end + + describe '#created_by_user' do + let(:provider) { create(:cluster_provider_aws) } + + subject { provider.created_by_user } + + it { is_expected.to eq provider.cluster.user } + end + + describe '#has_rbac_enabled?' do + let(:provider) { create(:cluster_provider_aws) } + + subject { provider.has_rbac_enabled? } + + it { is_expected.to be_truthy } + end + + describe '#knative_pre_installed?' do + let(:provider) { create(:cluster_provider_aws) } + + subject { provider.knative_pre_installed? } + + it { is_expected.to be_falsey } + end end diff --git a/spec/models/clusters/providers/gcp_spec.rb b/spec/models/clusters/providers/gcp_spec.rb index 15e152519b4..e2fd777d131 100644 --- a/spec/models/clusters/providers/gcp_spec.rb +++ b/spec/models/clusters/providers/gcp_spec.rb @@ -78,12 +78,20 @@ describe Clusters::Providers::Gcp do end end - describe '#legacy_abac?' do - let(:gcp) { build(:cluster_provider_gcp) } + describe '#has_rbac_enabled?' do + subject { gcp.has_rbac_enabled? } + + context 'when cluster is legacy_abac' do + let(:gcp) { create(:cluster_provider_gcp, :abac_enabled) } + + it { is_expected.to be_falsey } + end - subject { gcp } + context 'when cluster is not legacy_abac' do + let(:gcp) { create(:cluster_provider_gcp) } - it { is_expected.not_to be_legacy_abac } + it { is_expected.to be_truthy } + end end describe '#knative_pre_installed?' do diff --git a/spec/models/project_services/data_fields_spec.rb b/spec/models/project_services/data_fields_spec.rb index 146db0ae227..6b388a7222b 100644 --- a/spec/models/project_services/data_fields_spec.rb +++ b/spec/models/project_services/data_fields_spec.rb @@ -74,6 +74,12 @@ describe DataFields do expect(service.url_changed?).to be_falsy end end + + describe 'data_fields_present?' do + it 'returns true from the issue tracker service' do + expect(service.data_fields_present?).to be true + end + end end context 'when data are stored in data_fields' do @@ -92,6 +98,18 @@ describe DataFields do end end + context 'when service and data_fields are not persisted' do + let(:service) do + JiraService.new + end + + describe 'data_fields_present?' do + it 'returns true' do + expect(service.data_fields_present?).to be true + end + end + end + context 'when data are stored in properties' do let(:service) { create(:jira_service, :without_properties_callback, properties: properties) } diff --git a/spec/presenters/instance_clusterable_presenter_spec.rb b/spec/presenters/instance_clusterable_presenter_spec.rb new file mode 100644 index 00000000000..9f1268379f5 --- /dev/null +++ b/spec/presenters/instance_clusterable_presenter_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe InstanceClusterablePresenter do + include Gitlab::Routing.url_helpers + + let(:presenter) { described_class.new(instance) } + let(:cluster) { create(:cluster, :provided_by_gcp, :instance) } + let(:instance) { cluster.instance } + + describe '#create_aws_clusters_path' do + subject { described_class.new(instance).create_aws_clusters_path } + + it { is_expected.to eq(create_aws_admin_clusters_path) } + end + + describe '#authorize_aws_role_path' do + subject { described_class.new(instance).authorize_aws_role_path } + + it { is_expected.to eq(authorize_aws_role_admin_clusters_path) } + end + + describe '#revoke_aws_role_path' do + subject { described_class.new(instance).revoke_aws_role_path } + + it { is_expected.to eq(revoke_aws_role_admin_clusters_path) } + end + + describe '#aws_api_proxy_path' do + let(:resource) { 'resource' } + + subject { described_class.new(instance).aws_api_proxy_path(resource) } + + it { is_expected.to eq(aws_proxy_admin_clusters_path(resource: resource)) } + end +end diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index 8cf888d81ce..a080b59173f 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -102,7 +102,7 @@ describe API::Services do expect(json_response['properties'].keys).to match_array(service_instance.api_field_names) end - it "returns empty hash if properties and data fields are empty" do + it "returns empty hash or nil values if properties and data fields are empty" do # deprecated services are not valid for update initialized_service.update_attribute(:properties, {}) @@ -114,7 +114,7 @@ describe API::Services do get api("/projects/#{project.id}/services/#{dashed_service}", user) expect(response).to have_gitlab_http_status(200) - expect(json_response['properties'].keys).to be_empty + expect(json_response['properties'].values.compact).to be_empty end it "returns error when authenticated but not a project owner" do diff --git a/spec/services/clusters/aws/fetch_credentials_service_spec.rb b/spec/services/clusters/aws/fetch_credentials_service_spec.rb index 09f3be0534d..726d1c30603 100644 --- a/spec/services/clusters/aws/fetch_credentials_service_spec.rb +++ b/spec/services/clusters/aws/fetch_credentials_service_spec.rb @@ -4,21 +4,23 @@ require 'spec_helper' describe Clusters::Aws::FetchCredentialsService do describe '#execute' do + let(:user) { create(:user) } let(:provider) { create(:cluster_provider_aws) } let(:gitlab_access_key_id) { 'gitlab-access-key-id' } let(:gitlab_secret_access_key) { 'gitlab-secret-access-key' } + let(:region) { 'us-east-1' } let(:gitlab_credentials) { Aws::Credentials.new(gitlab_access_key_id, gitlab_secret_access_key) } - let(:sts_client) { Aws::STS::Client.new(credentials: gitlab_credentials, region: provider.region) } + let(:sts_client) { Aws::STS::Client.new(credentials: gitlab_credentials, region: region) } let(:assumed_role) { instance_double(Aws::AssumeRoleCredentials, credentials: assumed_role_credentials) } let(:assumed_role_credentials) { double } - subject { described_class.new(provider).execute } + subject { described_class.new(provision_role, region: region, provider: provider).execute } context 'provision role is configured' do - let(:provision_role) { create(:aws_role, user: provider.created_by_user) } + let(:provision_role) { create(:aws_role, user: user) } before do stub_application_setting(eks_access_key_id: gitlab_access_key_id) @@ -29,25 +31,34 @@ describe Clusters::Aws::FetchCredentialsService do .and_return(gitlab_credentials) expect(Aws::STS::Client).to receive(:new) - .with(credentials: gitlab_credentials, region: provider.region) + .with(credentials: gitlab_credentials, region: region) .and_return(sts_client) expect(Aws::AssumeRoleCredentials).to receive(:new) .with( client: sts_client, role_arn: provision_role.role_arn, - role_session_name: "gitlab-eks-cluster-#{provider.cluster_id}-user-#{provider.created_by_user_id}", + role_session_name: session_name, external_id: provision_role.role_external_id ).and_return(assumed_role) end - it { is_expected.to eq assumed_role_credentials } + context 'provider is specified' do + let(:session_name) { "gitlab-eks-cluster-#{provider.cluster_id}-user-#{user.id}" } + + it { is_expected.to eq assumed_role_credentials } + end + + context 'provider is not specifed' do + let(:provider) { nil } + let(:session_name) { "gitlab-eks-autofill-user-#{user.id}" } + + it { is_expected.to eq assumed_role_credentials } + end end context 'provision role is not configured' do - before do - expect(provider.created_by_user.aws_role).to be_nil - end + let(:provision_role) { nil } it 'raises an error' do expect { subject }.to raise_error(described_class::MissingRoleError, 'AWS provisioning role not configured') diff --git a/spec/services/clusters/aws/provision_service_spec.rb b/spec/services/clusters/aws/provision_service_spec.rb index 5c044b8732e..927ffaef002 100644 --- a/spec/services/clusters/aws/provision_service_spec.rb +++ b/spec/services/clusters/aws/provision_service_spec.rb @@ -6,6 +6,7 @@ describe Clusters::Aws::ProvisionService do describe '#execute' do let(:provider) { create(:cluster_provider_aws) } + let(:provision_role) { create(:aws_role, user: provider.created_by_user) } let(:client) { instance_double(Aws::CloudFormation::Client, create_stack: true) } let(:cloudformation_template) { double } let(:credentials) do @@ -34,7 +35,8 @@ describe Clusters::Aws::ProvisionService do before do allow(Clusters::Aws::FetchCredentialsService).to receive(:new) - .with(provider).and_return(double(execute: credentials)) + .with(provision_role, provider: provider, region: provider.region) + .and_return(double(execute: credentials)) allow(provider).to receive(:api_client) .and_return(client) @@ -107,15 +109,6 @@ describe Clusters::Aws::ProvisionService do include_examples 'provision error', 'Amazon credentials are not configured' end - context 'AWS credentials are not configured' do - before do - allow(Clusters::Aws::FetchCredentialsService).to receive(:new) - .and_raise(Settingslogic::MissingSetting) - end - - include_examples 'provision error', 'Amazon credentials are not configured' - end - context 'Authentication failure' do before do allow(Clusters::Aws::FetchCredentialsService).to receive(:new) diff --git a/spec/services/clusters/aws/proxy_service_spec.rb b/spec/services/clusters/aws/proxy_service_spec.rb new file mode 100644 index 00000000000..7b0e0512b95 --- /dev/null +++ b/spec/services/clusters/aws/proxy_service_spec.rb @@ -0,0 +1,210 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Clusters::Aws::ProxyService do + let(:role) { create(:aws_role) } + let(:credentials) { instance_double(Aws::Credentials) } + let(:client_instance) { instance_double(client) } + + let(:region) { 'region' } + let(:vpc_id) { } + let(:params) do + ActionController::Parameters.new({ + resource: resource, + region: region, + vpc_id: vpc_id + }) + end + + subject { described_class.new(role, params: params).execute } + + context 'external resources' do + before do + allow(Clusters::Aws::FetchCredentialsService).to receive(:new) do + double(execute: credentials) + end + + allow(client).to receive(:new) + .with( + credentials: credentials, region: region, + http_open_timeout: 5, http_read_timeout: 10) + .and_return(client_instance) + end + + shared_examples 'bad request' do + it 'returns an empty hash' do + expect(subject.status).to eq :bad_request + expect(subject.body).to eq({}) + end + end + + describe 'key_pairs' do + let(:client) { Aws::EC2::Client } + let(:resource) { 'key_pairs' } + let(:response) { double(to_hash: :key_pairs) } + + it 'requests a list of key pairs' do + expect(client_instance).to receive(:describe_key_pairs).once.and_return(response) + expect(subject.status).to eq :ok + expect(subject.body).to eq :key_pairs + end + end + + describe 'roles' do + let(:client) { Aws::IAM::Client } + let(:resource) { 'roles' } + let(:response) { double(to_hash: :roles) } + + it 'requests a list of roles' do + expect(client_instance).to receive(:list_roles).once.and_return(response) + expect(subject.status).to eq :ok + expect(subject.body).to eq :roles + end + end + + describe 'regions' do + let(:client) { Aws::EC2::Client } + let(:resource) { 'regions' } + let(:response) { double(to_hash: :regions) } + + it 'requests a list of regions' do + expect(client_instance).to receive(:describe_regions).once.and_return(response) + expect(subject.status).to eq :ok + expect(subject.body).to eq :regions + end + end + + describe 'security_groups' do + let(:client) { Aws::EC2::Client } + let(:resource) { 'security_groups' } + let(:response) { double(to_hash: :security_groups) } + + include_examples 'bad request' + + context 'VPC is specified' do + let(:vpc_id) { 'vpc-1' } + + it 'requests a list of security groups for a VPC' do + expect(client_instance).to receive(:describe_security_groups).once + .with(filters: [{ name: 'vpc-id', values: [vpc_id] }]) + .and_return(response) + expect(subject.status).to eq :ok + expect(subject.body).to eq :security_groups + end + end + end + + describe 'subnets' do + let(:client) { Aws::EC2::Client } + let(:resource) { 'subnets' } + let(:response) { double(to_hash: :subnets) } + + include_examples 'bad request' + + context 'VPC is specified' do + let(:vpc_id) { 'vpc-1' } + + it 'requests a list of subnets for a VPC' do + expect(client_instance).to receive(:describe_subnets).once + .with(filters: [{ name: 'vpc-id', values: [vpc_id] }]) + .and_return(response) + expect(subject.status).to eq :ok + expect(subject.body).to eq :subnets + end + end + end + + describe 'vpcs' do + let(:client) { Aws::EC2::Client } + let(:resource) { 'vpcs' } + let(:response) { double(to_hash: :vpcs) } + + it 'requests a list of VPCs' do + expect(client_instance).to receive(:describe_vpcs).once.and_return(response) + expect(subject.status).to eq :ok + expect(subject.body).to eq :vpcs + end + end + + context 'errors' do + let(:client) { Aws::EC2::Client } + + context 'unknown resource' do + let(:resource) { 'instances' } + + include_examples 'bad request' + end + + context 'client and configuration errors' do + let(:resource) { 'vpcs' } + + before do + allow(client_instance).to receive(:describe_vpcs).and_raise(error) + end + + context 'error fetching credentials' do + let(:error) { Aws::STS::Errors::ServiceError.new(nil, 'error message') } + + include_examples 'bad request' + end + + context 'credentials not configured' do + let(:error) { Aws::Errors::MissingCredentialsError.new('error message') } + + include_examples 'bad request' + end + + context 'role not configured' do + let(:error) { Clusters::Aws::FetchCredentialsService::MissingRoleError.new('error message') } + + include_examples 'bad request' + end + + context 'EC2 error' do + let(:error) { Aws::EC2::Errors::ServiceError.new(nil, 'error message') } + + include_examples 'bad request' + end + + context 'IAM error' do + let(:error) { Aws::IAM::Errors::ServiceError.new(nil, 'error message') } + + include_examples 'bad request' + end + + context 'STS error' do + let(:error) { Aws::STS::Errors::ServiceError.new(nil, 'error message') } + + include_examples 'bad request' + end + end + end + end + + context 'local resources' do + describe 'instance_types' do + let(:resource) { 'instance_types' } + let(:cloudformation_template) { double } + let(:instance_types) { double(dig: %w(t3.small)) } + + before do + allow(File).to receive(:read) + .with(Rails.root.join('vendor', 'aws', 'cloudformation', 'eks_cluster.yaml')) + .and_return(cloudformation_template) + + allow(YAML).to receive(:safe_load) + .with(cloudformation_template) + .and_return(instance_types) + end + + it 'returns a list of instance types' do + expect(subject.status).to eq :ok + expect(subject.body).to have_key(:instance_types) + expect(subject.body[:instance_types]).to match_array([ + instance_type_name: 't3.small' + ]) + end + end + end +end |