beaker-google 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/release.yml +41 -0
- data/.github/workflows/ci.yml +11 -8
- data/.github/workflows/release.yml +91 -17
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +20 -0
- data/CHANGELOG.md +32 -0
- data/Gemfile +8 -0
- data/README.md +2 -2
- data/Rakefile +7 -0
- data/beaker-google.gemspec +9 -6
- data/lib/beaker/hypervisor/google_compute.rb +4 -4
- data/lib/beaker/hypervisor/google_compute_helper.rb +15 -5
- data/lib/beaker-google/version.rb +1 -1
- data/spec/classes/beaker/google_compute_constants_and_defaults_spec.rb +141 -0
- data/spec/classes/beaker/google_compute_helper_api_version_spec.rb +37 -0
- data/spec/classes/beaker/google_compute_helper_configuration_validation_spec.rb +100 -0
- data/spec/classes/beaker/google_compute_helper_constants_and_defaults_spec.rb +66 -0
- data/spec/classes/beaker/google_compute_helper_edge_cases_spec.rb +173 -0
- data/spec/classes/beaker/google_compute_helper_error_handling_spec.rb +105 -0
- data/spec/classes/beaker/google_compute_helper_spec.rb +368 -0
- data/spec/classes/beaker/google_compute_helper_utilities_spec.rb +95 -0
- data/spec/classes/beaker/google_compute_initialization_spec.rb +52 -0
- data/spec/classes/beaker/google_compute_provision_spec.rb +68 -0
- data/spec/classes/beaker/google_compute_spec.rb +95 -0
- data/spec/classes/beaker/google_compute_ssh_key_management_spec.rb +115 -0
- data/spec/classes/beaker/google_spec.rb +68 -0
- data/spec/classes/beaker-google/beaker_google_version_spec.rb +19 -0
- data/spec/classes/beaker_integration_spec.rb +67 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/google_compute_shared_setup.rb +138 -0
- data/spec/support/shared_mocks.rb +89 -0
- metadata +59 -15
- data/.github/workflows/codeql-analysis.yml +0 -70
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Beaker::GoogleComputeHelper do
|
|
6
|
+
let(:logger) { instance_double(Beaker::Logger) }
|
|
7
|
+
let(:base_options) { { logger: logger, gce_project: 'test-project', gce_ports: [] } }
|
|
8
|
+
|
|
9
|
+
def mock_google_services
|
|
10
|
+
# Mock the authentication and service initialization
|
|
11
|
+
allow(Google::Auth).to receive(:get_application_default).and_return(double)
|
|
12
|
+
|
|
13
|
+
compute_service = double
|
|
14
|
+
allow(compute_service).to receive(:authorization=)
|
|
15
|
+
allow(compute_service).to receive(:request_options).and_return(Google::Apis::RequestOptions.new)
|
|
16
|
+
allow(Google::Apis::ComputeV1::ComputeService).to receive(:new).and_return(compute_service)
|
|
17
|
+
|
|
18
|
+
oslogin_service = double
|
|
19
|
+
allow(oslogin_service).to receive(:authorization=)
|
|
20
|
+
allow(Google::Apis::OsloginV1::CloudOSLoginService).to receive(:new).and_return(oslogin_service)
|
|
21
|
+
|
|
22
|
+
client_options = double
|
|
23
|
+
allow(client_options).to receive(:application_name=)
|
|
24
|
+
allow(client_options).to receive(:application_version=)
|
|
25
|
+
allow(Google::Apis::ClientOptions).to receive(:default).and_return(client_options)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe 'initialization validation' do
|
|
29
|
+
context 'when project is not provided' do
|
|
30
|
+
let(:options) { base_options.merge(gce_project: nil) }
|
|
31
|
+
|
|
32
|
+
it 'raises an error' do
|
|
33
|
+
expect do
|
|
34
|
+
described_class.new(options)
|
|
35
|
+
end.to raise_error('You must specify a gce_project for Google Compute Engine instances!')
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'when project is provided' do
|
|
40
|
+
let(:options) { base_options }
|
|
41
|
+
|
|
42
|
+
it 'does not raise an error' do
|
|
43
|
+
mock_google_services
|
|
44
|
+
|
|
45
|
+
expect do
|
|
46
|
+
described_class.new(options)
|
|
47
|
+
end.not_to raise_error
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe 'port validation' do
|
|
53
|
+
context 'when port format is invalid' do
|
|
54
|
+
let(:options) { base_options.merge(gce_ports: ['22']) }
|
|
55
|
+
|
|
56
|
+
it 'raises an error' do
|
|
57
|
+
expect do
|
|
58
|
+
described_class.new(options)
|
|
59
|
+
end.to raise_error(%r{Invalid format for port 22. Should be 'port/proto'})
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'when port protocol is invalid' do
|
|
64
|
+
let(:options) { base_options.merge(gce_ports: ['22/invalid']) }
|
|
65
|
+
|
|
66
|
+
it 'raises an error' do
|
|
67
|
+
expect do
|
|
68
|
+
described_class.new(options)
|
|
69
|
+
end.to raise_error(%r{Invalid value 'invalid' for protocol in '22/invalid'. Must be one of})
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'when port format is valid' do
|
|
74
|
+
let(:options) { base_options.merge(gce_ports: ['22/tcp', '80/tcp']) }
|
|
75
|
+
|
|
76
|
+
it 'does not raise an error' do
|
|
77
|
+
mock_google_services
|
|
78
|
+
|
|
79
|
+
expect do
|
|
80
|
+
described_class.new(options)
|
|
81
|
+
end.not_to raise_error
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context 'when all valid protocols are used' do
|
|
86
|
+
let(:valid_protocols) { described_class::VALID_PROTOS }
|
|
87
|
+
|
|
88
|
+
before do
|
|
89
|
+
mock_google_services
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'accepts all valid protocols' do
|
|
93
|
+
valid_protocols.each do |proto|
|
|
94
|
+
options = base_options.merge(gce_ports: ["80/#{proto}"])
|
|
95
|
+
expect { described_class.new(options) }.not_to raise_error
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Beaker::GoogleComputeHelper do
|
|
6
|
+
context 'when testing constants and defaults' do
|
|
7
|
+
let(:base_options) do
|
|
8
|
+
{
|
|
9
|
+
gce_project: 'test-project',
|
|
10
|
+
gce_zone: 'us-central1-a',
|
|
11
|
+
gce_network: 'default',
|
|
12
|
+
logger: instance_double(Beaker::Logger, debug: nil, info: nil, warn: nil, error: nil),
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe 'Google Compute Helper constants' do
|
|
17
|
+
it 'defines AUTH_URL constant' do
|
|
18
|
+
expect(described_class::AUTH_URL).to eq('https://www.googleapis.com/auth/compute')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'defines API_VERSION constant' do
|
|
22
|
+
expect(described_class::API_VERSION).to eq('v1')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'defines BASE_URL constant' do
|
|
26
|
+
expect(described_class::BASE_URL).to eq('https://www.googleapis.com/compute/v1/projects/')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'defines DEFAULT_ZONE_NAME constant' do
|
|
30
|
+
expect(described_class::DEFAULT_ZONE_NAME).to eq('us-central1-a')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'defines DEFAULT_MACHINE_TYPE constant' do
|
|
34
|
+
expect(described_class::DEFAULT_MACHINE_TYPE).to eq('e2-standard-4')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'defines DEFAULT_NETWORK_NAME constant' do
|
|
38
|
+
expect(described_class::DEFAULT_NETWORK_NAME).to eq('default')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'defines SLEEPWAIT constant' do
|
|
42
|
+
expect(described_class::SLEEPWAIT).to eq(5)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'defines valid protocols' do
|
|
46
|
+
expect(described_class::VALID_PROTOS).to eq(%w[tcp udp icmp esp ah ipip sctp])
|
|
47
|
+
.and be_frozen
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'defines GCP auth scopes structure' do
|
|
51
|
+
auth_scopes = described_class::GCP_AUTH_SCOPE
|
|
52
|
+
|
|
53
|
+
expect(auth_scopes).to be_an(Array).and be_frozen.and have_attributes(length: 2)
|
|
54
|
+
.and include('https://www.googleapis.com/auth/compute')
|
|
55
|
+
.and include('https://www.googleapis.com/auth/cloud-platform.read-only')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe 'Google Compute constants' do
|
|
60
|
+
it 'defines Windows image projects' do
|
|
61
|
+
expect(Beaker::GoogleCompute::WINDOWS_IMAGE_PROJECT).to eq(%w[windows-cloud windows-sql-cloud])
|
|
62
|
+
.and be_frozen
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Beaker::GoogleComputeHelper do
|
|
6
|
+
context 'when testing edge cases and integration' do
|
|
7
|
+
describe 'version loading' do
|
|
8
|
+
it 'loads version as a module constant' do
|
|
9
|
+
expect(BeakerGoogle::VERSION).to be_a(String)
|
|
10
|
+
.and match(/^\d+\.\d+\.\d+/)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'is accessible through the module' do
|
|
14
|
+
expect { BeakerGoogle::VERSION }.not_to raise_error
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe 'module structure' do
|
|
19
|
+
it 'defines the BeakerGoogle module' do
|
|
20
|
+
expect(BeakerGoogle).to be_a(Module)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'has const_get method' do
|
|
24
|
+
expect(BeakerGoogle).to respond_to(:const_get)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'has version information' do
|
|
28
|
+
expect(BeakerGoogle.const_get(:VERSION)).to be_a(String)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'string processing edge cases' do
|
|
33
|
+
it 'handles nil values safely' do
|
|
34
|
+
expect(safe_string_process(nil)).to be_nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'handles empty strings' do
|
|
38
|
+
expect(safe_string_process('')).to eq('')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'handles whitespace' do
|
|
42
|
+
expect(safe_string_process(' test ')).to eq('test')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'handles special characters' do
|
|
46
|
+
expect(safe_string_process('test@example.com')).to eq('test@example.com')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def safe_string_process(str)
|
|
52
|
+
return nil if str.nil?
|
|
53
|
+
return str if str.empty?
|
|
54
|
+
|
|
55
|
+
str.strip
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe 'environment variable handling' do
|
|
60
|
+
it 'handles missing environment variables gracefully' do
|
|
61
|
+
allow(ENV).to receive(:[]).with('NONEXISTENT_VAR').and_return(nil)
|
|
62
|
+
expect(ENV.fetch('NONEXISTENT_VAR', nil)).to be_nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'handles empty environment variables' do
|
|
66
|
+
allow(ENV).to receive(:[]).with('EMPTY_VAR').and_return('')
|
|
67
|
+
allow(ENV).to receive(:fetch).with('EMPTY_VAR', nil).and_return('')
|
|
68
|
+
expect(ENV.fetch('EMPTY_VAR', nil)).to eq('')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'handles environment variables with spaces' do
|
|
72
|
+
allow(ENV).to receive(:[]).with('SPACE_VAR').and_return(' value ')
|
|
73
|
+
allow(ENV).to receive(:fetch).with('SPACE_VAR', nil).and_return(' value ')
|
|
74
|
+
expect(ENV.fetch('SPACE_VAR', nil)).to eq(' value ')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe 'GoogleComputeHelper options processing' do
|
|
79
|
+
let(:logger) { instance_double(Beaker::Logger) }
|
|
80
|
+
let(:base_options) { { logger: logger, gce_project: 'test-project' } }
|
|
81
|
+
|
|
82
|
+
def mock_google_services
|
|
83
|
+
# Mock the authentication and service initialization
|
|
84
|
+
allow(Google::Auth).to receive(:get_application_default).and_return(double)
|
|
85
|
+
|
|
86
|
+
compute_service = double
|
|
87
|
+
allow(compute_service).to receive(:authorization=)
|
|
88
|
+
allow(compute_service).to receive(:request_options).and_return(Google::Apis::RequestOptions.new)
|
|
89
|
+
allow(Google::Apis::ComputeV1::ComputeService).to receive(:new).and_return(compute_service)
|
|
90
|
+
|
|
91
|
+
oslogin_service = double
|
|
92
|
+
allow(oslogin_service).to receive(:authorization=)
|
|
93
|
+
allow(Google::Apis::OsloginV1::CloudOSLoginService).to receive(:new).and_return(oslogin_service)
|
|
94
|
+
|
|
95
|
+
client_options = double
|
|
96
|
+
allow(client_options).to receive(:application_name=)
|
|
97
|
+
allow(client_options).to receive(:application_version=)
|
|
98
|
+
allow(Google::Apis::ClientOptions).to receive(:default).and_return(client_options)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
before do
|
|
102
|
+
mock_google_services
|
|
103
|
+
allow(ENV).to receive(:fetch).and_call_original
|
|
104
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_ports', '').and_return('')
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'handles nil gce_ports configuration' do
|
|
108
|
+
options = base_options.merge(gce_ports: nil)
|
|
109
|
+
|
|
110
|
+
expect do
|
|
111
|
+
described_class.new(options)
|
|
112
|
+
end.not_to raise_error
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'handles empty gce_ports configuration' do
|
|
116
|
+
options = base_options.merge(gce_ports: [])
|
|
117
|
+
|
|
118
|
+
mock_google_services
|
|
119
|
+
|
|
120
|
+
expect do
|
|
121
|
+
described_class.new(options)
|
|
122
|
+
end.not_to raise_error
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'handles gce_ports with multiple valid entries' do
|
|
126
|
+
options = base_options.merge(gce_ports: ['22/tcp', '80/tcp', '443/tcp'])
|
|
127
|
+
|
|
128
|
+
mock_google_services
|
|
129
|
+
|
|
130
|
+
expect do
|
|
131
|
+
described_class.new(options)
|
|
132
|
+
end.not_to raise_error
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def ports_for(env_value, configured)
|
|
136
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_ports', '').and_return(env_value)
|
|
137
|
+
described_class.new(base_options.merge(gce_ports: configured)).options[:gce_ports]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'lets BEAKER_gce_ports replace configured gce_ports' do
|
|
141
|
+
expect(ports_for('8140/tcp, 443/tcp', ['80/tcp'])).to eq(['8140/tcp', '443/tcp'])
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'uses BEAKER_gce_ports when gce_ports is not configured' do
|
|
145
|
+
expect(ports_for('8140/tcp', nil)).to eq(['8140/tcp'])
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'keeps configured gce_ports when BEAKER_gce_ports is empty' do
|
|
149
|
+
expect(ports_for('', ['80/tcp'])).to eq(['80/tcp'])
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'keeps configured gce_ports when BEAKER_gce_ports is only whitespace' do
|
|
153
|
+
expect(ports_for(' ', ['80/tcp'])).to eq(['80/tcp'])
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'defaults to no ports when neither BEAKER_gce_ports nor gce_ports is set' do
|
|
157
|
+
expect(ports_for('', nil)).to eq([])
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'validates ports taken from BEAKER_gce_ports' do
|
|
161
|
+
expect { ports_for('8140/bogus', ['80/tcp']) }.to raise_error(/Invalid value 'bogus' for protocol/)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'splits a comma-separated gce_ports string from the hosts file' do
|
|
165
|
+
expect(ports_for('', '80/tcp, 443/tcp')).to eq(['80/tcp', '443/tcp'])
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'splits comma-separated entries inside a gce_ports list' do
|
|
169
|
+
expect(ports_for('', ['80/tcp,443/tcp', ' 8140/tcp '])).to eq(['80/tcp', '443/tcp', '8140/tcp'])
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Beaker::GoogleComputeHelper do
|
|
6
|
+
context 'when handling errors' do
|
|
7
|
+
describe 'GoogleComputeError' do
|
|
8
|
+
it 'can be raised with a custom message' do
|
|
9
|
+
expect do
|
|
10
|
+
raise Beaker::GoogleComputeHelper::GoogleComputeError, 'Custom error message'
|
|
11
|
+
end.to raise_error(Beaker::GoogleComputeHelper::GoogleComputeError, 'Custom error message')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'inherits from StandardError' do
|
|
15
|
+
expect(Beaker::GoogleComputeHelper::GoogleComputeError).to be < StandardError
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe 'GoogleComputeHelper configuration errors' do
|
|
20
|
+
let(:logger) { instance_double(Beaker::Logger) }
|
|
21
|
+
let(:base_options) { { logger: logger } }
|
|
22
|
+
|
|
23
|
+
before do
|
|
24
|
+
# Mock the authentication and service initialization
|
|
25
|
+
allow(Google::Auth).to receive(:get_application_default).and_return(double)
|
|
26
|
+
|
|
27
|
+
compute_service = double
|
|
28
|
+
allow(compute_service).to receive(:authorization=)
|
|
29
|
+
allow(compute_service).to receive(:request_options).and_return(Google::Apis::RequestOptions.new)
|
|
30
|
+
allow(Google::Apis::ComputeV1::ComputeService).to receive(:new).and_return(compute_service)
|
|
31
|
+
|
|
32
|
+
oslogin_service = double
|
|
33
|
+
allow(oslogin_service).to receive(:authorization=)
|
|
34
|
+
allow(Google::Apis::OsloginV1::CloudOSLoginService).to receive(:new).and_return(oslogin_service)
|
|
35
|
+
|
|
36
|
+
client_options = double
|
|
37
|
+
allow(client_options).to receive(:application_name=)
|
|
38
|
+
allow(client_options).to receive(:application_version=)
|
|
39
|
+
allow(Google::Apis::ClientOptions).to receive(:default).and_return(client_options)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'raises error when gce_project is missing' do
|
|
43
|
+
expect do
|
|
44
|
+
described_class.new(base_options.merge(gce_project: nil))
|
|
45
|
+
end.to raise_error('You must specify a gce_project for Google Compute Engine instances!')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'passes validation when gce_project is provided' do
|
|
49
|
+
options = base_options.merge(gce_project: 'test-project', gce_ports: [])
|
|
50
|
+
|
|
51
|
+
expect do
|
|
52
|
+
described_class.new(options)
|
|
53
|
+
end.not_to raise_error
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe 'GoogleComputeHelper port validation errors' do
|
|
58
|
+
let(:logger) { instance_double(Beaker::Logger) }
|
|
59
|
+
let(:base_options) { { logger: logger, gce_project: 'test-project' } }
|
|
60
|
+
|
|
61
|
+
before do
|
|
62
|
+
# Mock the authentication and service initialization
|
|
63
|
+
allow(Google::Auth).to receive(:get_application_default).and_return(double)
|
|
64
|
+
|
|
65
|
+
compute_service = double
|
|
66
|
+
allow(compute_service).to receive(:authorization=)
|
|
67
|
+
allow(compute_service).to receive(:request_options).and_return(Google::Apis::RequestOptions.new)
|
|
68
|
+
allow(Google::Apis::ComputeV1::ComputeService).to receive(:new).and_return(compute_service)
|
|
69
|
+
|
|
70
|
+
oslogin_service = double
|
|
71
|
+
allow(oslogin_service).to receive(:authorization=)
|
|
72
|
+
allow(Google::Apis::OsloginV1::CloudOSLoginService).to receive(:new).and_return(oslogin_service)
|
|
73
|
+
|
|
74
|
+
client_options = double
|
|
75
|
+
allow(client_options).to receive(:application_name=)
|
|
76
|
+
allow(client_options).to receive(:application_version=)
|
|
77
|
+
allow(Google::Apis::ClientOptions).to receive(:default).and_return(client_options)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'raises error for invalid protocol' do
|
|
81
|
+
options = base_options.merge(gce_ports: ['80/invalid'])
|
|
82
|
+
|
|
83
|
+
expect do
|
|
84
|
+
described_class.new(options)
|
|
85
|
+
end.to raise_error(%r{Invalid value 'invalid' for protocol in '80/invalid'})
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'raises error for invalid port format' do
|
|
89
|
+
options = base_options.merge(gce_ports: ['invalid-port'])
|
|
90
|
+
|
|
91
|
+
expect do
|
|
92
|
+
described_class.new(options)
|
|
93
|
+
end.to raise_error(/Invalid format for port invalid-port/)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'accepts valid protocols' do
|
|
97
|
+
options = base_options.merge(gce_ports: ['80/tcp', '443/udp'])
|
|
98
|
+
|
|
99
|
+
expect do
|
|
100
|
+
described_class.new(options)
|
|
101
|
+
end.not_to raise_error
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|