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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/release.yml +41 -0
  3. data/.github/workflows/ci.yml +30 -17
  4. data/.github/workflows/release.yml +91 -17
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +4 -518
  7. data/.rubocop_todo.yml +20 -0
  8. data/.simplecov +2 -0
  9. data/CHANGELOG.md +50 -1
  10. data/Gemfile +13 -2
  11. data/README.md +2 -2
  12. data/Rakefile +23 -6
  13. data/beaker-google.gemspec +27 -23
  14. data/bin/beaker-google +1 -0
  15. data/lib/beaker/hypervisor/google.rb +5 -1
  16. data/lib/beaker/hypervisor/google_compute.rb +55 -25
  17. data/lib/beaker/hypervisor/google_compute_helper.rb +599 -581
  18. data/lib/beaker-google/version.rb +3 -1
  19. data/spec/classes/beaker/google_compute_constants_and_defaults_spec.rb +141 -0
  20. data/spec/classes/beaker/google_compute_helper_api_version_spec.rb +37 -0
  21. data/spec/classes/beaker/google_compute_helper_configuration_validation_spec.rb +100 -0
  22. data/spec/classes/beaker/google_compute_helper_constants_and_defaults_spec.rb +66 -0
  23. data/spec/classes/beaker/google_compute_helper_edge_cases_spec.rb +173 -0
  24. data/spec/classes/beaker/google_compute_helper_error_handling_spec.rb +105 -0
  25. data/spec/classes/beaker/google_compute_helper_spec.rb +368 -0
  26. data/spec/classes/beaker/google_compute_helper_utilities_spec.rb +95 -0
  27. data/spec/classes/beaker/google_compute_initialization_spec.rb +52 -0
  28. data/spec/classes/beaker/google_compute_provision_spec.rb +68 -0
  29. data/spec/classes/beaker/google_compute_spec.rb +95 -0
  30. data/spec/classes/beaker/google_compute_ssh_key_management_spec.rb +115 -0
  31. data/spec/classes/beaker/google_spec.rb +68 -0
  32. data/spec/classes/beaker-google/beaker_google_version_spec.rb +19 -0
  33. data/spec/classes/beaker_integration_spec.rb +67 -0
  34. data/spec/spec_helper.rb +45 -0
  35. data/spec/support/google_compute_shared_setup.rb +138 -0
  36. data/spec/support/shared_mocks.rb +89 -0
  37. metadata +102 -38
  38. data/.github/workflows/codeql-analysis.yml +0 -70
@@ -10,636 +10,654 @@ require 'ostruct'
10
10
  # TODO: Figure out what to do about the timeout thing
11
11
  # TODO: Implement Google::Apis::RequestOptions on all calls (In lib/google/apis/options.rb)
12
12
 
13
- # Beaker helper module for doing API level Google Compute Engine interaction.
14
- class Beaker::GoogleComputeHelper
15
- class GoogleComputeError < StandardError
16
- end
13
+ module Beaker
14
+ # Beaker helper module for doing API level Google Compute Engine interaction.
15
+ class GoogleComputeHelper
16
+ class GoogleComputeError < StandardError
17
+ end
17
18
 
18
- SLEEPWAIT = 5
19
+ attr_reader :options
19
20
 
20
- AUTH_URL = 'https://www.googleapis.com/auth/compute'
21
- API_VERSION = 'v1'
22
- BASE_URL = "https://www.googleapis.com/compute/#{API_VERSION}/projects/"
23
- DEFAULT_ZONE_NAME = 'us-central1-a'
24
- DEFAULT_MACHINE_TYPE = 'e2-standard-4'
25
- DEFAULT_NETWORK_NAME = 'default'
21
+ SLEEPWAIT = 5
26
22
 
27
- VALID_PROTOS = ['tcp', 'udp', 'icmp', 'esp', 'ah', 'ipip', 'sctp']
23
+ AUTH_URL = 'https://www.googleapis.com/auth/compute'
24
+ API_VERSION = 'v1'
25
+ BASE_URL = "https://www.googleapis.com/compute/#{API_VERSION}/projects/"
26
+ DEFAULT_ZONE_NAME = 'us-central1-a'
27
+ DEFAULT_MACHINE_TYPE = 'e2-standard-4'
28
+ DEFAULT_NETWORK_NAME = 'default'
28
29
 
29
- GCP_AUTH_SCOPE = [
30
- Google::Apis::ComputeV1::AUTH_COMPUTE,
31
- Google::Apis::OsloginV1::AUTH_CLOUD_PLATFORM_READ_ONLY,
32
- ].freeze
30
+ VALID_PROTOS = %w[tcp udp icmp esp ah ipip sctp].freeze
33
31
 
34
- ##
35
- # Create a new instance of the Google Compute Engine helper object
36
- #
37
- def initialize(options)
38
- @options = options
39
- @logger = options[:logger]
32
+ GCP_AUTH_SCOPE = [
33
+ ::Google::Apis::ComputeV1::AUTH_COMPUTE,
34
+ ::Google::Apis::OsloginV1::AUTH_CLOUD_PLATFORM_READ_ONLY,
35
+ ].freeze
40
36
 
41
- set_client(Beaker::Version::STRING)
37
+ ##
38
+ # Create a new instance of the Google Compute Engine helper object
39
+ #
40
+ def initialize(options)
41
+ @options = options
42
+ @logger = options[:logger]
42
43
 
43
- # ::Google::Apis.logger = ::Logger.new(::STDERR)
44
- # ::Google::Apis.logger.level = ::Logger::DEBUG
45
- # ::Google::Apis.logger.level = ::Logger::WARN
44
+ client(Beaker::Version::STRING)
46
45
 
47
- @options[:gce_project] = ENV['BEAKER_gce_project'] if ENV['BEAKER_gce_project']
46
+ # ::Google::Apis.logger = ::Logger.new(::STDERR)
47
+ # ::Google::Apis.logger.level = ::Logger::DEBUG
48
+ # ::Google::Apis.logger.level = ::Logger::WARN
48
49
 
49
- @options[:gce_zone] = ENV.fetch('BEAKER_gce_zone', DEFAULT_ZONE_NAME)
50
- @options[:gce_network] = ENV.fetch('BEAKER_gce_network', DEFAULT_NETWORK_NAME)
51
- @options[:gce_subnetwork] = ENV.fetch('BEAKER_gce_subnetwork', nil)
50
+ @options[:gce_project] = ENV['BEAKER_gce_project'] if ENV['BEAKER_gce_project']
52
51
 
