foreman_google 3.0.7 → 3.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +0 -15
- data/app/assets/javascripts/foreman_google/locale/cs_CZ/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/de/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/el/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/en/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/en_GB/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/es/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/fr/foreman_google.js +8 -2
- data/app/assets/javascripts/foreman_google/locale/it/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/ja/foreman_google.js +8 -2
- data/app/assets/javascripts/foreman_google/locale/ka/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/ko/foreman_google.js +8 -2
- data/app/assets/javascripts/foreman_google/locale/pl/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/pt_BR/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/ru/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/sv_SE/foreman_google.js +7 -1
- data/app/assets/javascripts/foreman_google/locale/zh_CN/foreman_google.js +8 -2
- data/app/assets/javascripts/foreman_google/locale/zh_TW/foreman_google.js +7 -1
- data/app/lib/google_cloud_compute/compute_attributes.rb +3 -1
- data/app/models/foreman_google/google_compute.rb +2 -2
- data/lib/foreman_google/version.rb +1 -1
- data/locale/cs_CZ/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/cs_CZ/foreman_google.po +7 -1
- data/locale/de/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/de/foreman_google.po +7 -1
- data/locale/el/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/el/foreman_google.po +7 -1
- data/locale/en/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/en/foreman_google.po +7 -1
- data/locale/en_GB/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/en_GB/foreman_google.po +7 -1
- data/locale/es/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/es/foreman_google.po +7 -1
- data/locale/foreman_google.pot +12 -4
- data/locale/fr/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/fr/foreman_google.po +9 -3
- data/locale/it/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/it/foreman_google.po +7 -1
- data/locale/ja/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/ja/foreman_google.po +9 -3
- data/locale/ka/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/ka/foreman_google.po +7 -1
- data/locale/ko/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/ko/foreman_google.po +9 -3
- data/locale/pl/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/pl/foreman_google.po +7 -1
- data/locale/pt_BR/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/pt_BR/foreman_google.po +7 -1
- data/locale/ru/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/ru/foreman_google.po +7 -1
- data/locale/sv_SE/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/sv_SE/foreman_google.po +7 -1
- data/locale/zh_CN/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/zh_CN/foreman_google.po +9 -3
- data/locale/zh_TW/LC_MESSAGES/foreman_google.mo +0 -0
- data/locale/zh_TW/foreman_google.po +7 -1
- data/test/controllers/foreman_google/api/v2/compute_resources_extensions_test.rb +51 -0
- data/test/models/concerns/foreman_google/host_managed_extensions_test.rb +46 -0
- data/test/models/foreman_google/gce_test.rb +275 -3
- data/test/models/foreman_google/google_compute_test.rb +193 -4
- data/test/unit/foreman_google/google_compute_adapter_test.rb +59 -7
- data/test/unit/google_cloud_compute/compute_attributes_test.rb +235 -0
- data/test/unit/google_cloud_compute/compute_collection_test.rb +78 -0
- data/test/unit/google_extensions/attached_disk_test.rb +35 -0
- metadata +10 -30
|
@@ -194,20 +194,209 @@ module ForemanGoogle
|
|
|
194
194
|
|
|
195
195
|
it '@network' do
|
|
196
196
|
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
197
|
-
|
|
197
|
+
assert_equal 'default', cr.network
|
|
198
198
|
|
|
199
199
|
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: { network: 'my-network' })
|
|
200
|
-
|
|
200
|
+
assert_equal 'my-network', cr.network
|
|
201
201
|
end
|
|
202
202
|
|
|
203
203
|
it '@zone' do
|
|
204
204
|
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
205
|
-
|
|
205
|
+
assert_equal zone, cr.zone
|
|
206
206
|
end
|
|
207
207
|
|
|
208
208
|
it '@zone_name' do
|
|
209
209
|
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, instance: instance)
|
|
210
|
-
|
|
210
|
+
assert_equal zone, cr.zone_name
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
describe '#status' do
|
|
214
|
+
it 'returns status when persisted' do
|
|
215
|
+
instance.status = 'RUNNING'
|
|
216
|
+
client.expects(:instance).with(zone, identity).returns(instance)
|
|
217
|
+
assert_equal 'RUNNING', subject.status
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it 'returns false when not persisted' do
|
|
221
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
222
|
+
assert_not cr.status
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
describe '#state' do
|
|
227
|
+
it 'is an alias for status' do
|
|
228
|
+
instance.status = 'TERMINATED'
|
|
229
|
+
client.expects(:instance).with(zone, identity).returns(instance)
|
|
230
|
+
assert_equal subject.status, subject.state
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
describe '#start' do
|
|
235
|
+
it 'delegates to client.start when persisted' do
|
|
236
|
+
client.stubs(:instance).with(zone, identity).returns(instance)
|
|
237
|
+
client.expects(:start).with(zone, identity).returns(true)
|
|
238
|
+
subject.start
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it 'raises when not persisted' do
|
|
242
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
243
|
+
assert_raises(Foreman::Exception) { cr.start }
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
describe '#stop' do
|
|
248
|
+
it 'delegates to client.stop when persisted' do
|
|
249
|
+
client.stubs(:instance).with(zone, identity).returns(instance)
|
|
250
|
+
client.expects(:stop).with(zone, identity).returns(true)
|
|
251
|
+
subject.stop
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it 'raises when not persisted' do
|
|
255
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
256
|
+
assert_raises(Foreman::Exception) { cr.stop }
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
describe '#to_s' do
|
|
261
|
+
it 'returns the name' do
|
|
262
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: { name: 'my-vm' })
|
|
263
|
+
assert_equal 'my-vm', cr.to_s
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
describe '#interfaces' do
|
|
268
|
+
it 'returns network_interfaces' do
|
|
269
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
270
|
+
assert_equal cr.network_interfaces, cr.interfaces
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
describe '#vm_description' do
|
|
275
|
+
it 'delegates to pretty_machine_type' do
|
|
276
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, instance: instance)
|
|
277
|
+
assert_equal cr.pretty_machine_type, cr.vm_description
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
describe '#vm_ip_address - no network interfaces' do
|
|
282
|
+
it 'returns nil' do
|
|
283
|
+
empty_instance = OpenStruct.new(
|
|
284
|
+
name: 'instance', network_interfaces: [],
|
|
285
|
+
creation_timestamp: Time.zone.now, zone: zone,
|
|
286
|
+
machine_type: 'machineTypes/e2-micro'
|
|
287
|
+
)
|
|
288
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, instance: empty_instance)
|
|
289
|
+
assert_nil cr.vm_ip_address
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
describe '#private_ip_address - no network interfaces' do
|
|
294
|
+
it 'returns nil' do
|
|
295
|
+
empty_instance = OpenStruct.new(
|
|
296
|
+
name: 'instance', network_interfaces: [],
|
|
297
|
+
creation_timestamp: Time.zone.now, zone: zone,
|
|
298
|
+
machine_type: 'machineTypes/e2-micro'
|
|
299
|
+
)
|
|
300
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, instance: empty_instance)
|
|
301
|
+
assert_nil cr.private_ip_address
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
describe '#pretty_image_name - no disks' do
|
|
306
|
+
it 'returns nil' do
|
|
307
|
+
instance.disks = []
|
|
308
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, instance: instance)
|
|
309
|
+
assert_nil cr.pretty_image_name
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
describe '#ip_addresses' do
|
|
314
|
+
it 'returns public and private IP' do
|
|
315
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, instance: instance)
|
|
316
|
+
assert_equal ['1.2.3.4', '10.10.10.23'], cr.ip_addresses
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
describe '#serial_port_output' do
|
|
321
|
+
it 'delegates to client' do
|
|
322
|
+
client.stubs(:instance).with(zone, identity).returns(instance)
|
|
323
|
+
client.expects(:serial_port_output).with(zone, identity).returns(OpenStruct.new(contents: 'boot log'))
|
|
324
|
+
assert_equal 'boot log', subject.serial_port_output
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
it 'returns nil when client returns nil' do
|
|
328
|
+
client.stubs(:instance).with(zone, identity).returns(instance)
|
|
329
|
+
client.expects(:serial_port_output).with(zone, identity).returns(nil)
|
|
330
|
+
assert_nil subject.serial_port_output
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
describe '#volumes_attributes=' do
|
|
335
|
+
it 'is a no-op' do
|
|
336
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
337
|
+
cr.volumes_attributes = { '0' => { size_gb: 10 } }
|
|
338
|
+
assert cr.volumes.any?
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
describe '#reload - without identity' do
|
|
343
|
+
it 'returns nil' do
|
|
344
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
345
|
+
assert_nil cr.reload
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
describe '#create_volumes' do
|
|
350
|
+
it 'inserts disks and waits for READY' do
|
|
351
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: { volumes: [{ size_gb: '20' }] })
|
|
352
|
+
|
|
353
|
+
client.expects(:insert_disk).with(zone, cr.volumes.first.insert_attrs)
|
|
354
|
+
client.expects(:disk).with(zone, cr.volumes.first.device_name).returns(OpenStruct.new(status: 'READY'))
|
|
355
|
+
client.expects(:wait_for).yields.returns({ duration: 1 })
|
|
356
|
+
|
|
357
|
+
cr.create_volumes
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
describe '#destroy_volumes' do
|
|
362
|
+
it 'deletes each volume disk' do
|
|
363
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: { volumes: [{ size_gb: '20' }] })
|
|
364
|
+
client.expects(:delete_disk).with(zone, cr.volumes.first.device_name)
|
|
365
|
+
cr.destroy_volumes
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
describe '#create_instance' do
|
|
370
|
+
it 'calls insert_instance via ComputeAttributes' do
|
|
371
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: { name: 'test-vm', machine_type: 'e2-micro' })
|
|
372
|
+
client.expects(:insert_instance).with(zone, has_key(:name))
|
|
373
|
+
cr.create_instance
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
describe '#set_disk_auto_delete' do
|
|
378
|
+
it 'delegates to client' do
|
|
379
|
+
args = { name: 'my-vm' }
|
|
380
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, args: args)
|
|
381
|
+
client.expects(:set_disk_auto_delete).with(zone, 'my-vm')
|
|
382
|
+
cr.set_disk_auto_delete
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
describe '#wait_for' do
|
|
387
|
+
it 'delegates to client.wait_for' do
|
|
388
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone)
|
|
389
|
+
client.expects(:wait_for).yields.returns({ duration: 0 })
|
|
390
|
+
result = cr.wait_for { true }
|
|
391
|
+
assert_equal({ duration: 0 }, result)
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
describe '#public_ip_address' do
|
|
396
|
+
it 'is an alias for vm_ip_address' do
|
|
397
|
+
cr = ForemanGoogle::GoogleCompute.new(client: client, zone: zone, instance: instance)
|
|
398
|
+
assert_equal cr.vm_ip_address, cr.public_ip_address
|
|
399
|
+
end
|
|
211
400
|
end
|
|
212
401
|
end
|
|
213
402
|
end
|
|
@@ -131,7 +131,7 @@ module ForemanGoogle
|
|
|
131
131
|
|
|
132
132
|
result = subject.insert_instance('us-east1-b', args)
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
assert_equal 'insert', result.operation.operation_type
|
|
135
135
|
assert_includes result.operation.target_link, 'foreman-test-google'
|
|
136
136
|
end
|
|
137
137
|
|
|
@@ -156,14 +156,14 @@ module ForemanGoogle
|
|
|
156
156
|
stub_request(:post, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/instances/instance_name/start')
|
|
157
157
|
.to_return(status: 200, body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'instance_start.json')))
|
|
158
158
|
result = subject.start('us-east1-b', 'instance_name')
|
|
159
|
-
|
|
159
|
+
assert_equal 'start', result.operation.operation_type
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
it '#stop' do
|
|
163
163
|
stub_request(:post, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/instances/instance_name/stop')
|
|
164
164
|
.to_return(status: 200, body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'instance_stop.json')))
|
|
165
165
|
result = subject.stop('us-east1-b', 'instance_name')
|
|
166
|
-
|
|
166
|
+
assert_equal 'stop', result.operation.operation_type
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
it '#set_disk_auto_delete' do
|
|
@@ -174,7 +174,7 @@ module ForemanGoogle
|
|
|
174
174
|
.to_return(status: 200, body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'instance_set_disk_auto_delete.json')))
|
|
175
175
|
result = subject.set_disk_auto_delete('us-east1-b', 'instance_name')
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
assert_equal 'instance-1', result[0].device_name
|
|
178
178
|
assert result[0].auto_delete
|
|
179
179
|
end
|
|
180
180
|
end
|
|
@@ -186,14 +186,14 @@ module ForemanGoogle
|
|
|
186
186
|
|
|
187
187
|
result = subject.insert_disk('us-east1-b', { name: 'foreman-disk1', size_gb: 23 })
|
|
188
188
|
assert_includes result.operation.target_link, 'foreman-disk1'
|
|
189
|
-
|
|
189
|
+
assert_equal 'insert', result.operation.operation_type
|
|
190
190
|
end
|
|
191
191
|
|
|
192
192
|
it '#get' do
|
|
193
193
|
stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/disks/foreman-disk1')
|
|
194
194
|
.to_return(status: 200, body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'disks_get.json')))
|
|
195
195
|
result = subject.disk('us-east1-b', 'foreman-disk1')
|
|
196
|
-
|
|
196
|
+
assert_equal 'foreman-disk1', result.name
|
|
197
197
|
end
|
|
198
198
|
|
|
199
199
|
it '#delete' do
|
|
@@ -202,7 +202,59 @@ module ForemanGoogle
|
|
|
202
202
|
result = subject.delete_disk('us-east1-b', 'foreman-disk1')
|
|
203
203
|
|
|
204
204
|
assert_includes result.operation.target_link, 'foreman-disk1'
|
|
205
|
-
|
|
205
|
+
assert_equal 'delete', result.operation.operation_type
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
describe '#delete_instance' do
|
|
210
|
+
it 'deletes an instance' do
|
|
211
|
+
stub_request(:delete, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/instances/instance_name')
|
|
212
|
+
.to_return(status: 200, body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'instance_stop.json')))
|
|
213
|
+
result = subject.delete_instance('us-east1-b', 'instance_name')
|
|
214
|
+
assert_equal 'stop', result.operation.operation_type
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
describe '#image' do
|
|
219
|
+
setup do
|
|
220
|
+
stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/global/images')
|
|
221
|
+
.to_return(body: File.read(File.join(__dir__, '..', '..', 'fixtures', 'images_coastal.json')))
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it 'finds image by numeric id' do
|
|
225
|
+
subject.stub(:all_projects, []) do
|
|
226
|
+
result = subject.image(1)
|
|
227
|
+
assert_equal 'coastal-image', result.name
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'returns nil when image not found' do
|
|
232
|
+
subject.stub(:all_projects, []) do
|
|
233
|
+
assert_nil subject.image(999)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
describe '#serial_port_output' do
|
|
239
|
+
it 'returns serial port output' do
|
|
240
|
+
body = { contents: 'boot log output', next: 12_345, start: 0, selfLink: 'self-link' }.to_json
|
|
241
|
+
stub_request(:get, 'https://compute.googleapis.com/compute/v1/projects/coastal-haven-123456/zones/us-east1-b/instances/instance_name/serialPort')
|
|
242
|
+
.to_return(status: 200, body: body)
|
|
243
|
+
result = subject.serial_port_output('us-east1-b', 'instance_name')
|
|
244
|
+
assert_equal 'boot log output', result.contents
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
describe '#project_id' do
|
|
249
|
+
it 'returns the project_id from auth JSON' do
|
|
250
|
+
assert_equal 'coastal-haven-123456', subject.project_id
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
describe '#wait_for' do
|
|
255
|
+
it 'returns immediately when block yields true' do
|
|
256
|
+
result = subject.wait_for { true }
|
|
257
|
+
assert result[:duration] <= 1
|
|
206
258
|
end
|
|
207
259
|
end
|
|
208
260
|
end
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
require 'test_google_helper'
|
|
2
|
+
|
|
3
|
+
module GoogleCloudCompute
|
|
4
|
+
class ComputeAttributesTest < GoogleTestCase
|
|
5
|
+
let(:client) { mock('GoogleAdapter') }
|
|
6
|
+
subject { GoogleCloudCompute::ComputeAttributes.new(client) }
|
|
7
|
+
|
|
8
|
+
setup do
|
|
9
|
+
client.stubs(:project_id).returns('my-project')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe '#for_new' do
|
|
13
|
+
describe 'name handling' do
|
|
14
|
+
it 'generates a default name with foreman- prefix when name is nil' do
|
|
15
|
+
result = subject.for_new({})
|
|
16
|
+
assert_match(/\Aforeman-\d+\z/, result[:name])
|
|
17
|
+
assert_equal result[:name], result[:hostname]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'parameterizes the provided name' do
|
|
21
|
+
result = subject.for_new(name: 'My VM Name')
|
|
22
|
+
assert_equal 'my-vm-name', result[:name]
|
|
23
|
+
assert_equal 'my-vm-name', result[:hostname]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe 'network handling' do
|
|
28
|
+
it 'defaults to default network' do
|
|
29
|
+
result = subject.for_new({})
|
|
30
|
+
assert_equal 'default', result[:network]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'uses custom network name' do
|
|
34
|
+
result = subject.for_new(network: 'custom-net')
|
|
35
|
+
assert_equal 'custom-net', result[:network]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'builds full URL without external IP' do
|
|
39
|
+
result = subject.for_new(network: 'default')
|
|
40
|
+
expected_url = 'https://compute.googleapis.com/compute/v1/projects/my-project/global/networks/default'
|
|
41
|
+
assert_equal expected_url, result[:network_interfaces][0][:network]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'adds NAT access config with external IP' do
|
|
45
|
+
result = subject.for_new(associate_external_ip: '1')
|
|
46
|
+
nic = result[:network_interfaces][0]
|
|
47
|
+
assert_equal 'global/networks/default', nic[:network]
|
|
48
|
+
assert_equal [{ name: 'External NAT', type: 'ONE_TO_ONE_NAT' }], nic[:access_configs]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'uses custom network interfaces with external IP' do
|
|
52
|
+
result = subject.for_new(
|
|
53
|
+
associate_external_ip: '1',
|
|
54
|
+
network_interfaces: [{ network: 'global/networks/my-net' }]
|
|
55
|
+
)
|
|
56
|
+
nic = result[:network_interfaces][0]
|
|
57
|
+
assert_equal 'global/networks/my-net', nic[:network]
|
|
58
|
+
assert_equal [{ name: 'External NAT', type: 'ONE_TO_ONE_NAT' }], nic[:access_configs]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe 'associate_external_ip boolean casting' do
|
|
63
|
+
it 'casts string 1 to true' do
|
|
64
|
+
result = subject.for_new(associate_external_ip: '1')
|
|
65
|
+
assert result[:associate_external_ip]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'casts string 0 to false' do
|
|
69
|
+
result = subject.for_new(associate_external_ip: '0')
|
|
70
|
+
assert_not result[:associate_external_ip]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'defaults to false when absent' do
|
|
74
|
+
result = subject.for_new({})
|
|
75
|
+
assert_not result[:associate_external_ip]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe 'volume construction' do
|
|
80
|
+
it 'creates a default 20 GB disk when no volumes' do
|
|
81
|
+
result = subject.for_new({})
|
|
82
|
+
assert_equal 1, result[:volumes].length
|
|
83
|
+
assert_equal 20, result[:volumes].first.disk_size_gb
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'creates volumes with custom size' do
|
|
87
|
+
result = subject.for_new(volumes: [{ size_gb: '50' }])
|
|
88
|
+
assert_equal 50, result[:volumes].first.disk_size_gb
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'sets source image on first volume when image_id is provided' do
|
|
92
|
+
image = OpenStruct.new(id: 1, self_link: 'projects/my-project/global/images/centos-7')
|
|
93
|
+
client.stubs(:image).with(1).returns(image)
|
|
94
|
+
|
|
95
|
+
result = subject.for_new(
|
|
96
|
+
volumes: [{ size_gb: '20' }, { size_gb: '30' }],
|
|
97
|
+
image_id: '1'
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
assert_equal 'projects/my-project/global/images/centos-7', result[:volumes][0].source
|
|
101
|
+
assert_empty result[:volumes][1].source
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'names disks sequentially' do
|
|
105
|
+
result = subject.for_new(name: 'test-vm', volumes: [{ size_gb: '20' }, { size_gb: '30' }])
|
|
106
|
+
assert_equal 'test-vm-disk1', result[:volumes][0].device_name
|
|
107
|
+
assert_equal 'test-vm-disk2', result[:volumes][1].device_name
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'accepts disk_size_gb as an alternative key' do
|
|
111
|
+
result = subject.for_new(volumes: [{ disk_size_gb: '40' }])
|
|
112
|
+
assert_equal 40, result[:volumes].first.disk_size_gb
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe 'metadata construction' do
|
|
117
|
+
it 'includes ssh-keys' do
|
|
118
|
+
result = subject.for_new(username: 'gce_user', public_key: 'ssh-rsa AAAA')
|
|
119
|
+
ssh_item = result[:metadata][:items].find { |i| i[:key] == 'ssh-keys' }
|
|
120
|
+
assert_equal 'gce_user:ssh-rsa AAAA', ssh_item[:value]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'includes user-data when present' do
|
|
124
|
+
result = subject.for_new(username: 'user', public_key: 'key', user_data: '#cloud-config')
|
|
125
|
+
ud_item = result[:metadata][:items].find { |i| i[:key] == 'user-data' }
|
|
126
|
+
assert_equal '#cloud-config', ud_item[:value]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'omits user-data when blank' do
|
|
130
|
+
result = subject.for_new(username: 'user', public_key: 'key')
|
|
131
|
+
keys = result[:metadata][:items].map { |i| i[:key] }
|
|
132
|
+
assert_not_includes keys, 'user-data'
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'passes through machine_type and image_id' do
|
|
137
|
+
result = subject.for_new(machine_type: 'e2-micro', image_id: '42')
|
|
138
|
+
assert_equal 'e2-micro', result[:machine_type]
|
|
139
|
+
assert_equal '42', result[:image_id]
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
describe '#for_create' do
|
|
144
|
+
let(:instance) do
|
|
145
|
+
vol1 = Google::Cloud::Compute::V1::AttachedDisk.new(device_name: 'vm-disk1')
|
|
146
|
+
vol2 = Google::Cloud::Compute::V1::AttachedDisk.new(device_name: 'vm-disk2')
|
|
147
|
+
OpenStruct.new(
|
|
148
|
+
name: 'test-vm',
|
|
149
|
+
zone: 'us-east1-b',
|
|
150
|
+
machine_type: 'e2-micro',
|
|
151
|
+
volumes: [vol1, vol2],
|
|
152
|
+
network_interfaces: [{ network: 'global/networks/default' }],
|
|
153
|
+
metadata: { items: [{ key: 'ssh-keys', value: 'user:key' }] }
|
|
154
|
+
)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'builds machine_type URL from zone' do
|
|
158
|
+
result = subject.for_create(instance)
|
|
159
|
+
assert_equal 'zones/us-east1-b/machineTypes/e2-micro', result[:machine_type]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it 'builds disk source paths' do
|
|
163
|
+
result = subject.for_create(instance)
|
|
164
|
+
assert_equal 'zones/us-east1-b/disks/vm-disk1', result[:disks][0][:source]
|
|
165
|
+
assert_equal 'zones/us-east1-b/disks/vm-disk2', result[:disks][1][:source]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'marks first disk as boot' do
|
|
169
|
+
result = subject.for_create(instance)
|
|
170
|
+
assert result[:disks][0][:boot]
|
|
171
|
+
assert_not result[:disks][1][:boot]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'includes network_interfaces and metadata' do
|
|
175
|
+
result = subject.for_create(instance)
|
|
176
|
+
assert_equal instance.network_interfaces, result[:network_interfaces]
|
|
177
|
+
assert_equal instance.metadata, result[:metadata]
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'includes name' do
|
|
181
|
+
result = subject.for_create(instance)
|
|
182
|
+
assert_equal 'test-vm', result[:name]
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe '#for_instance' do
|
|
187
|
+
let(:nics) do
|
|
188
|
+
[OpenStruct.new(network: 'projects/my-project/global/networks/custom', network_i_p: '10.0.0.1')]
|
|
189
|
+
end
|
|
190
|
+
let(:instance) do
|
|
191
|
+
OpenStruct.new(
|
|
192
|
+
name: 'existing-vm',
|
|
193
|
+
creation_timestamp: Time.zone.parse('2024-01-15 10:00:00'),
|
|
194
|
+
zone: 'projects/my-project/zones/us-west1-a',
|
|
195
|
+
machine_type: 'zones/us-west1-a/machineTypes/n1-standard-1',
|
|
196
|
+
network_interfaces: nics,
|
|
197
|
+
disks: [OpenStruct.new(device_name: 'disk1')],
|
|
198
|
+
metadata: { items: [] }
|
|
199
|
+
)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'extracts zone_name from full zone URL' do
|
|
203
|
+
result = subject.for_instance(instance)
|
|
204
|
+
assert_equal 'us-west1-a', result[:zone_name]
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it 'extracts network name from full URL' do
|
|
208
|
+
result = subject.for_instance(instance)
|
|
209
|
+
assert_equal 'custom', result[:network]
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it 'converts creation_timestamp to DateTime' do
|
|
213
|
+
result = subject.for_instance(instance)
|
|
214
|
+
assert_kind_of DateTime, result[:creation_timestamp]
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'passes through name and hostname' do
|
|
218
|
+
result = subject.for_instance(instance)
|
|
219
|
+
assert_equal 'existing-vm', result[:name]
|
|
220
|
+
assert_equal 'existing-vm', result[:hostname]
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it 'passes through disks as volumes and metadata' do
|
|
224
|
+
result = subject.for_instance(instance)
|
|
225
|
+
assert_equal instance.disks, result[:volumes]
|
|
226
|
+
assert_equal instance.metadata, result[:metadata]
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it 'passes through machine_type' do
|
|
230
|
+
result = subject.for_instance(instance)
|
|
231
|
+
assert_equal instance.machine_type, result[:machine_type]
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'test_google_helper'
|
|
2
|
+
|
|
3
|
+
module GoogleCloudCompute
|
|
4
|
+
class ComputeCollectionTest < GoogleTestCase
|
|
5
|
+
let(:client) { mock('GoogleAdapter') }
|
|
6
|
+
let(:zone) { 'us-east1-b' }
|
|
7
|
+
|
|
8
|
+
setup do
|
|
9
|
+
client.stubs(:project_id).returns('project_id')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'with instances' do
|
|
13
|
+
let(:instances) do
|
|
14
|
+
nics = [OpenStruct.new(access_configs: [OpenStruct.new(nat_i_p: '1.2.3.4')],
|
|
15
|
+
network: 'projects/project_id/global/networks/default', network_i_p: '10.0.0.1')]
|
|
16
|
+
[
|
|
17
|
+
OpenStruct.new(id: 1, name: 'vm-1', network_interfaces: nics,
|
|
18
|
+
creation_timestamp: Time.zone.now, zone: zone, machine_type: 'machineTypes/e2-micro'),
|
|
19
|
+
OpenStruct.new(id: 2, name: 'vm-2', network_interfaces: nics,
|
|
20
|
+
creation_timestamp: Time.zone.now, zone: zone, machine_type: 'machineTypes/e2-small'),
|
|
21
|
+
]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
setup do
|
|
25
|
+
client.stubs(:instances).with(zone).returns(instances)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'wraps instances as GoogleCompute objects' do
|
|
29
|
+
collection = GoogleCloudCompute::ComputeCollection.new(client, zone)
|
|
30
|
+
collection.each do |vm|
|
|
31
|
+
assert_kind_of ForemanGoogle::GoogleCompute, vm
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'iterates via each' do
|
|
36
|
+
collection = GoogleCloudCompute::ComputeCollection.new(client, zone)
|
|
37
|
+
names = collection.map(&:name)
|
|
38
|
+
assert_equal %w[vm-1 vm-2], names
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns all VMs via all' do
|
|
42
|
+
collection = GoogleCloudCompute::ComputeCollection.new(client, zone)
|
|
43
|
+
assert_equal 2, collection.all.length
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'is Enumerable' do
|
|
47
|
+
collection = GoogleCloudCompute::ComputeCollection.new(client, zone)
|
|
48
|
+
assert_kind_of Enumerable, collection
|
|
49
|
+
assert_equal 2, collection.count
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe 'with empty instance list' do
|
|
54
|
+
setup do
|
|
55
|
+
client.stubs(:instances).with(zone).returns([])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'returns empty collection' do
|
|
59
|
+
collection = GoogleCloudCompute::ComputeCollection.new(client, zone)
|
|
60
|
+
assert_empty collection.all
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'iterates zero times' do
|
|
64
|
+
collection = GoogleCloudCompute::ComputeCollection.new(client, zone)
|
|
65
|
+
count = 0
|
|
66
|
+
collection.each { count += 1 }
|
|
67
|
+
assert_equal 0, count
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe 'with attrs' do
|
|
72
|
+
it 'passes attrs to client.instances' do
|
|
73
|
+
client.expects(:instances).with(zone, filter: 'name = "test"').returns([])
|
|
74
|
+
GoogleCloudCompute::ComputeCollection.new(client, zone, filter: 'name = "test"')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -12,6 +12,41 @@ module GoogleExtensions
|
|
|
12
12
|
disk = Google::Cloud::Compute::V1::AttachedDisk.new
|
|
13
13
|
assert_empty disk.insert_attrs[:source_image]
|
|
14
14
|
end
|
|
15
|
+
|
|
16
|
+
it 'includes device_name as name' do
|
|
17
|
+
disk = Google::Cloud::Compute::V1::AttachedDisk.new(device_name: 'boot-disk', disk_size_gb: 30)
|
|
18
|
+
attrs = disk.insert_attrs
|
|
19
|
+
assert_equal 'boot-disk', attrs[:name]
|
|
20
|
+
assert_equal 30, attrs[:size_gb]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#size_gb' do
|
|
25
|
+
it 'returns disk_size_gb' do
|
|
26
|
+
disk = Google::Cloud::Compute::V1::AttachedDisk.new(disk_size_gb: 50)
|
|
27
|
+
assert_equal 50, disk.size_gb
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '#persisted?' do
|
|
32
|
+
it 'returns nil' do
|
|
33
|
+
disk = Google::Cloud::Compute::V1::AttachedDisk.new
|
|
34
|
+
assert_nil disk.persisted?
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe '#id' do
|
|
39
|
+
it 'returns nil' do
|
|
40
|
+
disk = Google::Cloud::Compute::V1::AttachedDisk.new
|
|
41
|
+
assert_nil disk.id
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#_delete' do
|
|
46
|
+
it 'returns nil' do
|
|
47
|
+
disk = Google::Cloud::Compute::V1::AttachedDisk.new
|
|
48
|
+
assert_nil disk._delete
|
|
49
|
+
end
|
|
15
50
|
end
|
|
16
51
|
end
|
|
17
52
|
end
|