Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/clusters/aws')
-rw-r--r--spec/services/clusters/aws/authorize_role_service_spec.rb102
-rw-r--r--spec/services/clusters/aws/fetch_credentials_service_spec.rb139
-rw-r--r--spec/services/clusters/aws/finalize_creation_service_spec.rb124
-rw-r--r--spec/services/clusters/aws/provision_service_spec.rb130
-rw-r--r--spec/services/clusters/aws/verify_provision_status_service_spec.rb76
5 files changed, 0 insertions, 571 deletions
diff --git a/spec/services/clusters/aws/authorize_role_service_spec.rb b/spec/services/clusters/aws/authorize_role_service_spec.rb
deleted file mode 100644
index 17bbc372675..00000000000
--- a/spec/services/clusters/aws/authorize_role_service_spec.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Aws::AuthorizeRoleService do
- subject { described_class.new(user, params: params).execute }
-
- let(:role) { create(:aws_role) }
- let(:user) { role.user }
- let(:credentials) { instance_double(Aws::Credentials) }
- let(:credentials_service) { instance_double(Clusters::Aws::FetchCredentialsService, execute: credentials) }
-
- let(:role_arn) { 'arn:my-role' }
- let(:region) { 'region' }
- let(:params) do
- params = ActionController::Parameters.new({
- cluster: {
- role_arn: role_arn,
- region: region
- }
- })
-
- params.require(:cluster).permit(:role_arn, :region)
- end
-
- before do
- allow(Clusters::Aws::FetchCredentialsService).to receive(:new)
- .with(instance_of(Aws::Role)).and_return(credentials_service)
- end
-
- context 'role exists' do
- it 'updates the existing Aws::Role record and returns a set of credentials' do
- expect(subject.status).to eq(:ok)
- expect(subject.body).to eq(credentials)
- expect(role.reload.role_arn).to eq(role_arn)
- end
- end
-
- context 'errors' do
- shared_examples 'bad request' do
- it 'returns an empty hash' do
- expect(subject.status).to eq(:unprocessable_entity)
- expect(subject.body).to eq({ message: message })
- end
-
- it 'logs the error' do
- expect(::Gitlab::ErrorTracking).to receive(:track_exception)
-
- subject
- end
- end
-
- context 'role does not exist' do
- let(:user) { create(:user) }
- let(:message) { 'Error: Unable to find AWS role for current user' }
-
- include_examples 'bad request'
- end
-
- context 'supplied ARN is invalid' do
- let(:role_arn) { 'invalid' }
- let(:message) { 'Validation failed: Role arn must be a valid Amazon Resource Name' }
-
- include_examples 'bad request'
- end
-
- context 'client errors' do
- before do
- allow(credentials_service).to receive(:execute).and_raise(error)
- end
-
- context 'error fetching credentials' do
- let(:error) { Aws::STS::Errors::ServiceError.new(nil, 'error message') }
- let(:message) { 'AWS service error: error message' }
-
- include_examples 'bad request'
- end
-
- context 'error in assuming role' do
- let(:raw_message) { "User foo is not authorized to perform: sts:AssumeRole on resource bar" }
- let(:error) { Aws::STS::Errors::AccessDenied.new(nil, raw_message) }
- let(:message) { "Access denied: #{raw_message}" }
-
- include_examples 'bad request'
- end
-
- context 'credentials not configured' do
- let(:error) { Aws::Errors::MissingCredentialsError.new('error message') }
- let(:message) { "Error: No AWS credentials were supplied" }
-
- include_examples 'bad request'
- end
-
- context 'role not configured' do
- let(:error) { Clusters::Aws::FetchCredentialsService::MissingRoleError.new('error message') }
- let(:message) { "Error: No AWS provision role found for user" }
-
- include_examples 'bad request'
- end
- end
- end
-end
diff --git a/spec/services/clusters/aws/fetch_credentials_service_spec.rb b/spec/services/clusters/aws/fetch_credentials_service_spec.rb
deleted file mode 100644
index 0358ca1f535..00000000000
--- a/spec/services/clusters/aws/fetch_credentials_service_spec.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Aws::FetchCredentialsService do
- describe '#execute' do
- let(:user) { create(:user) }
- let(:provider) { create(:cluster_provider_aws, region: 'ap-southeast-2') }
-
- let(:gitlab_access_key_id) { 'gitlab-access-key-id' }
- let(:gitlab_secret_access_key) { 'gitlab-secret-access-key' }
-
- 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: region) }
- let(:assumed_role) { instance_double(Aws::AssumeRoleCredentials, credentials: assumed_role_credentials) }
-
- let(:assumed_role_credentials) { double }
-
- subject { described_class.new(provision_role, provider: provider).execute }
-
- context 'provision role is configured' do
- let(:provision_role) { create(:aws_role, user: user, region: 'custom-region') }
-
- before do
- 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)
- .and_return(gitlab_credentials)
-
- expect(Aws::STS::Client).to receive(:new)
- .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: session_name,
- external_id: provision_role.role_external_id,
- policy: session_policy
- ).and_return(assumed_role)
- end
-
- context 'provider is specified' do
- let(:region) { provider.region }
- let(:session_name) { "gitlab-eks-cluster-#{provider.cluster_id}-user-#{user.id}" }
- let(:session_policy) { nil }
-
- it { is_expected.to eq assumed_role_credentials }
- end
-
- context 'provider is not specifed' do
- let(:provider) { nil }
- let(:region) { provision_role.region }
- let(:session_name) { "gitlab-eks-autofill-user-#{user.id}" }
- let(:session_policy) { 'policy-document' }
-
- subject { described_class.new(provision_role, provider: provider).execute }
-
- before do
- stub_file_read(Rails.root.join('vendor', 'aws', 'iam', 'eks_cluster_read_only_policy.json'), content: session_policy)
- end
-
- it { is_expected.to eq assumed_role_credentials }
-
- context 'region is not specifed' do
- let(:region) { Clusters::Providers::Aws::DEFAULT_REGION }
- let(:provision_role) { create(:aws_role, user: user, region: nil) }
-
- it { is_expected.to eq assumed_role_credentials }
- end
- end
- end
-
- context 'provision role is not configured' do
- let(:provision_role) { nil }
-
- it 'raises an error' do
- expect { subject }.to raise_error(described_class::MissingRoleError, 'AWS provisioning role not configured')
- end
- end
-
- context 'with an instance profile attached to an IAM role' do
- let(:sts_client) { Aws::STS::Client.new(region: region, stub_responses: true) }
- let(:provision_role) { create(:aws_role, user: user, region: 'custom-region') }
-
- before do
- stub_application_setting(eks_access_key_id: nil)
- stub_application_setting(eks_secret_access_key: nil)
-
- expect(Aws::STS::Client).to receive(:new)
- .with(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: session_name,
- external_id: provision_role.role_external_id,
- policy: session_policy
- ).and_call_original
- end
-
- context 'provider is specified' do
- let(:region) { provider.region }
- let(:session_name) { "gitlab-eks-cluster-#{provider.cluster_id}-user-#{user.id}" }
- let(:session_policy) { nil }
-
- it 'returns credentials', :aggregate_failures do
- expect(subject.access_key_id).to be_present
- expect(subject.secret_access_key).to be_present
- expect(subject.session_token).to be_present
- end
- end
-
- context 'provider is not specifed' do
- let(:provider) { nil }
- let(:region) { provision_role.region }
- let(:session_name) { "gitlab-eks-autofill-user-#{user.id}" }
- let(:session_policy) { 'policy-document' }
-
- before do
- stub_file_read(Rails.root.join('vendor', 'aws', 'iam', 'eks_cluster_read_only_policy.json'), content: session_policy)
- end
-
- subject { described_class.new(provision_role, provider: provider).execute }
-
- it 'returns credentials', :aggregate_failures do
- expect(subject.access_key_id).to be_present
- expect(subject.secret_access_key).to be_present
- expect(subject.session_token).to be_present
- end
- end
- end
- end
-end
diff --git a/spec/services/clusters/aws/finalize_creation_service_spec.rb b/spec/services/clusters/aws/finalize_creation_service_spec.rb
deleted file mode 100644
index 6b0cb86eff0..00000000000
--- a/spec/services/clusters/aws/finalize_creation_service_spec.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Aws::FinalizeCreationService do
- describe '#execute' do
- let(:provider) { create(:cluster_provider_aws, :creating) }
- let(:platform) { provider.cluster.platform_kubernetes }
-
- let(:create_service_account_service) { double(execute: true) }
- let(:fetch_token_service) { double(execute: gitlab_token) }
- let(:kube_client) { double(create_config_map: true) }
- let(:cluster_stack) { double(outputs: [endpoint_output, cert_output, node_role_output]) }
- let(:node_auth_config_map) { double }
-
- let(:endpoint_output) { double(output_key: 'ClusterEndpoint', output_value: api_url) }
- let(:cert_output) { double(output_key: 'ClusterCertificate', output_value: Base64.encode64(ca_pem)) }
- let(:node_role_output) { double(output_key: 'NodeInstanceRole', output_value: node_role) }
-
- let(:api_url) { 'https://kubernetes.example.com' }
- let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem')) }
- let(:gitlab_token) { 'gitlab-token' }
- let(:iam_token) { 'iam-token' }
- let(:node_role) { 'arn::aws::iam::123456789012:role/node-role' }
-
- subject { described_class.new.execute(provider) }
-
- before do
- allow(Clusters::Kubernetes::CreateOrUpdateServiceAccountService).to receive(:gitlab_creator)
- .with(kube_client, rbac: true)
- .and_return(create_service_account_service)
-
- allow(Clusters::Kubernetes::FetchKubernetesTokenService).to receive(:new)
- .with(
- kube_client,
- Clusters::Kubernetes::GITLAB_ADMIN_TOKEN_NAME,
- Clusters::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE)
- .and_return(fetch_token_service)
-
- allow(Gitlab::Kubernetes::KubeClient).to receive(:new)
- .with(
- api_url,
- auth_options: { bearer_token: iam_token },
- ssl_options: {
- verify_ssl: OpenSSL::SSL::VERIFY_PEER,
- cert_store: instance_of(OpenSSL::X509::Store)
- },
- http_proxy_uri: nil
- )
- .and_return(kube_client)
-
- allow(provider.api_client).to receive(:describe_stacks)
- .with(stack_name: provider.cluster.name)
- .and_return(double(stacks: [cluster_stack]))
-
- allow(Kubeclient::AmazonEksCredentials).to receive(:token)
- .with(provider.credentials, provider.cluster.name)
- .and_return(iam_token)
-
- allow(Gitlab::Kubernetes::ConfigMaps::AwsNodeAuth).to receive(:new)
- .with(node_role).and_return(double(generate: node_auth_config_map))
- end
-
- it 'configures the provider and platform' do
- subject
-
- expect(provider).to be_created
- expect(platform.api_url).to eq(api_url)
- expect(platform.ca_pem).to eq(ca_pem)
- expect(platform.token).to eq(gitlab_token)
- expect(platform).to be_rbac
- end
-
- it 'calls the create_service_account_service' do
- expect(create_service_account_service).to receive(:execute).once
-
- subject
- end
-
- it 'configures cluster node authentication' do
- expect(kube_client).to receive(:create_config_map).with(node_auth_config_map).once
-
- subject
- end
-
- describe 'error handling' do
- shared_examples 'provision error' do |message|
- it "sets the status to :errored with an appropriate error message" do
- subject
-
- expect(provider).to be_errored
- expect(provider.status_reason).to include(message)
- end
- end
-
- context 'failed to request stack details from AWS' do
- before do
- allow(provider.api_client).to receive(:describe_stacks)
- .and_raise(Aws::CloudFormation::Errors::ServiceError.new(double, "Error message"))
- end
-
- include_examples 'provision error', 'Failed to fetch CloudFormation stack'
- end
-
- context 'failed to create auth config map' do
- before do
- allow(kube_client).to receive(:create_config_map)
- .and_raise(Kubeclient::HttpError.new(500, 'Error', nil))
- end
-
- include_examples 'provision error', 'Failed to run Kubeclient'
- end
-
- context 'failed to save records' do
- before do
- allow(provider.cluster).to receive(:save!)
- .and_raise(ActiveRecord::RecordInvalid)
- end
-
- include_examples 'provision error', 'Failed to configure EKS provider'
- end
- end
- end
-end
diff --git a/spec/services/clusters/aws/provision_service_spec.rb b/spec/services/clusters/aws/provision_service_spec.rb
deleted file mode 100644
index 5efac29ec1e..00000000000
--- a/spec/services/clusters/aws/provision_service_spec.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.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
- instance_double(
- Aws::Credentials,
- access_key_id: 'key',
- secret_access_key: 'secret',
- session_token: 'token'
- )
- end
-
- let(:parameters) do
- [
- { parameter_key: 'ClusterName', parameter_value: provider.cluster.name },
- { parameter_key: 'ClusterRole', parameter_value: provider.role_arn },
- { parameter_key: 'KubernetesVersion', parameter_value: provider.kubernetes_version },
- { parameter_key: 'ClusterControlPlaneSecurityGroup', parameter_value: provider.security_group_id },
- { parameter_key: 'VpcId', parameter_value: provider.vpc_id },
- { parameter_key: 'Subnets', parameter_value: provider.subnet_ids.join(',') },
- { parameter_key: 'NodeAutoScalingGroupDesiredCapacity', parameter_value: provider.num_nodes.to_s },
- { parameter_key: 'NodeInstanceType', parameter_value: provider.instance_type },
- { parameter_key: 'KeyName', parameter_value: provider.key_name }
- ]
- end
-
- subject { described_class.new.execute(provider) }
-
- before do
- allow(Clusters::Aws::FetchCredentialsService).to receive(:new)
- .with(provision_role, provider: provider)
- .and_return(double(execute: credentials))
-
- allow(provider).to receive(:api_client)
- .and_return(client)
-
- stub_file_read(Rails.root.join('vendor', 'aws', 'cloudformation', 'eks_cluster.yaml'), content: cloudformation_template)
- end
-
- it 'updates the provider status to :creating and configures the provider with credentials' do
- subject
-
- expect(provider).to be_creating
- expect(provider.access_key_id).to eq 'key'
- expect(provider.secret_access_key).to eq 'secret'
- expect(provider.session_token).to eq 'token'
- end
-
- it 'creates a CloudFormation stack' do
- expect(client).to receive(:create_stack).with(
- stack_name: provider.cluster.name,
- template_body: cloudformation_template,
- parameters: parameters,
- capabilities: ["CAPABILITY_IAM"]
- )
-
- subject
- end
-
- it 'schedules a worker to monitor creation status' do
- expect(WaitForClusterCreationWorker).to receive(:perform_in)
- .with(Clusters::Aws::VerifyProvisionStatusService::INITIAL_INTERVAL, provider.cluster_id)
-
- subject
- end
-
- describe 'error handling' do
- shared_examples 'provision error' do |message|
- it "sets the status to :errored with an appropriate error message" do
- subject
-
- expect(provider).to be_errored
- expect(provider.status_reason).to include(message)
- end
- end
-
- context 'invalid state transition' do
- before do
- allow(provider).to receive(:make_creating).and_return(false)
- end
-
- include_examples 'provision error', 'Failed to update provider record'
- end
-
- context 'AWS role is not configured' do
- before do
- allow(Clusters::Aws::FetchCredentialsService).to receive(:new)
- .and_raise(Clusters::Aws::FetchCredentialsService::MissingRoleError)
- end
-
- include_examples 'provision error', 'Amazon role is not configured'
- end
-
- context 'AWS credentials are not configured' do
- before do
- allow(Clusters::Aws::FetchCredentialsService).to receive(:new)
- .and_raise(Aws::Errors::MissingCredentialsError)
- end
-
- include_examples 'provision error', 'Amazon credentials are not configured'
- end
-
- context 'Authentication failure' do
- before do
- allow(Clusters::Aws::FetchCredentialsService).to receive(:new)
- .and_raise(Aws::STS::Errors::ServiceError.new(double, 'Error message'))
- end
-
- include_examples 'provision error', 'Amazon authentication failed'
- end
-
- context 'CloudFormation failure' do
- before do
- allow(client).to receive(:create_stack)
- .and_raise(Aws::CloudFormation::Errors::ServiceError.new(double, 'Error message'))
- end
-
- include_examples 'provision error', 'Amazon CloudFormation request failed'
- end
- end
- end
-end
diff --git a/spec/services/clusters/aws/verify_provision_status_service_spec.rb b/spec/services/clusters/aws/verify_provision_status_service_spec.rb
deleted file mode 100644
index b9a58b97842..00000000000
--- a/spec/services/clusters/aws/verify_provision_status_service_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Clusters::Aws::VerifyProvisionStatusService do
- describe '#execute' do
- let(:provider) { create(:cluster_provider_aws) }
-
- let(:stack) { double(stack_status: stack_status, creation_time: creation_time) }
- let(:creation_time) { 1.minute.ago }
-
- subject { described_class.new.execute(provider) }
-
- before do
- allow(provider.api_client).to receive(:describe_stacks)
- .with(stack_name: provider.cluster.name)
- .and_return(double(stacks: [stack]))
- end
-
- shared_examples 'provision error' do |message|
- it "sets the status to :errored with an appropriate error message" do
- subject
-
- expect(provider).to be_errored
- expect(provider.status_reason).to include(message)
- end
- end
-
- context 'stack creation is still in progress' do
- let(:stack_status) { 'CREATE_IN_PROGRESS' }
- let(:verify_service) { double(execute: true) }
-
- it 'schedules a worker to check again later' do
- expect(WaitForClusterCreationWorker).to receive(:perform_in)
- .with(described_class::POLL_INTERVAL, provider.cluster_id)
-
- subject
- end
-
- context 'stack creation is taking too long' do
- let(:creation_time) { 1.hour.ago }
-
- include_examples 'provision error', 'Kubernetes cluster creation time exceeds timeout'
- end
- end
-
- context 'stack creation is complete' do
- let(:stack_status) { 'CREATE_COMPLETE' }
- let(:finalize_service) { double(execute: true) }
-
- it 'finalizes creation' do
- expect(Clusters::Aws::FinalizeCreationService).to receive(:new).and_return(finalize_service)
- expect(finalize_service).to receive(:execute).with(provider).once
-
- subject
- end
- end
-
- context 'stack creation failed' do
- let(:stack_status) { 'CREATE_FAILED' }
-
- include_examples 'provision error', 'Unexpected status'
- end
-
- context 'error communicating with CloudFormation API' do
- let(:stack_status) { 'CREATE_IN_PROGRESS' }
-
- before do
- allow(provider.api_client).to receive(:describe_stacks)
- .and_raise(Aws::CloudFormation::Errors::ServiceError.new(double, 'Error message'))
- end
-
- include_examples 'provision error', 'Amazon CloudFormation request failed'
- end
- end
-end