53
- @configure_ports = ENV.fetch('BEAKER_gce_ports', "").strip
54
- # Split the ports based on commas, removing any empty values
55
- @options[:gce_ports] = @configure_ports.split(/\s*?,\s*/).reject { |s| s.empty? }
52
+ @options[:gce_zone] = ENV.fetch('BEAKER_gce_zone', DEFAULT_ZONE_NAME)
53
+ @options[:gce_network] = ENV.fetch('BEAKER_gce_network', DEFAULT_NETWORK_NAME)
54
+ @options[:gce_subnetwork] = ENV.fetch('BEAKER_gce_subnetwork', nil)
56
55
 
57
- raise 'You must specify a gce_project for Google Compute Engine instances!' unless @options[:gce_project]
56
+ # A non-empty BEAKER_gce_ports replaces gce_ports from the hosts file, as
57
+ # BEAKER_gce_project and BEAKER_gce_machine_type replace theirs. Either
58
+ # source may be a comma-separated string or a list.
59
+ env_ports = ENV.fetch('BEAKER_gce_ports', '').strip
60
+ ports = env_ports.empty? ? @options[:gce_ports] : env_ports
61
+ @options[:gce_ports] = Array(ports).flat_map { |entry| entry.to_s.split(',') }.map(&:strip).reject(&:empty?)
58
62
 
59
- @options[:gce_ports].each do |port|
60
- parts = port.split('/', 2)
61
- raise "Invalid format for port #{port}. Should be 'port/proto'" unless parts.length == 2
62
- proto = parts[1]
63
- raise "Invalid value '#{proto}' for protocol in '#{port}'. Must be one of '#{VALID_PROTOS.join("', '")}'" unless VALID_PROTOS.include? proto
64
- end
65
- authorizer = authenticate
66
- @compute = ::Google::Apis::ComputeV1::ComputeService.new
67
- @compute.authorization = authorizer
63
+ raise 'You must specify a gce_project for Google Compute Engine instances!' unless @options[:gce_project]
68
64
 
69
- # Find the appropriate username to log into created instances
70
- @cloudoslogin = Google::Apis::OsloginV1::CloudOSLoginService.new
71
- @cloudoslogin.authorization = authorizer
72
- end
65
+ @options[:gce_ports].each do |port|
66
+ parts = port.split('/', 2)
67
+ raise "Invalid format for port #{port}. Should be 'port/proto'" unless parts.length == 2
73
68
 
74
- ##
75
- # Determines the default Google Compute zone based upon options and
76
- # defaults
77
- #
78
- # @return [String] The name of the zone
79
- def default_zone
80
- @options[:gce_zone]
81
- end
69
+ proto = parts[1]
70
+ unless VALID_PROTOS.include? proto
71
+ raise "Invalid value '#{proto}' for protocol in '#{port}'. Must be one of '#{VALID_PROTOS.join("', '")}'"
72
+ end
73
+ end
74
+ authorizer = authenticate
75
+ @compute = ::Google::Apis::ComputeV1::ComputeService.new
76
+ @compute.authorization = authorizer
77
+ # google-apis-compute_v1 sends a dated X-Goog-Api-Version header on every
78
+ # call, and a release can name a version Compute Engine doesn't accept yet
79
+ # (0.157.0 sends 2026-11-01, which is rejected). Request options are
80
+ # applied after that header, so pin the API version this helper targets.
81
+ @compute.request_options.header = { 'X-Goog-Api-Version' => API_VERSION }
82
+
83
+ # Find the appropriate username to log into created instances
84
+ @cloudoslogin = ::Google::Apis::OsloginV1::CloudOSLoginService.new
85
+ @cloudoslogin.authorization = authorizer
86
+ end
82
87
 
83
- ##
84
- # Get the region name from the provided zone.
85
- #
86
- # Assume that the region is the name of the zone without
87
- # the final - and zone letter
88
- #
89
- # @return [String] The name of the region
90
- def default_region
91
- @options[:gce_zone].split('-')[0..1].join('-')
92
- end
88
+ ##
89
+ # Determines the default Google Compute zone based upon options and
90
+ # defaults
91
+ #
92
+ # @return [String] The name of the zone
93
+ def default_zone
94
+ @options[:gce_zone]
95
+ end
93
96
 
94
- ##
95
- # Determines the default Google Compute network based upon defaults and
96
- # options
97
- #
98
- # @return [String] The short name of the VPC network
99
- def default_network
100
- @options[:gce_network]
101
- end
97
+ ##
98
+ # Get the region name from the provided zone.
99
+ #
100
+ # Assume that the region is the name of the zone without
101
+ # the final - and zone letter
102
+ #
103
+ # @return [String] The name of the region
104
+ def default_region
105
+ @options[:gce_zone].split('-')[0..1].join('-')
106
+ end
102
107
 
103
- ##
104
- # Find the username for ssh to use with this connection
105
- #
106
- # @return [String] The username for ssh
107
- #
108
- # @raise [Google::Auth::IDTokens::KeySourceError] if the key source failed to obtain public keys
109
- # @raise [Google::Auth::IDTokens::VerificationError] if the token verification failed.
110
- # Additional data may be available in the error subclass and message.
111
- def ssh_username
112
- authorizer = @compute.authorization
113
- # This is a bit of a hack based on what I found in a user (default application credentials)
114
- # and a service account. There might be a better way of doing this.
115
- case authorizer.class.to_s
116
- when 'Google::Auth::UserRefreshCredentials'
117
- authorizer.refresh!
118
- userid = ::Google::Auth::IDTokens.verify_oidc(authorizer.id_token)['email']
119
- when 'Google::Auth::ServiceAccountCredentials'
120
- userid = authorizer.issuer
121
- else
122
- raise 'Unknown type of credential'
108
+ ##
109
+ # Determines the default Google Compute network based upon defaults and
110
+ # options
111
+ #
112
+ # @return [String] The short name of the VPC network
113
+ def default_network
114
+ @options[:gce_network]
123
115
  end
124
- userid = "users/#{userid}" unless userid.start_with? 'users/'
125
- @cloudoslogin.get_user_login_profile(userid).posix_accounts[0].username
126
- end
127
116
 
