1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# 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
|