beaker-google 1.1.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 +30 -17
- data/.github/workflows/release.yml +91 -17
- data/.gitignore +1 -0
- data/.rubocop.yml +4 -518
- data/.rubocop_todo.yml +20 -0
- data/.simplecov +2 -0
- data/CHANGELOG.md +50 -1
- data/Gemfile +13 -2
- data/README.md +2 -2
- data/Rakefile +23 -6
- data/beaker-google.gemspec +27 -23
- data/bin/beaker-google +1 -0
- data/lib/beaker/hypervisor/google.rb +5 -1
- data/lib/beaker/hypervisor/google_compute.rb +55 -25
- data/lib/beaker/hypervisor/google_compute_helper.rb +599 -581
- data/lib/beaker-google/version.rb +3 -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 +102 -38
- data/.github/workflows/codeql-analysis.yml +0 -70
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Beaker::GoogleCompute do
|
|
6
|
+
include FakeFS::SpecHelpers
|
|
7
|
+
|
|
8
|
+
subject(:google_compute) do
|
|
9
|
+
mock_google_services
|
|
10
|
+
described_class.new(hosts, options)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
let(:logger) { instance_double(Beaker::Logger) }
|
|
14
|
+
let(:hosts) { [] }
|
|
15
|
+
let(:options) { { logger: logger, gce_project: 'test-project', gce_ports: [] } }
|
|
16
|
+
|
|
17
|
+
def mock_google_services
|
|
18
|
+
# Mock the authentication and service initialization
|
|
19
|
+
allow(Google::Auth).to receive(:get_application_default).and_return(double)
|
|
20
|
+
|
|
21
|
+
compute_service = double
|
|
22
|
+
allow(compute_service).to receive(:authorization=)
|
|
23
|
+
allow(compute_service).to receive(:request_options).and_return(Google::Apis::RequestOptions.new)
|
|
24
|
+
allow(Google::Apis::ComputeV1::ComputeService).to receive(:new).and_return(compute_service)
|
|
25
|
+
|
|
26
|
+
oslogin_service = double
|
|
27
|
+
allow(oslogin_service).to receive(:authorization=)
|
|
28
|
+
allow(Google::Apis::OsloginV1::CloudOSLoginService).to receive(:new).and_return(oslogin_service)
|
|
29
|
+
|
|
30
|
+
client_options = double
|
|
31
|
+
allow(client_options).to receive(:application_name=)
|
|
32
|
+
allow(client_options).to receive(:application_version=)
|
|
33
|
+
allow(Google::Apis::ClientOptions).to receive(:default).and_return(client_options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe '#find_google_ssh_private_key' do
|
|
37
|
+
let(:default_private_key) { File.join(Dir.home, '.ssh', 'google_compute_engine') }
|
|
38
|
+
|
|
39
|
+
context 'when default key exists' do
|
|
40
|
+
before do
|
|
41
|
+
FileUtils.mkdir_p(File.dirname(default_private_key))
|
|
42
|
+
File.write(default_private_key, 'private key content')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'returns the default private key path' do
|
|
46
|
+
expect(google_compute.find_google_ssh_private_key).to eq(default_private_key)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'when private key does not exist' do
|
|
51
|
+
it 'raises an error' do
|
|
52
|
+
expect { google_compute.find_google_ssh_private_key }.to raise_error(/Could not find GCE Private SSH key/)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#find_google_ssh_private_key with custom key' do
|
|
58
|
+
subject(:google_compute) do
|
|
59
|
+
mock_google_services
|
|
60
|
+
described_class.new(hosts, options.merge(gce_ssh_private_key: custom_private_key))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
let(:custom_private_key) { '/custom/path/to/key' }
|
|
64
|
+
|
|
65
|
+
context 'when custom key is specified in options' do
|
|
66
|
+
before do
|
|
67
|
+
FileUtils.mkdir_p(File.dirname(custom_private_key))
|
|
68
|
+
File.write(custom_private_key, 'private key content')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'returns the custom private key path' do
|
|
72
|
+
expect(google_compute.find_google_ssh_private_key).to eq(custom_private_key)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe '#find_google_ssh_public_key' do
|
|
78
|
+
subject(:google_compute) do
|
|
79
|
+
mock_google_services
|
|
80
|
+
described_class.new(hosts, options)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'when public key exists' do
|
|
84
|
+
let(:private_key) { '/path/to/private_key' }
|
|
85
|
+
let(:public_key) { '/path/to/private_key.pub' }
|
|
86
|
+
|
|
87
|
+
before do
|
|
88
|
+
FileUtils.mkdir_p(File.dirname(private_key))
|
|
89
|
+
File.write(private_key, 'private key content')
|
|
90
|
+
File.write(public_key, 'public key content')
|
|
91
|
+
# Set up the private key path in options for this test
|
|
92
|
+
google_compute.instance_variable_get(:@options)[:gce_ssh_private_key] = private_key
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'returns the public key path' do
|
|
96
|
+
expect(google_compute.find_google_ssh_public_key).to eq(public_key)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context 'when public key does not exist' do
|
|
101
|
+
let(:private_key) { '/path/to/private_key' }
|
|
102
|
+
|
|
103
|
+
before do
|
|
104
|
+
FileUtils.mkdir_p(File.dirname(private_key))
|
|
105
|
+
File.write(private_key, 'private key content')
|
|
106
|
+
# Set up the private key path in options for this test
|
|
107
|
+
google_compute.instance_variable_get(:@options)[:gce_ssh_private_key] = private_key
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'raises an error' do
|
|
111
|
+
expect { google_compute.find_google_ssh_public_key }.to raise_error(/Could not find GCE Public SSH key/)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
# Mock the Google Compute classes to avoid dependency issues
|
|
6
|
+
module Beaker
|
|
7
|
+
class Google < Beaker::GoogleCompute
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
RSpec.describe Beaker::Google do
|
|
12
|
+
let(:hosts) { [] }
|
|
13
|
+
let(:options) { { gce_project: 'test', logger: instance_double(Beaker::Logger) } }
|
|
14
|
+
|
|
15
|
+
# Mock Google authentication and services to avoid actual authentication
|
|
16
|
+
before do
|
|
17
|
+
# Mock the authentication components
|
|
18
|
+
allow(Google::Auth).to receive(:get_application_default).and_return(
|
|
19
|
+
instance_double(Google::Auth::ServiceAccountCredentials),
|
|
20
|
+
)
|
|
21
|
+
allow(Google::Auth::ServiceAccountCredentials).to receive(:from_env).and_return(
|
|
22
|
+
instance_double(Google::Auth::ServiceAccountCredentials),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Mock the Google API client options
|
|
26
|
+
client_options = instance_double(Google::Apis::ClientOptions)
|
|
27
|
+
allow(client_options).to receive(:application_name=)
|
|
28
|
+
allow(client_options).to receive(:application_version=)
|
|
29
|
+
allow(Google::Apis::ClientOptions).to receive(:default).and_return(client_options)
|
|
30
|
+
|
|
31
|
+
# Mock the Google Compute and OS Login services
|
|
32
|
+
compute_service = instance_double(Google::Apis::ComputeV1::ComputeService)
|
|
33
|
+
allow(compute_service).to receive(:authorization=)
|
|
34
|
+
allow(compute_service).to receive(:request_options).and_return(Google::Apis::RequestOptions.new)
|
|
35
|
+
allow(Google::Apis::ComputeV1::ComputeService).to receive(:new).and_return(compute_service)
|
|
36
|
+
|
|
37
|
+
oslogin_service = instance_double(Google::Apis::OsloginV1::CloudOSLoginService)
|
|
38
|
+
allow(oslogin_service).to receive(:authorization=)
|
|
39
|
+
allow(Google::Apis::OsloginV1::CloudOSLoginService).to receive(:new).and_return(oslogin_service)
|
|
40
|
+
|
|
41
|
+
# Mock environment variables that might be checked
|
|
42
|
+
allow(ENV).to receive(:[]).and_call_original
|
|
43
|
+
allow(ENV).to receive(:fetch).and_call_original
|
|
44
|
+
allow(ENV).to receive(:[]).with('GOOGLE_APPLICATION_CREDENTIALS').and_return(nil)
|
|
45
|
+
allow(ENV).to receive(:[]).with('GOOGLE_CLOUD_UNIVERSE_DOMAIN').and_return(nil)
|
|
46
|
+
allow(ENV).to receive(:[]).with('GOOGLE_CLOUD_PROJECT').and_return(nil)
|
|
47
|
+
allow(ENV).to receive(:[]).with('GCLOUD_PROJECT').and_return(nil)
|
|
48
|
+
allow(ENV).to receive(:[]).with('BEAKER_gce_project').and_return(nil)
|
|
49
|
+
allow(ENV).to receive(:[]).with('BEAKER_gce_ssh_public_key').and_return(nil)
|
|
50
|
+
allow(ENV).to receive(:[]).with('BEAKER_gce_ssh_private_key').and_return(nil)
|
|
51
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_zone', anything).and_return('us-central1-a')
|
|
52
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_network', anything).and_return('default')
|
|
53
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_subnetwork', anything).and_return(nil)
|
|
54
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_ports', anything).and_return('')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe 'class hierarchy' do
|
|
58
|
+
it 'inherits from GoogleCompute' do
|
|
59
|
+
expect(described_class.superclass).to eq(Beaker::GoogleCompute)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe 'instantiation' do
|
|
64
|
+
it 'can be instantiated' do
|
|
65
|
+
expect { described_class.new(hosts, options) }.not_to raise_error
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe BeakerGoogle do
|
|
6
|
+
describe 'VERSION' do
|
|
7
|
+
it 'has a version number' do
|
|
8
|
+
expect(BeakerGoogle::VERSION).not_to be_nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'is a string' do
|
|
12
|
+
expect(BeakerGoogle::VERSION).to be_a(String)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'follows semantic versioning pattern' do
|
|
16
|
+
expect(BeakerGoogle::VERSION).to match(/\A\d+\.\d+\.\d+\z/)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Beaker do
|
|
6
|
+
context 'when testing Google integration' do
|
|
7
|
+
describe 'basic integration test' do
|
|
8
|
+
let(:logger) { instance_double(Beaker::Logger) }
|
|
9
|
+
let(:test_options) { { logger: logger, gce_project: 'test-project', gce_ports: [] } }
|
|
10
|
+
|
|
11
|
+
def mock_google_services
|
|
12
|
+
# Mock the authentication and service initialization
|
|
13
|
+
allow(Google::Auth).to receive(:get_application_default).and_return(double)
|
|
14
|
+
|
|
15
|
+
compute_service = double
|
|
16
|
+
allow(compute_service).to receive(:authorization=)
|
|
17
|
+
allow(compute_service).to receive(:request_options).and_return(Google::Apis::RequestOptions.new)
|
|
18
|
+
allow(Google::Apis::ComputeV1::ComputeService).to receive(:new).and_return(compute_service)
|
|
19
|
+
|
|
20
|
+
oslogin_service = double
|
|
21
|
+
allow(oslogin_service).to receive(:authorization=)
|
|
22
|
+
allow(Google::Apis::OsloginV1::CloudOSLoginService).to receive(:new).and_return(oslogin_service)
|
|
23
|
+
|
|
24
|
+
client_options = double
|
|
25
|
+
allow(client_options).to receive(:application_name=)
|
|
26
|
+
allow(client_options).to receive(:application_version=)
|
|
27
|
+
allow(Google::Apis::ClientOptions).to receive(:default).and_return(client_options)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
before do
|
|
31
|
+
mock_google_services
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'loads the beaker-google version' do
|
|
35
|
+
expect(BeakerGoogle::VERSION).to be_a(String)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'can create GoogleComputeHelper instances' do
|
|
39
|
+
expect do
|
|
40
|
+
Beaker::GoogleComputeHelper.new(test_options)
|
|
41
|
+
end.not_to raise_error
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'can create GoogleCompute instances' do
|
|
45
|
+
expect do
|
|
46
|
+
Beaker::GoogleCompute.new([], test_options)
|
|
47
|
+
end.not_to raise_error
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'has proper class inheritance' do
|
|
51
|
+
expect(Beaker::GoogleCompute).to be < Beaker::Hypervisor
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'loads ComputeV1 API' do
|
|
55
|
+
expect(defined?(Google::Apis::ComputeV1)).to be_truthy
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'loads OsloginV1 API' do
|
|
59
|
+
expect(defined?(Google::Apis::OsloginV1)).to be_truthy
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'loads Google Auth' do
|
|
63
|
+
expect(defined?(Google::Auth)).to be_truthy
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec'
|
|
4
|
+
require 'rspec/its'
|
|
5
|
+
require 'fakefs/spec_helpers'
|
|
6
|
+
require 'simplecov'
|
|
7
|
+
|
|
8
|
+
# Start SimpleCov if coverage is enabled
|
|
9
|
+
SimpleCov.start if ENV['BEAKER_GOOGLE_COVERAGE']
|
|
10
|
+
|
|
11
|
+
# Require beaker first to establish the base classes
|
|
12
|
+
require 'beaker'
|
|
13
|
+
|
|
14
|
+
# Only require the version module directly
|
|
15
|
+
require 'beaker-google/version'
|
|
16
|
+
|
|
17
|
+
# Require the hypervisor classes
|
|
18
|
+
require 'beaker/hypervisor/google_compute_helper'
|
|
19
|
+
require 'beaker/hypervisor/google_compute'
|
|
20
|
+
require 'beaker/hypervisor/google'
|
|
21
|
+
|
|
22
|
+
# Load shared mock classes
|
|
23
|
+
require_relative 'support/shared_mocks'
|
|
24
|
+
|
|
25
|
+
RSpec.configure do |config|
|
|
26
|
+
config.expect_with :rspec do |expectations|
|
|
27
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
config.mock_with :rspec do |mocks|
|
|
31
|
+
mocks.verify_partial_doubles = true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
|
35
|
+
config.filter_run_when_matching :focus
|
|
36
|
+
config.disable_monkey_patching!
|
|
37
|
+
config.warnings = true
|
|
38
|
+
|
|
39
|
+
config.default_formatter = 'doc' if config.files_to_run.one?
|
|
40
|
+
|
|
41
|
+
config.profile_examples = 10
|
|
42
|
+
config.order = :random
|
|
43
|
+
|
|
44
|
+
Kernel.srand config.seed
|
|
45
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Shared setup for Google Compute tests to avoid multiple memoized helpers
|
|
4
|
+
module GoogleComputeSharedSetup
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(ClassMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
def setup_google_compute_mocks
|
|
11
|
+
let(:mock_gce_helper) { instance_double(Beaker::GoogleComputeHelper) }
|
|
12
|
+
let(:mock_network) { MockNetwork.new }
|
|
13
|
+
let(:mock_machine_type) { MockMachineType.new }
|
|
14
|
+
let(:mock_image) { MockImage.new }
|
|
15
|
+
let(:mock_instance) do
|
|
16
|
+
instance_double(Google::Apis::ComputeV1::Instance).tap do |instance|
|
|
17
|
+
allow(instance).to receive(:network_interfaces)
|
|
18
|
+
.and_return([
|
|
19
|
+
instance_double(Google::Apis::ComputeV1::NetworkInterface).tap do |interface|
|
|
20
|
+
allow(interface).to receive(:access_configs)
|
|
21
|
+
.and_return([
|
|
22
|
+
instance_double(Google::Apis::ComputeV1::AccessConfig).tap do |config|
|
|
23
|
+
allow(config).to receive(:nat_ip).and_return('1.2.3.4')
|
|
24
|
+
end,
|
|
25
|
+
])
|
|
26
|
+
end,
|
|
27
|
+
])
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
let(:mock_operation) do
|
|
31
|
+
instance_double(Google::Apis::ComputeV1::Operation).tap do |operation|
|
|
32
|
+
allow(operation).to receive(:error).and_return(nil)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
let(:logger) { instance_double(Beaker::Logger, debug: nil, info: nil, warn: nil, error: nil) }
|
|
37
|
+
|
|
38
|
+
before do
|
|
39
|
+
# Mock the GoogleComputeHelper initialization to avoid authentication
|
|
40
|
+
allow(Beaker::GoogleComputeHelper).to receive(:new).and_return(mock_gce_helper)
|
|
41
|
+
|
|
42
|
+
# Mock all the GoogleComputeHelper methods
|
|
43
|
+
allow(mock_gce_helper).to receive_messages(
|
|
44
|
+
get_network: mock_network,
|
|
45
|
+
get_machine_type: mock_machine_type,
|
|
46
|
+
get_image: mock_image,
|
|
47
|
+
get_latest_image_from_family: mock_image,
|
|
48
|
+
get_instance: mock_instance,
|
|
49
|
+
create_firewall: mock_operation,
|
|
50
|
+
delete_firewall: mock_operation,
|
|
51
|
+
create_instance: mock_operation,
|
|
52
|
+
delete_instance: mock_operation,
|
|
53
|
+
add_instance_tag: mock_operation,
|
|
54
|
+
set_metadata_on_instance: mock_operation,
|
|
55
|
+
options: options,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Set up environment variables for testing
|
|
59
|
+
allow(ENV).to receive(:fetch).and_call_original
|
|
60
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_machine_type', anything).and_return('n1-standard-1')
|
|
61
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_ssh_private_key',
|
|
62
|
+
anything).and_return(File.join(Dir.home, '.ssh', 'google_compute_engine'))
|
|
63
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_zone', anything).and_return('us-central1-a')
|
|
64
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_network', anything).and_return('default')
|
|
65
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_subnetwork', anything).and_return(nil)
|
|
66
|
+
allow(ENV).to receive(:fetch).with('BEAKER_gce_ports', anything).and_return('80/tcp,443/tcp')
|
|
67
|
+
allow(ENV).to receive(:[]).with('BEAKER_gce_project').and_return('test-project')
|
|
68
|
+
allow(ENV).to receive(:[]).with('BEAKER_gce_ssh_public_key').and_return(nil)
|
|
69
|
+
allow(ENV).to receive(:[]).with('BEAKER_gce_ssh_private_key').and_return(nil)
|
|
70
|
+
|
|
71
|
+
# Mock the image disk size
|
|
72
|
+
allow(mock_image).to receive(:disk_size_gb).and_return(20)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def setup_test_hosts
|
|
77
|
+
let(:primary_host) do
|
|
78
|
+
{
|
|
79
|
+
'name' => 'test-host-1',
|
|
80
|
+
'user' => 'root',
|
|
81
|
+
'options' => { 'ssh' => { 'keys' => [] } },
|
|
82
|
+
'gce_machine_type' => 'n1-standard-1',
|
|
83
|
+
:image => 'ubuntu-1804-lts',
|
|
84
|
+
'volume_size' => nil,
|
|
85
|
+
'disable_root_ssh' => nil,
|
|
86
|
+
}.tap do |host|
|
|
87
|
+
# Add methods needed by the gem
|
|
88
|
+
def host.close; end
|
|
89
|
+
|
|
90
|
+
def host.name
|
|
91
|
+
self['name']
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def host.options
|
|
95
|
+
self['options']
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
let(:secondary_host) do
|
|
101
|
+
{
|
|
102
|
+
'name' => 'test-host-2',
|
|
103
|
+
'user' => 'root',
|
|
104
|
+
'options' => { 'ssh' => { 'keys' => [] } },
|
|
105
|
+
'gce_machine_type' => 'n1-standard-1',
|
|
106
|
+
:image => 'ubuntu-1804-lts',
|
|
107
|
+
'volume_size' => nil,
|
|
108
|
+
'disable_root_ssh' => nil,
|
|
109
|
+
}.tap do |host|
|
|
110
|
+
# Add methods needed by the gem
|
|
111
|
+
def host.close; end
|
|
112
|
+
|
|
113
|
+
def host.name
|
|
114
|
+
self['name']
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def host.options
|
|
118
|
+
self['options']
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
let(:hosts) { [primary_host, secondary_host] }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def setup_test_options
|
|
127
|
+
let(:options) do
|
|
128
|
+
{
|
|
129
|
+
gce_project: 'test-project',
|
|
130
|
+
gce_zone: 'us-central1-a',
|
|
131
|
+
gce_network: 'default',
|
|
132
|
+
gce_ports: ['80/tcp', '443/tcp'],
|
|
133
|
+
logger: logger,
|
|
134
|
+
}
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
# Add mutex_m requirement for Ruby 3.4.0 compatibility
|
|
6
|
+
begin
|
|
7
|
+
require 'mutex_m'
|
|
8
|
+
rescue LoadError
|
|
9
|
+
# mutex_m is not available on all Ruby versions
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Mock external classes that we don't want to test
|
|
13
|
+
class MockNetwork
|
|
14
|
+
def initialize
|
|
15
|
+
@name = 'test-network'
|
|
16
|
+
@self_link = 'https://www.googleapis.com/compute/v1/projects/test-project/global/networks/test-network'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
attr_reader :name, :self_link
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class MockSubnetwork
|
|
23
|
+
def initialize
|
|
24
|
+
@name = 'test-subnetwork'
|
|
25
|
+
@self_link = 'https://www.googleapis.com/compute/v1/projects/test-project/regions/us-central1/subnetworks/test-subnetwork'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
attr_reader :name, :self_link
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class MockMachineType
|
|
32
|
+
def initialize
|
|
33
|
+
@name = 'n1-standard-1'
|
|
34
|
+
@memory_mb = 3840
|
|
35
|
+
@guest_cpus = 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
attr_reader :name, :memory_mb, :guest_cpus
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class MockImage
|
|
42
|
+
def initialize
|
|
43
|
+
@name = 'test-image'
|
|
44
|
+
@self_link = 'https://www.googleapis.com/compute/v1/projects/test-project/global/images/test-image'
|
|
45
|
+
@disk_size_gb = 20
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
attr_reader :name, :self_link, :disk_size_gb
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class MockInstance
|
|
52
|
+
def initialize
|
|
53
|
+
@name = 'test-instance'
|
|
54
|
+
@status = 'RUNNING'
|
|
55
|
+
@tags = MockTags.new
|
|
56
|
+
@metadata = MockMetadata.new
|
|
57
|
+
@fingerprint = 'test-fingerprint'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
attr_reader :name, :status, :tags, :metadata, :fingerprint
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class MockTags
|
|
64
|
+
def initialize
|
|
65
|
+
@items = []
|
|
66
|
+
@fingerprint = 'test-fingerprint'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
attr_reader :items, :fingerprint
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class MockMetadata
|
|
73
|
+
def initialize
|
|
74
|
+
@items = []
|
|
75
|
+
@fingerprint = 'test-fingerprint'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
attr_accessor :items
|
|
79
|
+
attr_reader :fingerprint
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class MockOperation
|
|
83
|
+
def initialize
|
|
84
|
+
@name = 'test-operation'
|
|
85
|
+
@status = 'RUNNING'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
attr_reader :name, :status
|
|
89
|
+
end
|