128
- ##
129
- # Infer the network that a given subnetwork is attached to
130
- #
131
- # @param [String] subnetwork_name The name of the subnetwork
132
- #
133
- # @return [String] The short name of the network
134
- #
135
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
136
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
137
- # @raise [Google::Apis::AuthorizationError] Authorization is required
138
- def default_network_from_subnet(subnetwork_name)
139
- subnetwork = @compute.get_subnetwork(@options[:gce_project], default_region, subnetwork_name)
140
- m = %r{.*/networks/(?<network_name>.*)\Z}.match subnetwork.network
141
- nil if m.nil?
142
- m['network_name']
143
- end
117
+ ##
118
+ # Find the username for ssh to use with this connection
119
+ #
120
+ # @return [String] The username for ssh
121
+ #
122
+ # @raise [Google::Auth::IDTokens::KeySourceError] if the key source failed to obtain public keys
123
+ # @raise [Google::Auth::IDTokens::VerificationError] if the token verification failed.
124
+ # Additional data may be available in the error subclass and message.
125
+ def ssh_username
126
+ authorizer = @compute.authorization
127
+ # This is a bit of a hack based on what I found in a user (default application credentials)
128
+ # and a service account. There might be a better way of doing this.
129
+ case authorizer.class.to_s
130
+ when 'Google::Auth::UserRefreshCredentials'
131
+ authorizer.refresh!
132
+ userid = ::Google::Auth::IDTokens.verify_oidc(authorizer.id_token)['email']
133
+ when 'Google::Auth::ServiceAccountCredentials'
134
+ userid = authorizer.issuer
135
+ else
136
+ raise 'Unknown type of credential'
137
+ end
138
+ userid = "users/#{userid}" unless userid.start_with? 'users/'
139
+ @cloudoslogin.get_user_login_profile(userid).posix_accounts[0].username
140
+ end
144
141
 
145
- ##
146
- # Determine the subnetwork to use for instances
147
- #
148
- # If the network is the 'default' network, get the 'default' subnetwork for the region.
149
- # If no subnet is provided by the user, pick the first one out of the user-provided network
150
- #
151
- # @return [String] The name of the subnetwork that should be attached to the instances
152
- def default_subnetwork
153
- network_name = @options[:gce_network]
154
- if network_name == 'default'
155
- @options[:gce_subnetwork] ||= @compute.get_subnetwork(@options[:gce_project], default_region, 'default').name
156
- elsif @options[:gce_subnetwork].nil?
157
- # No subnet set, get the first subnet in our current region for the network
158
- subnetwork = @compute.get_network(@options[:gce_project], network_name).subnetworks[0]
159
- m = %r{.*/subnetworks/(?<subnetwork_name>.*)\Z}.match subnetwork
160
- raise "Unable to find a subnetwork in provided network #{network_name}" if m.nil?
161
-
162
- @options[:gce_subnetwork] = m['subnetwork_name']
142
+ ##
143
+ # Infer the network that a given subnetwork is attached to
144
+ #
145
+ # @param [String] subnetwork_name The name of the subnetwork
146
+ #
147
+ # @return [String] The short name of the network
148
+ #
149
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
150
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
151
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
152
+ def default_network_from_subnet(subnetwork_name)
153
+ subnetwork = @compute.get_subnetwork(@options[:gce_project], default_region, subnetwork_name)
154
+ m = %r{.*/networks/(?<network_name>.*)\Z}.match subnetwork.network
155
+ nil if m.nil?
156
+ m['network_name']
163
157
  end
164
- @options[:gce_subnetwork]
165
- end
166
158
 
167
- ##
168
- # Set the user-agent information for the application.
169
- #
170
- # @param version The version number of Beaker currently running
171
- def set_client(version)
172
- ::Google::Apis::ClientOptions.default.application_name = 'beaker-google'
173
- ::Google::Apis::ClientOptions.default.application_version = version
174
- end
159
+ ##
160
+ # Determine the subnetwork to use for instances
161
+ #
162
+ # If the network is the 'default' network, get the 'default' subnetwork for the region.
163
+ # If no subnet is provided by the user, pick the first one out of the user-provided network
164
+ #
165
+ # @return [String] The name of the subnetwork that should be attached to the instances
166
+ def default_subnetwork
167
+ network_name = @options[:gce_network]
168
+ if network_name == 'default'
169
+ @options[:gce_subnetwork] ||= @compute.get_subnetwork(@options[:gce_project], default_region, 'default').name
170
+ elsif @options[:gce_subnetwork].nil?
171
+ # No subnet set, get the first subnet in our current region for the network
172
+ subnetwork = @compute.get_network(@options[:gce_project], network_name).subnetworks[0]
173
+ m = %r{.*/subnetworks/(?<subnetwork_name>.*)\Z}.match subnetwork
174
+ raise "Unable to find a subnetwork in provided network #{network_name}" if m.nil?
175
+
176
+ @options[:gce_subnetwork] = m['subnetwork_name']
177
+ end
178
+ @options[:gce_subnetwork]
179
+ end
175
180
 
176
- ##
177
- # Creates an authentication object to use in the various Google APIs
178
- #
179
- # This method currently supports using application credentials via the
180
- # GOOGLE_APPLICATION_CREDENTIALS environment variable, and application default
181
- # credentials.
182
- #
183
- # @return [Google::Auth::UserRefreshCredentials|Google::Auth::ServiceAccountCredentials]
184
- # Authorization object to pass to Google APIs
185
- def authenticate
186
- if ENV['GOOGLE_APPLICATION_CREDENTIALS']
187
- ::Google::Auth::ServiceAccountCredentials.from_env(scope: GCP_AUTH_SCOPE)
188
- else
189
- # Fall back to default application auth
190
- ::Google::Auth.get_application_default(GCP_AUTH_SCOPE)
181
+ ##
182
+ # Set the user-agent information for the application.
183
+ #
184
+ # @param version The version number of Beaker currently running
185
+ def client(version)
186
+ ::Google::Apis::ClientOptions.default.application_name = 'beaker-google'
187
+ ::Google::Apis::ClientOptions.default.application_version = version
191
188
  end
192
- end
193
189
 
194
- ##
195
- # Find the correct image object for a given project and name
196
- #
197
- # @param [String] image_project The project that owns the requested image
198
- #
199
- # @param [String] name The name of the image in the project. This must
200
- # be the exact name of the image
201
- #
202
- # @return [Google::Apis::ComputeV1::Image]
203
- #
204
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
205
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
206
- # @raise [Google::Apis::AuthorizationError] Authorization is required
207
- def get_image(project, name)
208
- @compute.get_image(project, name)
209
- end
190
+ ##
191
+ # Creates an authentication object to use in the various Google APIs
192
+ #
193
+ # This method currently supports using application credentials via the
194
+ # GOOGLE_APPLICATION_CREDENTIALS environment variable, and application default
195
+ # credentials.
196
+ #
197
+ # @return [Google::Auth::UserRefreshCredentials|Google::Auth::ServiceAccountCredentials]
198
+ # Authorization object to pass to Google APIs
199
+ def authenticate
200
+ if ENV['GOOGLE_APPLICATION_CREDENTIALS']
201
+ ::Google::Auth::ServiceAccountCredentials.from_env(scope: GCP_AUTH_SCOPE)
202
+ else
203
+ # Fall back to default application auth
204
+ ::Google::Auth.get_application_default(GCP_AUTH_SCOPE)
205
+ end
206
+ end
210
207
 
