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