211
- ##
212
- # Find the latest non-deprecated image in the given project and family
213
- #
214
- # @param [String] image_project The project that owns the requested image
215
- #
216
- # @param [String] family The name of the image family
217
- #
218
- # @return [Google::Apis::ComputeV1::Image]
219
- #
220
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
221
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
222
- # @raise [Google::Apis::AuthorizationError] Authorization is required
223
- def get_latest_image_from_family(image_project, family)
224
- @compute.get_image_from_family(image_project, family)
225
- end
208
+ ##
209
+ # Find the correct image object for a given project and name
210
+ #
211
+ # @param [String] image_project The project that owns the requested image
212
+ #
213
+ # @param [String] name The name of the image in the project. This must
214
+ # be the exact name of the image
215
+ #
216
+ # @return [Google::Apis::ComputeV1::Image]
217
+ #
218
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
219
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
220
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
221
+ def get_image(project, name)
222
+ @compute.get_image(project, name)
223
+ end
226
224
 
227
- ##
228
- # Determines the Google Compute machineType object based upon the selected
229
- # gce_machine_type option
230
- #
231
- # @param [String] type_name The name of the type to get
232
- #
233
- # @return [Google::Apis::ComputeV1::MachineType]
234
- #
235
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
236
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
237
- # @raise [Google::Apis::AuthorizationError] Authorization is required
238
- def get_machine_type(type_name = DEFAULT_MACHINE_TYPE)
239
- @compute.get_machine_type(@options[:gce_project], default_zone, type_name)
240
- end
225
+ ##
226
+ # Find the latest non-deprecated image in the given project and family
227
+ #
228
+ # @param [String] image_project The project that owns the requested image
229
+ #
230
+ # @param [String] family The name of the image family
231
+ #
232
+ # @return [Google::Apis::ComputeV1::Image]
233
+ #
234
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
235
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
236
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
237
+ def get_latest_image_from_family(image_project, family)
238
+ @compute.get_image_from_family(image_project, family)
239
+ end
241
240
 
242
- ##
243
- # Determines the Google Compute network object in use for the current connection
244
- #
245
- # @return [Google::Apis::ComputeV1::Network]
246
- #
247
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
248
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
249
- # @raise [Google::Apis::AuthorizationError] Authorization is required
250
- def get_network(network_name = default_network)
251
- @compute.get_network(@options[:gce_project], network_name)
252
- end
241
+ ##
242
+ # Determines the Google Compute machineType object based upon the selected
243
+ # gce_machine_type option
244
+ #
245
+ # @param [String] type_name The name of the type to get
246
+ #
247
+ # @return [Google::Apis::ComputeV1::MachineType]
248
+ #
249
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
250
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
251
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
252
+ def get_machine_type(type_name = DEFAULT_MACHINE_TYPE)
253
+ @compute.get_machine_type(@options[:gce_project], default_zone, type_name)
254
+ end
253
255
 
254
- ##
255
- # Determines a list of existing Google Compute instances
256
- #
257
- # @return [Array[Google::Apis::ComputeV1::Instance]]
258
- #
259
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
260
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
261
- # @raise [Google::Apis::AuthorizationError] Authorization is required
262
- def list_instances
263
- @compute.list_instances(@options[:gce_project], default_zone).items
264
- end
256
+ ##
257
+ # Determines the Google Compute network object in use for the current connection
258
+ #
259
+ # @return [Google::Apis::ComputeV1::Network]
260
+ #
261
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
262
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
263
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
264
+ def get_network(network_name = default_network)
265
+ @compute.get_network(@options[:gce_project], network_name)
266
+ end
265
267
 
266
- ##
267
- # Determines a list of existing Google Compute disks
268
- #
269
- # @param [Integer] start The time when we started code execution, it is
270
- # compared to Time.now to determine how many further code execution
271
- # attempts remain
272
- #
273
- # @return [Array[Google::Apis::ComputeV1::Disk]]
274
- #
275
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
276
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
277
- # @raise [Google::Apis::AuthorizationError] Authorization is required
278
- def list_disks
279
- @compute.list_disks(@options[:gce_project], default_zone).items
280
- end
268
+ ##
269
+ # Determines a list of existing Google Compute instances
270
+ #
271
+ # @return [Array[Google::Apis::ComputeV1::Instance]]
272
+ #
273
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
274
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
275
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
276
+ def list_instances
277
+ @compute.list_instances(@options[:gce_project], default_zone).items
278
+ end
281
279
 
282
- ##
283
- # Determines a list of existing Google Compute firewalls
284
- #
285
- # @return [Array[Google::Apis::ComputeV1::Firewall]]
286
- #
287
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
288
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
289
- # @raise [Google::Apis::AuthorizationError] Authorization is required
290
- def list_firewalls
291
- @compute.list_firewalls(@options[:gce_project],
292
- filter: 'name != default-allow-internal AND name != default-ssh').items
293
- end
280
+ ##
281
+ # Determines a list of existing Google Compute disks
282
+ #
283
+ # @param [Integer] start The time when we started code execution, it is
284
+ # compared to Time.now to determine how many further code execution
285
+ # attempts remain
286
+ #
287
+ # @return [Array[Google::Apis::ComputeV1::Disk]]
288
+ #
289
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
290
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
291
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
292
+ def list_disks
293
+ @compute.list_disks(@options[:gce_project], default_zone).items
294
+ end
294
295
 
295
- ##
296
- # Create a Google Compute firewall
297
- #
298
- # @param [String] name The name of the firewall to create
299
- #
300
- # @param [::Google::Apis::ComputeV1::Network] network The Google Compute networkin which to create
301
- # the firewall
302
- #
303
- # @param [Array<String>] allow List of ports to allow through the firewall. One of 'allow' or 'deny' must be specified, but not both.
304
- #
305
- # @param [Array<String>] deny List of ports to deny through the firewall. One of 'allow' or 'deny' must be specified, but not both.
306
- #
307
- # @param [Array<String>] source_ranges List of ranges in CIDR format to accept through the firewall. If neither 'source_ranges'
308
- # or 'source_tags' is specified, GCP adds a default 'source_range' of '0.0.0.0/0' (allow all)
309
- #
310
- # @param [Array<String>] source_tags List of network tags to accept through the firewall. If neither 'source_ranges'
311
- # or 'source_tags' is specified, GCP adds a default 'source_range' of '0.0.0.0/0' (allow all)
312
- #
313
- # @param [Array<String>] target_ranges List of ranges in CIDR format to apply this firewall. If neither 'target_ranges'
314
- # or 'target_tags' is specified, the firewall applies to all hosts in the VPC
315
- #
316
- # @param [Array<String>] target_tags List of network tags to apply this firewall. If neither 'target_ranges'
317
- # or 'target_tags' is specified, the firewall applies to all hosts in the VPC
318
- #
319
- # @return [Google::Apis::ComputeV1::Operation]
320
- #
321
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
322
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
323
- # @raise [Google::Apis::AuthorizationError] Authorization is required
324
- def create_firewall(name, network, allow: [], deny: [], source_ranges: [], source_tags: [], target_ranges: [], target_tags: [])
325
- allowed = []
326
- allow.each do |port|
327
- parts = port.split('/', 2)
328
- if parts[1] == 'tcp' || parts[1] == 'udp' || parts[1] == 'sctp' then
329
- allowed << ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: parts[1], ports: [parts[0]])
330
- else
331
- allowed << ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: parts[1])
332
- end
296
+ ##
297
+ # Determines a list of existing Google Compute firewalls
298
+ #
299
+ # @return [Array[Google::Apis::ComputeV1::Firewall]]
300
+ #
301
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
302
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
303
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
304
+ def list_firewalls
305
+ @compute.list_firewalls(@options[:gce_project],
306
+ filter: 'name != default-allow-internal AND name != default-ssh').items
333
307
  end
334
- denied = []
335
- deny.each do |port|
336
- parts = port.split('/', 2)
337
- if parts[1] == 'tcp' || parts[1] == 'udp' || parts[1] == 'sctp' then
338
- denied << ::Google::Apis::ComputeV1::Firewall::Denied.new(ip_protocol: parts[1], ports: [parts[0]])
339
- else
340
- denied << ::Google::Apis::ComputeV1::Firewall::Denied.new(ip_protocol: parts[1])
308
+
309
+ ##
310
+ # Create a Google Compute firewall
311
+ #
312
+ # @param [String] name The name of the firewall to create
313
+ #
314
+ # @param [::Google::Apis::ComputeV1::Network] network The Google Compute networkin which to create
315
+ # the firewall
316
+ #
317
+ # @param [Array<String>] allow List of ports to allow through the firewall. One of 'allow' or 'deny' must be
318
+ # specified, but not both.
319
+ #
320
+ # @param [Array<String>] deny List of ports to deny through the firewall. One of 'allow' or 'deny' must be
321
+ # specified, but not both.
322
+ #
323
+ # @param [Array<String>] source_ranges List of ranges in CIDR format to accept through the firewall. If neither
324
+ # 'source_ranges' or 'source_tags' is specified, GCP adds a default 'source_range' of '0.0.0.0/0' (allow all)
325
+ #
326
+ # @param [Array<String>] source_tags List of network tags to accept through the firewall. If neither 'source_ranges'
327
+ # or 'source_tags' is specified, GCP adds a default 'source_range' of '0.0.0.0/0' (allow all)
328
+ #
329
+ # @param [Array<String>] target_ranges List of ranges in CIDR format to apply this firewall. If neither
330
+ # 'target_ranges' or 'target_tags' is specified, the firewall applies to all hosts in the VPC
331
+ #
332
+ # @param [Array<String>] target_tags List of network tags to apply this firewall. If neither 'target_ranges' or
333
+ # 'target_tags' is specified, the firewall applies to all hosts in the VPC
334
+ #
335
+ # @return [Google::Apis::ComputeV1::Operation]
336
+ #
337
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
338
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
339
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
340
+ def create_firewall(name, network, allow: [], deny: [], source_ranges: [], source_tags: [], target_ranges: [],
341
+ target_tags: [])
342
+ allowed = []
343
+ allow.each do |port|
344
+ parts = port.split('/', 2)
345
+ allowed << if %w[tcp udp sctp].include?(parts[1])
346
+ ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: parts[1], ports: [parts[0]])
347
+ else
348
+ ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: parts[1])
349
+ end
341
350
  end
351
+ denied = []
352
+ deny.each do |port|
353
+ parts = port.split('/', 2)
354
+ denied << if %w[tcp udp sctp].include?(parts[1])
355
+ ::Google::Apis::ComputeV1::Firewall::Denied.new(ip_protocol: parts[1], ports: [parts[0]])
356
+ else
357
+ ::Google::Apis::ComputeV1::Firewall::Denied.new(ip_protocol: parts[1])
358
+ end
359
+ end
360
+
361
+ firewall_object = ::Google::Apis::ComputeV1::Firewall.new(
362
+ name: name,
363
+ direction: 'INGRESS',
364
+ network: network.self_link,
365
+ allowed: allowed,
366
+ denied: denied,
367
+ source_ranges: source_ranges,
368
+ source_tags: source_tags,
369
+ target_ranges: target_ranges,
370
+ target_tags: target_tags,
371
+ )
372
+ operation = @compute.insert_firewall(@options[:gce_project], firewall_object)
373
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
342
374
  end
343
375
 
344
- firewall_object = ::Google::Apis::ComputeV1::Firewall.new(
345
- name: name,
346
- direction: 'INGRESS',
347
- network: network.self_link,
348
- allowed: allowed,
349
- denied: denied,
350
- source_ranges: source_ranges,
351
- source_tags: source_tags,
352
- target_ranges: target_ranges,
353
- target_tags: target_tags,
354
- )
355
- operation = @compute.insert_firewall(@options[:gce_project], firewall_object)
356
- @compute.wait_global_operation(@options[:gce_project], operation.name)
357
- end
376
+ ##
377
+ # Get the named firewall
378
+ #
379
+ # @param [String] name The name of the firewall
380
+ #
381
+ # @return [Google::Apis::ComputeV1::Firewall]
382
+ #
383
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
384
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
385
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
386
+ def get_firewall(name)
387
+ @compute.get_firewall(@options[:gce_project], name)
388
+ end
358
389
 
359
- ##
360
- # Get the named firewall
361
- #
362
- # @param [String] name The name of the firewall
363
- #
364
- # @return [Google::Apis::ComputeV1::Firewall]
365
- #
366
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
367
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
368
- # @raise [Google::Apis::AuthorizationError] Authorization is required
369
- def get_firewall(name)
370
- firewall = @compute.get_firewall(@options[:gce_project], name)
371
- end
390
+ ##
391
+ # Add a source range to the firewall.
392
+ #
393
+ # @param [String] name The name of the firewall
394
+ #
395
+ # @param [String] range The IP range in CIDR format to add to the firewall
396
+ #
397
+ # @return [Google::Apis::ComputeV1::Operation]
398
+ #
399
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
400
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
401
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
402
+ def add_firewall_source_range(name, range)
403
+ firewall = get_firewall(name)
404
+ firewall.source_ranges = [] if firewall.source_ranges.nil?
405
+ firewall.source_ranges << range
406
+ operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
407
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
408
+ end
372
409
 
373
- ##
374
- # Add a source range to the firewall.
375
- #
376
- # @param [String] name The name of the firewall
377
- #
378
- # @param [String] range The IP range in CIDR format to add to the firewall
379
- #
380
- # @return [Google::Apis::ComputeV1::Operation]
381
- #
382
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
383
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
384
- # @raise [Google::Apis::AuthorizationError] Authorization is required
385
- def add_firewall_source_range(name, range)
386
- firewall = get_firewall(name)
387
- firewall.source_ranges = [] if firewall.source_ranges.nil?
388
- firewall.source_ranges << range
389
- operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
390
- @compute.wait_global_operation(@options[:gce_project], operation.name)
391
- end
410
+ ##
411
+ # Add an allowed port to the firewall
412
+ #
413
+ # @param [String] name The name of the firewall
414
+ #
415
+ # @param [String] port The port number to open on the firewall
416
+ #
417
+ # @param [String] proto The protocol of the port. This should be 'tcp' or 'udp'
418
+ #
419
+ # @return [Google::Apis::ComputeV1::Operation]
420
+ #
421
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
422
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
423
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
424
+ def add_firewall_port(name, port, proto)
425
+ firewall = get_firewall(name)
426
+ firewall.allowed = [] if firewall.allowed.nil?
427
+ firewall.allowed << ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: proto, ports: [port])
428
+ operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
429
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
430
+ end
392
431
 
393
- ##
394
- # Add an allowed port to the firewall
395
- #
396
- # @param [String] name The name of the firewall
397
- #
398
- # @param [String] port The port number to open on the firewall
399
- #
400
- # @param [String] proto The protocol of the port. This should be 'tcp' or 'udp'
401
- #
402
- # @return [Google::Apis::ComputeV1::Operation]
403
- #
404
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
405
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
406
- # @raise [Google::Apis::AuthorizationError] Authorization is required
407
- def add_firewall_port(name, port, proto)
408
- firewall = get_firewall(name)
409
- firewall.allowed = [] if firewall.allowed.nil?
410
- firewall.allowed << ::Google::Apis::ComputeV1::Firewall::Allowed.new(ip_protocol: proto, ports: [port])
411
- operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
412
- @compute.wait_global_operation(@options[:gce_project], operation.name)
413
- end
432
+ ##
433
+ # Add a taget_tag to an existing firewall
434
+ #
435
+ # @param [String] the name of the firewall to update
436
+ #
437
+ # @param [String] tag The target tag to add to the firewall
438
+ #
439
+ # @return [Google::Apis::ComputeV1::Operation]
440
+ #
441
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
442
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
443
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
444
+ def add_firewall_target_tag(name, tag)
445
+ firewall = @compute.get_firewall(@options[:gce_project], name)
446
+ firewall.target_tags = [] if firewall.target_tags.nil?
447
+ firewall.target_tags << tag
448
+ operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
449
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
450
+ end
414
451
 
415
- ##
416
- # Add a taget_tag to an existing firewall
417
- #
418
- # @param [String] the name of the firewall to update
419
- #
420
- # @param [String] tag The target tag to add to the firewall
421
- #
422
- # @return [Google::Apis::ComputeV1::Operation]
423
- #
424
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
425
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
426
- # @raise [Google::Apis::AuthorizationError] Authorization is required
427
- def add_firewall_target_tag(name, tag)
428
- firewall = @compute.get_firewall(@options[:gce_project], name)
429
- firewall.target_tags = [] if firewall.target_tags.nil?
430
- firewall.target_tags << tag
431
- operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
432
- @compute.wait_global_operation(@options[:gce_project], operation.name)
433
- end
452
+ ##
453
+ # Add a source_tag to an existing firewall
454
+ #
455
+ # @param [String] the name of the firewall to update
456
+ #
457
+ # @param [String] tag The source tag to add to the firewall
458
+ #
459
+ # @return [Google::Apis::ComputeV1::Operation]
460
+ #
461
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
462
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
463
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
464
+ def add_firewall_source_tag(name, tag)
465
+ firewall = @compute.get_firewall(@options[:gce_project], name)
466
+ firewall.source_tags = [] if firewall.source_tags.nil?
467
+ firewall.source_tags << tag
468
+ operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
469
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
470
+ end
434
471
 
435
- ##
436
- # Add a source_tag to an existing firewall
437
- #
438
- # @param [String] the name of the firewall to update
439
- #
440
- # @param [String] tag The source tag to add to the firewall
441
- #
442
- # @return [Google::Apis::ComputeV1::Operation]
443
- #
444
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
445
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
446
- # @raise [Google::Apis::AuthorizationError] Authorization is required
447
- def add_firewall_source_tag(name, tag)
448
- firewall = @compute.get_firewall(@options[:gce_project], name)
449
- firewall.source_tags = [] if firewall.source_tags.nil?
450
- firewall.source_tags << tag
451
- operation = @compute.patch_firewall(@options[:gce_project], name, firewall)
452
- @compute.wait_global_operation(@options[:gce_project], operation.name)
453
- end
472
+ ##
473
+ # Create a Google Compute disk
474
+ #
475
+ # @param [String] name The name of the disk to create
476
+ #
477
+ # @param [String] img The existing disk image to clone for this image
478
+ # or nil to create a blank disk
479
+ #
480
+ # @return [Google::Apis::ComputeV1::Operation]
481
+ #
482
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
483
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
484
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
485
+ def create_disk(name, size, img = nil)
486
+ new_disk = ::Google::Apis::ComputeV1::Disk.new(
487
+ name: name,
488
+ size_gb: size,
489
+ source_image: img,
490
+ )
491
+ operation = @compute.insert_disk(@options[:gce_project], @options[:gce_zone], new_disk)
492
+ @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
493
+ end
454
494
 
455
- ##
456
- # Create a Google Compute disk
457
- #
458
- # @param [String] name The name of the disk to create
459
- #
460
- # @param [String] img The existing disk image to clone for this image
461
- # or nil to create a blank disk
462
- #
463
- # @return [Google::Apis::ComputeV1::Operation]
464
- #
465
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
466
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
467
- # @raise [Google::Apis::AuthorizationError] Authorization is required
468
- def create_disk(name, size, img = nil)
469
- new_disk = ::Google::Apis::ComputeV1::Disk.new(
470
- name: name,
471
- size_gb: size,
472
- source_image: img,
473
- )
474
- operation = @compute.insert_disk(@options[:gce_project], @options[:gce_zone], new_disk)
475
- @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
476
- end
495
+ ##
496
+ # Create a Google Compute instance
497
+ #
498
+ # @param [String] name The name of the instance to create
499
+ #
500
+ # @param [Google::Apis::ComputeV1::Image] img The Google Compute image to use for instance creation
501
+ #
502
+ # @param [Google::Apis::ComputeV1::MachineType] machine_type The Google Compute Machine Type
503
+ #
504
+ # @param [Integer] disk_size The size of the boot disk for the new instance. Must be equal to or
505
+ # greater than the image disk's size
506
+ #
507
+ # @param [String] hostname The custom hostname to set in the OS of the instance
508
+ #
509
+ # @return [Google::Apis::ComputeV1::Operation]
510
+ #
511
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
512
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
513
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
514
+ def create_instance(name, img, machine_type, disk_size, hostname)
515
+ initialize_params = ::Google::Apis::ComputeV1::AttachedDiskInitializeParams.new(
516
+ disk_size_gb: disk_size,
517
+ source_image: img.self_link,
518
+ )
519
+ disk_params = ::Google::Apis::ComputeV1::AttachedDisk.new(
520
+ boot: true,
521
+ auto_delete: true,
522
+ initialize_params: initialize_params,
523
+ )
524
+ # attached_network = ::Google::Apis::ComputeV1::networkInterfaces.new()
525
+ tags = ::Google::Apis::ComputeV1::Tags.new(
526
+ items: [name],
527
+ )
528
+ network_interface = ::Google::Apis::ComputeV1::NetworkInterface.new(
529
+ network: get_network(default_network).self_link,
530
+ subnetwork: @compute.get_subnetwork(@options[:gce_project], default_region, default_subnetwork).self_link,
531
+ # Create an AccessConfig to add a NAT IP to the host.
532
+ # TODO: Make this configurable
533
+ access_configs: [
534
+ ::Google::Apis::ComputeV1::AccessConfig.new(
535
+ network_tier: 'STANDARD',
536
+ ),
537
+ ],
538
+ )
539
+
540
+ instance_opts = {
541
+ machine_type: machine_type.self_link,
542
+ name: name,
543
+ disks: [disk_params],
544
+ network_interfaces: [network_interface],
545
+ tags: tags,
546
+ }
547
+
548
+ # use custom hostname if specified
549
+ if hostname && ENV.fetch('BEAKER_set_gce_hostname', false)
550
+ # The google api requires an FQDN for the custom hostname
551
+ valid_hostname = hostname.include?('.') ? hostname : "#{hostname}.beaker.test"
552
+ instance_opts[:hostname] = valid_hostname
553
+ end
477
554
 
478
- ##
479
- # Create a Google Compute instance
480
- #
481
- # @param [String] name The name of the instance to create
482
- #
483
- # @param [Google::Apis::ComputeV1::Image] img The Google Compute image to use for instance creation
484
- #
485
- # @param [Google::Apis::ComputeV1::MachineType] machine_type The Google Compute Machine Type
486
- #
487
- # @param [Integer] disk_size The size of the boot disk for the new instance. Must be equal to or
488
- # greater than the image disk's size
489
- #
490
- # @param [String] hostname The custom hostname to set in the OS of the instance
491
- #
492
- # @return [Google::Apis::ComputeV1::Operation]
493
- #
494
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
495
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
496
- # @raise [Google::Apis::AuthorizationError] Authorization is required
497
- def create_instance(name, img, machine_type, disk_size, hostname)
498
- initialize_params = ::Google::Apis::ComputeV1::AttachedDiskInitializeParams.new(
499
- disk_size_gb: disk_size,
500
- source_image: img.self_link,
501
- )
502
- disk_params = ::Google::Apis::ComputeV1::AttachedDisk.new(
503
- boot: true,
504
- auto_delete: true,
505
- initialize_params: initialize_params,
506
- )
507
- # attached_network = ::Google::Apis::ComputeV1::networkInterfaces.new()
508
- tags = ::Google::Apis::ComputeV1::Tags.new(
509
- items: [name],
510
- )
511
- network_interface = ::Google::Apis::ComputeV1::NetworkInterface.new(
512
- network: get_network(default_network).self_link,
513
- subnetwork: @compute.get_subnetwork(@options[:gce_project], default_region, default_subnetwork).self_link,
514
- # Create an AccessConfig to add a NAT IP to the host.
515
- # TODO: Make this configurable
516
- access_configs: [
517
- ::Google::Apis::ComputeV1::AccessConfig.new(
518
- network_tier: 'STANDARD',
519
- ),
520
- ],
521
- )
522
-
523
- instance_opts = {
524
- :machine_type => machine_type.self_link,
525
- :name => name,
526
- :disks => [disk_params],
527
- :network_interfaces => [network_interface],
528
- :tags => tags,
529
- }
530
-
531
- # use custom hostname if specified
532
- if hostname && ENV.fetch('BEAKER_set_gce_hostname', false)
533
- # The google api requires an FQDN for the custom hostname
534
- hostname.include?('.') ? valid_hostname = hostname : valid_hostname = hostname + '.beaker.test'
535
- instance_opts[:hostname] = valid_hostname
536
- end
537
-
538
- new_instance = ::Google::Apis::ComputeV1::Instance.new(instance_opts)
555
+ new_instance = ::Google::Apis::ComputeV1::Instance.new(**instance_opts)
539
556
 
540
- operation = @compute.insert_instance(@options[:gce_project], @options[:gce_zone], new_instance)
541
- @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
542
- end
557
+ operation = @compute.insert_instance(@options[:gce_project], @options[:gce_zone], new_instance)
558
+ @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
559
+ end
543
560
 
544
- ##
545
- # Get the named instace from Google Compute Image
546
- #
547
- # @param [String] name The name of the instance
548
- #
549
- # @return [Google::Apis::ComputeV1::Instance]
550
- #
551
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
552
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
553
- # @raise [Google::Apis::AuthorizationError] Authorization is required
554
- def get_instance(name)
555
- @compute.get_instance(@options[:gce_project], @options[:gce_zone], name)
556
- end
561
+ ##
562
+ # Get the named instace from Google Compute Image
563
+ #
564
+ # @param [String] name The name of the instance
565
+ #
566
+ # @return [Google::Apis::ComputeV1::Instance]
567
+ #
568
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
569
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
570
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
571
+ def get_instance(name)
572
+ @compute.get_instance(@options[:gce_project], @options[:gce_zone], name)
573
+ end
557
574
 
558
- ##
559
- # Add a tag to a Google Compute Instance
560
- #
561
- # @param [String] name The name of the instance
562
- #
563
- # @param [String] tag The tag to add to the instance
564
- #
565
- # @return [Google::Apis::ComputeV1::Operation]
566
- #
567
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
568
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
569
- # @raise [Google::Apis::AuthorizationError] Authorization is required
570
- def add_instance_tag(name, tag)
571
- instance = get_instance(name)
572
- tags = instance.tags
573
- tags.items << tag
574
- operation = @compute.set_instance_tags(@options[:gce_project], @options[:gce_zone], name, tags)
575
- @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
576
- end
575
+ ##
576
+ # Add a tag to a Google Compute Instance
577
+ #
578
+ # @param [String] name The name of the instance
579
+ #
580
+ # @param [String] tag The tag to add to the instance
581
+ #
582
+ # @return [Google::Apis::ComputeV1::Operation]
583
+ #
584
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
585
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
586
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
587
+ def add_instance_tag(name, tag)
588
+ instance = get_instance(name)
589
+ tags = instance.tags
590
+ tags.items << tag
591
+ operation = @compute.set_instance_tags(@options[:gce_project], @options[:gce_zone], name, tags)
592
+ @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
593
+ end
577
594
 
578
- ##
579
- # Set key/value metadata pairs to a Google Compute instance
580
- #
581
- # This function replaces any existing items in the metadata hash!
582
- #
583
- # @param [String] name The name of the instance to set metadata
584
- #
585
- # @param [String] data An array of hashes to set ass metadata. Each array
586
- # item should have a 'key' and 'value' key.
587
- #
588
- # @return [Google::Apis::ComputeV1::Operation]
589
- #
590
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
591
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
592
- # @raise [Google::Apis::AuthorizationError] Authorization is required
593
- def set_metadata_on_instance(name, data)
594
- instance = @compute.get_instance(@options[:gce_project], @options[:gce_zone], name)
595
- mdata = instance.metadata.dup
596
- mdata.items = data
597
- operation = @compute.set_instance_metadata(@options[:gce_project], @options[:gce_zone], name, mdata)
598
- @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
599
- end
595
+ ##
596
+ # Set key/value metadata pairs to a Google Compute instance
597
+ #
598
+ # This function replaces any existing items in the metadata hash!
599
+ #
600
+ # @param [String] name The name of the instance to set metadata
601
+ #
602
+ # @param [String] data An array of hashes to set ass metadata. Each array
603
+ # item should have a 'key' and 'value' key.
604
+ #
605
+ # @return [Google::Apis::ComputeV1::Operation]
606
+ #
607
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
608
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
609
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
610
+ def set_metadata_on_instance(name, data)
611
+ instance = @compute.get_instance(@options[:gce_project], @options[:gce_zone], name)
612
+ mdata = instance.metadata.dup
613
+ mdata.items = data
614
+ operation = @compute.set_instance_metadata(@options[:gce_project], @options[:gce_zone], name, mdata)
615
+ @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
616
+ end
600
617
 
601
- ##
602
- # Delete a Google Compute instance
603
- #
604
- # @param [String] name The name of the instance to delete
605
- #
606
- # @return [Google::Apis::ComputeV1::Operation]
607
- #
608
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
609
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
610
- # @raise [Google::Apis::AuthorizationError] Authorization is required
611
- def delete_instance(name)
612
- operation = @compute.delete_instance(@options[:gce_project], default_zone, name)
613
- @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
614
- end
618
+ ##
619
+ # Delete a Google Compute instance
620
+ #
621
+ # @param [String] name The name of the instance to delete
622
+ #
623
+ # @return [Google::Apis::ComputeV1::Operation]
624
+ #
625
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
626
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
627
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
628
+ def delete_instance(name)
629
+ operation = @compute.delete_instance(@options[:gce_project], default_zone, name)
630
+ @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
631
+ end
615
632
 
616
- ##
617
- # Delete a Google Compute disk
618
- #
619
- # @param [String] name The name of the disk to delete
620
- #
621
- # @return [Google::Apis::ComputeV1::Operation]
622
- #
623
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
624
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
625
- # @raise [Google::Apis::AuthorizationError] Authorization is required
626
- def delete_disk(name)
627
- operation = @compute.delete_disk(@options[:gce_project], default_zone, name)
628
- @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
629
- end
633
+ ##
634
+ # Delete a Google Compute disk
635
+ #
636
+ # @param [String] name The name of the disk to delete
637
+ #
638
+ # @return [Google::Apis::ComputeV1::Operation]
639
+ #
640
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
641
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
642
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
643
+ def delete_disk(name)
644
+ operation = @compute.delete_disk(@options[:gce_project], default_zone, name)
645
+ @compute.wait_zone_operation(@options[:gce_project], @options[:gce_zone], operation.name)
646
+ end
630
647
 
631
- ##
632
- # Delete a Google Compute firewall
633
- #
634
- # @param [String] name The name of the firewall to delete
635
- #
636
- # @return [Google::Apis::ComputeV1::Operation]
637
- #
638
- # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
639
- # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
640
- # @raise [Google::Apis::AuthorizationError] Authorization is required
641
- def delete_firewall(name)
642
- operation = @compute.delete_firewall(@options[:gce_project], name)
643
- @compute.wait_global_operation(@options[:gce_project], operation.name)
648
+ ##
649
+ # Delete a Google Compute firewall
650
+ #
651
+ # @param [String] name The name of the firewall to delete
652
+ #
653
+ # @return [Google::Apis::ComputeV1::Operation]
654
+ #
655
+ # @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried
656
+ # @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification
657
+ # @raise [Google::Apis::AuthorizationError] Authorization is required
658
+ def delete_firewall(name)
659
+ operation = @compute.delete_firewall(@options[:gce_project], name)
660
+ @compute.wait_global_operation(@options[:gce_project], operation.name)
661
+ end
644
662
  end
645
663
  end