cloud-mu 3.1.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +21 -13
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +4 -4
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +147 -37
- data/cloud-mu.gemspec +22 -20
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +158 -111
- data/modules/mu/adoption.rb +404 -71
- data/modules/mu/cleanup.rb +221 -306
- data/modules/mu/cloud.rb +129 -1633
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +926 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +169 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +10 -9
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +5 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +19 -10
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +10 -21
- data/modules/mu/config/ref.rb +411 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +98 -71
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +71 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +91 -68
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +43 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +410 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +218 -2612
- data/modules/mu/mommacat/daemon.rb +403 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +380 -122
- data/modules/mu/{clouds → providers}/aws/alarm.rb +7 -5
- data/modules/mu/{clouds → providers}/aws/bucket.rb +297 -59
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +37 -71
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +26 -25
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +724 -744
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +88 -70
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +220 -247
- data/modules/mu/{clouds → providers}/aws/folder.rb +8 -8
- data/modules/mu/{clouds → providers}/aws/function.rb +300 -142
- data/modules/mu/{clouds → providers}/aws/group.rb +31 -29
- data/modules/mu/{clouds → providers}/aws/habitat.rb +18 -15
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +66 -56
- data/modules/mu/{clouds → providers}/aws/log.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +29 -19
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +114 -16
- data/modules/mu/{clouds → providers}/aws/notifier.rb +142 -65
- data/modules/mu/{clouds → providers}/aws/role.rb +158 -118
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +201 -59
- data/modules/mu/{clouds → providers}/aws/server.rb +844 -1139
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +74 -65
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +26 -44
- data/modules/mu/{clouds → providers}/aws/user.rb +24 -25
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +525 -931
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +97 -49
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +68 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +85 -78
- data/modules/mu/{clouds → providers}/google/database.rb +11 -21
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +140 -168
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +19 -21
- data/modules/mu/{clouds → providers}/google/role.rb +94 -58
- data/modules/mu/{clouds → providers}/google/server.rb +243 -156
- data/modules/mu/{clouds → providers}/google/server_pool.rb +26 -45
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +103 -79
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +2 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +240 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
- data/modules/mu/clouds/aws/endpoint.rb +0 -592
|
@@ -87,7 +87,7 @@ module MU
|
|
|
87
87
|
img = fetchImage(image_id, credentials: credentials)
|
|
88
88
|
return DateTime.new if img.nil?
|
|
89
89
|
return DateTime.parse(img.creation_timestamp)
|
|
90
|
-
rescue ::Google::Apis::ClientError
|
|
90
|
+
rescue ::Google::Apis::ClientError
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
return DateTime.new
|
|
@@ -164,19 +164,26 @@ module MU
|
|
|
164
164
|
def self.diskConfig(config, create = true, disk_as_url = true, credentials: nil)
|
|
165
165
|
disks = []
|
|
166
166
|
if config['image_id'].nil? and config['basis'].nil?
|
|
167
|
-
pp config.keys
|
|
168
167
|
raise MuError, "Can't generate disk configuration for server #{config['name']} without an image ID or basis specified"
|
|
169
168
|
end
|
|
170
169
|
|
|
171
170
|
img = fetchImage(config['image_id'] || config['basis']['launch_config']['image_id'], credentials: credentials)
|
|
172
171
|
|
|
173
|
-
#
|
|
172
|
+
# if img.source_disk and img.source_disk.match(/projects\/([^\/]+)\/zones\/([^\/]+)\/disks\/(.*)/)
|
|
173
|
+
# _junk, proj, az, name = Regexp.last_match
|
|
174
|
+
# disk_desc = MU::Cloud::Google.compute(credentials: credentials).get_disk(proj, az, name)
|
|
175
|
+
# pp disk_desc
|
|
176
|
+
# raise "nah"
|
|
177
|
+
# end
|
|
178
|
+
|
|
174
179
|
disktype = "projects/#{config['project']}/zones/#{config['availability_zone']}/diskTypes/pd-standard"
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
disktype.gsub!(/.*?\/([^\/])$/, '\1') if !disk_as_url
|
|
183
|
+
|
|
177
184
|
imageobj = MU::Cloud::Google.compute(:AttachedDiskInitializeParams).new(
|
|
178
185
|
source_image: img.self_link,
|
|
179
|
-
disk_size_gb:
|
|
186
|
+
disk_size_gb: img.disk_size_gb,
|
|
180
187
|
disk_type: disktype,
|
|
181
188
|
)
|
|
182
189
|
disks << MU::Cloud::Google.compute(:AttachedDisk).new(
|
|
@@ -247,15 +254,22 @@ next if !create
|
|
|
247
254
|
subnet_cfg = config['vpc']['subnets'].sample
|
|
248
255
|
|
|
249
256
|
end
|
|
257
|
+
|
|
250
258
|
subnet = vpc.getSubnet(name: subnet_cfg['subnet_name'], cloud_id: subnet_cfg['subnet_id'])
|
|
251
259
|
if subnet.nil?
|
|
252
|
-
|
|
260
|
+
if config['vpc']['name']
|
|
261
|
+
subnet = vpc.getSubnet(name: config['vpc']['name']+subnet_cfg['subnet_name'], cloud_id: subnet_cfg['subnet_id'])
|
|
262
|
+
end
|
|
263
|
+
if subnet.nil?
|
|
264
|
+
raise MuError, "Couldn't find subnet details for #{subnet_cfg['subnet_name'] || subnet_cfg['subnet_id']} while configuring Server #{config['name']} (VPC: #{vpc.mu_name})"
|
|
265
|
+
end
|
|
253
266
|
end
|
|
254
267
|
|
|
255
268
|
base_iface_obj = {
|
|
256
269
|
:network => vpc.url,
|
|
257
270
|
:subnetwork => subnet.url
|
|
258
271
|
}
|
|
272
|
+
|
|
259
273
|
if config['associate_public_ip']
|
|
260
274
|
base_iface_obj[:access_configs] = [
|
|
261
275
|
MU::Cloud::Google.compute(:AccessConfig).new
|
|
@@ -322,7 +336,7 @@ next if !create
|
|
|
322
336
|
end
|
|
323
337
|
metadata["startup-script"] = @userdata if @userdata and !@userdata.empty?
|
|
324
338
|
|
|
325
|
-
deploykey = @config[
|
|
339
|
+
deploykey = @config["ssh_user"]+":"+@deploy.ssh_public_key
|
|
326
340
|
if metadata["ssh-keys"]
|
|
327
341
|
metadata["ssh-keys"] += "\n"+deploykey
|
|
328
342
|
else
|
|
@@ -348,7 +362,7 @@ next if !create
|
|
|
348
362
|
desc[:labels]["name"] = @mu_name.downcase
|
|
349
363
|
|
|
350
364
|
if @config['network_tags'] and @config['network_tags'].size > 0
|
|
351
|
-
desc[:tags] =
|
|
365
|
+
desc[:tags] = MU::Cloud::Google.compute(:Tags).new(
|
|
352
366
|
items: @config['network_tags']
|
|
353
367
|
)
|
|
354
368
|
end
|
|
@@ -369,7 +383,7 @@ next if !create
|
|
|
369
383
|
sleep 10
|
|
370
384
|
end
|
|
371
385
|
rescue ::Google::Apis::ClientError => e
|
|
372
|
-
MU.log e.message, MU::ERR
|
|
386
|
+
MU.log e.message+" inserting instance into #{@project_id}/#{@config['availability_zone']}", MU::ERR, details: instanceobj
|
|
373
387
|
raise e
|
|
374
388
|
end while @cloud_id.nil?
|
|
375
389
|
|
|
@@ -394,7 +408,7 @@ next if !create
|
|
|
394
408
|
|
|
395
409
|
notify
|
|
396
410
|
|
|
397
|
-
rescue
|
|
411
|
+
rescue StandardError => e
|
|
398
412
|
if !cloud_desc.nil? and !done
|
|
399
413
|
MU.log "Aborted before I could finish setting up #{@config['name']}, cleaning it up. Stack trace will print once cleanup is complete.", MU::WARN if !@deploy.nocleanup
|
|
400
414
|
MU::MommaCat.unlockAll
|
|
@@ -445,7 +459,7 @@ next if !create
|
|
|
445
459
|
)
|
|
446
460
|
begin
|
|
447
461
|
sleep 5
|
|
448
|
-
end while cloud_desc.status != "TERMINATED" # means STOPPED
|
|
462
|
+
end while cloud_desc(use_cache: false).status != "TERMINATED" # means STOPPED
|
|
449
463
|
end
|
|
450
464
|
|
|
451
465
|
# Ask the Google API to start this node
|
|
@@ -462,30 +476,30 @@ next if !create
|
|
|
462
476
|
end
|
|
463
477
|
|
|
464
478
|
# Ask the Google API to restart this node
|
|
465
|
-
#
|
|
466
|
-
def reboot(
|
|
479
|
+
# @param _hard [Boolean]: [IGNORED] Force a stop/start. This is the only available way to restart an instance in Google, so this flag is ignored.
|
|
480
|
+
def reboot(_hard = false)
|
|
467
481
|
return if @cloud_id.nil?
|
|
468
|
-
|
|
482
|
+
stop
|
|
483
|
+
start
|
|
469
484
|
end
|
|
470
485
|
|
|
471
486
|
# Figure out what's needed to SSH into this server.
|
|
472
487
|
# @return [Array<String>]: nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name, alternate_names
|
|
473
488
|
def getSSHConfig
|
|
474
|
-
|
|
489
|
+
describe(cloud_id: @cloud_id)
|
|
475
490
|
# XXX add some awesome alternate names from metadata and make sure they end
|
|
476
491
|
# up in MU::MommaCat's ssh config wangling
|
|
477
|
-
ssh_keydir = Etc.getpwuid(Process.uid).dir+"/.ssh"
|
|
478
492
|
return nil if @config.nil? or @deploy.nil?
|
|
479
493
|
|
|
480
494
|
nat_ssh_key = nat_ssh_user = nat_ssh_host = nil
|
|
481
|
-
if !@config["vpc"].nil? and !MU::Cloud
|
|
495
|
+
if !@config["vpc"].nil? and !MU::Cloud.resourceClass("Google", "VPC").haveRouteToInstance?(cloud_desc, credentials: @config['credentials'])
|
|
482
496
|
|
|
483
497
|
if !@nat.nil?
|
|
484
498
|
if @nat.cloud_desc.nil?
|
|
485
499
|
MU.log "NAT was missing cloud descriptor when called in #{@mu_name}'s getSSHConfig", MU::ERR
|
|
486
500
|
return nil
|
|
487
501
|
end
|
|
488
|
-
|
|
502
|
+
_foo, _bar, _baz, nat_ssh_host, nat_ssh_user, nat_ssh_key = @nat.getSSHConfig
|
|
489
503
|
if nat_ssh_user.nil? and !nat_ssh_host.nil?
|
|
490
504
|
MU.log "#{@config["name"]} (#{MU.deploy_id}) is configured to use #{@config['vpc']} NAT #{nat_ssh_host}, but username isn't specified. Guessing root.", MU::ERR, details: caller
|
|
491
505
|
nat_ssh_user = "root"
|
|
@@ -495,7 +509,8 @@ next if !create
|
|
|
495
509
|
|
|
496
510
|
if @config['ssh_user'].nil?
|
|
497
511
|
if windows?
|
|
498
|
-
@config['ssh_user'] =
|
|
512
|
+
@config['ssh_user'] = @config['windows_admin_user']
|
|
513
|
+
@config['ssh_user'] ||= "Administrator"
|
|
499
514
|
else
|
|
500
515
|
@config['ssh_user'] = "root"
|
|
501
516
|
end
|
|
@@ -512,26 +527,24 @@ next if !create
|
|
|
512
527
|
@cloud_id = instance_id
|
|
513
528
|
end
|
|
514
529
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
node, config, deploydata = describe(cloud_id: @cloud_id)
|
|
530
|
+
node, _config, deploydata = describe(cloud_id: @cloud_id)
|
|
518
531
|
instance = cloud_desc
|
|
519
532
|
raise MuError, "Couldn't find instance of #{@mu_name} (#{@cloud_id})" if !instance
|
|
520
533
|
return false if !MU::MommaCat.lock(@cloud_id+"-orchestrate", true)
|
|
521
534
|
return false if !MU::MommaCat.lock(@cloud_id+"-groom", true)
|
|
522
535
|
|
|
523
536
|
# MU::Cloud::AWS.createStandardTags(@cloud_id, region: @config['region'])
|
|
524
|
-
# MU::
|
|
537
|
+
# MU::Cloud::AWS.createTag(@cloud_id, "Name", node, region: @config['region'])
|
|
525
538
|
#
|
|
526
539
|
# if @config['optional_tags']
|
|
527
540
|
# MU::MommaCat.listOptionalTags.each { |key, value|
|
|
528
|
-
# MU::
|
|
541
|
+
# MU::Cloud::AWS.createTag(@cloud_id, key, value, region: @config['region'])
|
|
529
542
|
# }
|
|
530
543
|
# end
|
|
531
544
|
#
|
|
532
545
|
# if !@config['tags'].nil?
|
|
533
546
|
# @config['tags'].each { |tag|
|
|
534
|
-
# MU::
|
|
547
|
+
# MU::Cloud::AWS.createTag(@cloud_id, tag['key'], tag['value'], region: @config['region'])
|
|
535
548
|
# }
|
|
536
549
|
# end
|
|
537
550
|
# MU.log "Tagged #{node} (#{@cloud_id}) with MU-ID=#{MU.deploy_id}", MU::DEBUG
|
|
@@ -609,8 +622,8 @@ next if !create
|
|
|
609
622
|
@named = true
|
|
610
623
|
end
|
|
611
624
|
|
|
612
|
-
|
|
613
|
-
if !nat_ssh_host and !MU::Cloud
|
|
625
|
+
_nat_ssh_key, _nat_ssh_user, nat_ssh_host, _canonical_ip, _ssh_user, _ssh_key_name = getSSHConfig
|
|
626
|
+
if !nat_ssh_host and !MU::Cloud.resourceClass("Google", "VPC").haveRouteToInstance?(cloud_desc, credentials: @config['credentials'])
|
|
614
627
|
# XXX check if canonical_ip is in the private ranges
|
|
615
628
|
# raise MuError, "#{node} has no NAT host configured, and I have no other route to it"
|
|
616
629
|
end
|
|
@@ -641,8 +654,8 @@ next if !create
|
|
|
641
654
|
# Locate an existing instance or instances and return an array containing matching AWS resource descriptors for those that match.
|
|
642
655
|
# @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching instances
|
|
643
656
|
def self.find(**args)
|
|
644
|
-
args
|
|
645
|
-
|
|
657
|
+
args = MU::Cloud::Google.findLocationArgs(args)
|
|
658
|
+
|
|
646
659
|
if !args[:region].nil? and MU::Cloud::Google.listRegions.include?(args[:region])
|
|
647
660
|
regions = [args[:region]]
|
|
648
661
|
else
|
|
@@ -720,9 +733,6 @@ next if !create
|
|
|
720
733
|
# Return a description of this resource appropriate for deployment
|
|
721
734
|
# metadata. Arguments reflect the return values of the MU::Cloud::[Resource].describe method
|
|
722
735
|
def notify
|
|
723
|
-
node, config, deploydata = describe(cloud_id: @cloud_id, update_cache: true)
|
|
724
|
-
deploydata = {} if deploydata.nil?
|
|
725
|
-
|
|
726
736
|
if cloud_desc.nil?
|
|
727
737
|
raise MuError, "Failed to load instance metadata for #{@config['mu_name']}/#{@cloud_id}"
|
|
728
738
|
end
|
|
@@ -783,7 +793,7 @@ next if !create
|
|
|
783
793
|
|
|
784
794
|
MU::MommaCat.lock(@cloud_id+"-groom")
|
|
785
795
|
|
|
786
|
-
node,
|
|
796
|
+
node, _config, deploydata = describe(cloud_id: @cloud_id)
|
|
787
797
|
|
|
788
798
|
if node.nil? or node.empty?
|
|
789
799
|
raise MuError, "MU::Cloud::Google::Server.groom was called without a mu_name"
|
|
@@ -798,29 +808,6 @@ next if !create
|
|
|
798
808
|
|
|
799
809
|
# punchAdminNAT
|
|
800
810
|
|
|
801
|
-
# MU::Cloud::AWS::Server.tagVolumes(@cloud_id)
|
|
802
|
-
|
|
803
|
-
# If we have a loadbalancer configured, attach us to it
|
|
804
|
-
# if !@config['loadbalancers'].nil?
|
|
805
|
-
# if @loadbalancers.nil?
|
|
806
|
-
# raise MuError, "#{@mu_name} is configured to use LoadBalancers, but none have been loaded by dependencies()"
|
|
807
|
-
# end
|
|
808
|
-
# @loadbalancers.each { |lb|
|
|
809
|
-
# lb.registerNode(@cloud_id)
|
|
810
|
-
# }
|
|
811
|
-
# end
|
|
812
|
-
|
|
813
|
-
# Let us into any databases we depend on.
|
|
814
|
-
# This is probelmtic with autscaling - old ips are not removed, and access to the database can easily be given at the BoK level
|
|
815
|
-
# if @dependencies.has_key?("database")
|
|
816
|
-
# @dependencies['database'].values.each { |db|
|
|
817
|
-
# db.allowHost(@deploydata["private_ip_address"]+"/32")
|
|
818
|
-
# if @deploydata["public_ip_address"]
|
|
819
|
-
# db.allowHost(@deploydata["public_ip_address"]+"/32")
|
|
820
|
-
# end
|
|
821
|
-
# }
|
|
822
|
-
# end
|
|
823
|
-
|
|
824
811
|
@groomer.saveDeployData
|
|
825
812
|
|
|
826
813
|
begin
|
|
@@ -859,9 +846,9 @@ next if !create
|
|
|
859
846
|
project: @project_id,
|
|
860
847
|
exclude_storage: img_cfg['image_exclude_storage'],
|
|
861
848
|
make_public: img_cfg['public'],
|
|
862
|
-
tags: @
|
|
849
|
+
tags: @tags,
|
|
863
850
|
zone: @config['availability_zone'],
|
|
864
|
-
family:
|
|
851
|
+
family: img_cfg['family'],
|
|
865
852
|
credentials: @config['credentials']
|
|
866
853
|
)
|
|
867
854
|
@deploy.notify("images", @config['name'], {"image_id" => image_id})
|
|
@@ -897,50 +884,50 @@ next if !create
|
|
|
897
884
|
raise MuError, "Failed to find instance '#{instance_id}' in createImage"
|
|
898
885
|
end
|
|
899
886
|
|
|
900
|
-
labels = {
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
end
|
|
905
|
-
}
|
|
887
|
+
labels = Hash[tags.keys.map { |k|
|
|
888
|
+
[k.downcase, tags[k].downcase.gsub(/[^-_a-z0-9]/, '-')] }
|
|
889
|
+
]
|
|
890
|
+
labels["name"] = name
|
|
906
891
|
|
|
907
892
|
bootdisk = nil
|
|
908
893
|
threads = []
|
|
909
894
|
parent_thread_id = Thread.current.object_id
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
Thread.
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
diskname = disk.source.gsub(/.*?\//, "")
|
|
922
|
-
MU.log "Creating snapshot of #{diskname} in #{zone}", MU::NOTICE, details: snapobj
|
|
923
|
-
snap = MU::Cloud::Google.compute(credentials: credentials).create_disk_snapshot(
|
|
924
|
-
project,
|
|
925
|
-
zone,
|
|
926
|
-
diskname,
|
|
927
|
-
snapobj
|
|
928
|
-
)
|
|
929
|
-
MU::Cloud::Google.compute(credentials: credentials).set_snapshot_labels(
|
|
930
|
-
project,
|
|
931
|
-
snap.name,
|
|
932
|
-
MU::Cloud::Google.compute(:GlobalSetLabelsRequest).new(
|
|
933
|
-
label_fingerprint: snap.label_fingerprint,
|
|
934
|
-
labels: labels.merge({
|
|
935
|
-
"mu-device-name" => disk.device_name,
|
|
936
|
-
"mu-parent-image" => name,
|
|
937
|
-
"mu-orig-zone" => zone
|
|
938
|
-
})
|
|
895
|
+
if !exclude_storage
|
|
896
|
+
instance[instance_id].disks.each { |disk|
|
|
897
|
+
threads << Thread.new {
|
|
898
|
+
Thread.abort_on_exception = false
|
|
899
|
+
MU.dupGlobals(parent_thread_id)
|
|
900
|
+
if disk.boot
|
|
901
|
+
bootdisk = disk.source
|
|
902
|
+
else
|
|
903
|
+
snapobj = MU::Cloud::Google.compute(:Snapshot).new(
|
|
904
|
+
name: name+"-"+disk.device_name,
|
|
905
|
+
description: "Mu image created from #{name} (#{disk.device_name})"
|
|
939
906
|
)
|
|
940
|
-
|
|
941
|
-
|
|
907
|
+
diskname = disk.source.gsub(/.*?\//, "")
|
|
908
|
+
MU.log "Creating snapshot of #{diskname} in #{zone}", MU::NOTICE, details: snapobj
|
|
909
|
+
snap = MU::Cloud::Google.compute(credentials: credentials).create_disk_snapshot(
|
|
910
|
+
project,
|
|
911
|
+
zone,
|
|
912
|
+
diskname,
|
|
913
|
+
snapobj
|
|
914
|
+
)
|
|
915
|
+
MU::Cloud::Google.compute(credentials: credentials).set_snapshot_labels(
|
|
916
|
+
project,
|
|
917
|
+
snap.name,
|
|
918
|
+
MU::Cloud::Google.compute(:GlobalSetLabelsRequest).new(
|
|
919
|
+
label_fingerprint: snap.label_fingerprint,
|
|
920
|
+
labels: labels.merge({
|
|
921
|
+
"mu-device-name" => disk.device_name,
|
|
922
|
+
"mu-parent-image" => name,
|
|
923
|
+
"mu-orig-zone" => zone
|
|
924
|
+
})
|
|
925
|
+
)
|
|
926
|
+
)
|
|
927
|
+
end
|
|
928
|
+
}
|
|
942
929
|
}
|
|
943
|
-
|
|
930
|
+
end
|
|
944
931
|
threads.each do |t|
|
|
945
932
|
t.join
|
|
946
933
|
end
|
|
@@ -954,10 +941,28 @@ next if !create
|
|
|
954
941
|
}
|
|
955
942
|
image_desc[:family] = family if family
|
|
956
943
|
|
|
957
|
-
|
|
944
|
+
MU.log "Creating image of #{name}", MU::NOTICE, details: image_desc
|
|
945
|
+
newimage = MU::Cloud::Google.compute(credentials: credentials).insert_image(
|
|
958
946
|
project,
|
|
959
947
|
MU::Cloud::Google.compute(:Image).new(image_desc)
|
|
960
948
|
)
|
|
949
|
+
|
|
950
|
+
if make_public
|
|
951
|
+
MU.log "Making image #{newimage.name} public"
|
|
952
|
+
MU::Cloud::Google.compute(credentials: credentials).set_image_iam_policy(
|
|
953
|
+
project,
|
|
954
|
+
newimage.name,
|
|
955
|
+
MU::Cloud::Google.compute(:GlobalSetPolicyRequest).new(
|
|
956
|
+
bindings: [
|
|
957
|
+
MU::Cloud::Google.compute(:Binding).new(
|
|
958
|
+
members: ["allAuthenticatedUsers"],
|
|
959
|
+
role: "roles/compute.imageUser"
|
|
960
|
+
)
|
|
961
|
+
],
|
|
962
|
+
)
|
|
963
|
+
)
|
|
964
|
+
end
|
|
965
|
+
|
|
961
966
|
newimage.name
|
|
962
967
|
end
|
|
963
968
|
|
|
@@ -966,7 +971,7 @@ next if !create
|
|
|
966
971
|
# bastion hosts that may be in the path, see getSSHConfig if that's what
|
|
967
972
|
# you need.
|
|
968
973
|
def canonicalIP
|
|
969
|
-
|
|
974
|
+
describe(cloud_id: @cloud_id)
|
|
970
975
|
|
|
971
976
|
if !cloud_desc
|
|
972
977
|
raise MuError, "Couldn't retrieve cloud descriptor for server #{self}"
|
|
@@ -987,7 +992,7 @@ next if !create
|
|
|
987
992
|
# Our deploydata gets corrupted often with server pools, this will cause us to use the wrong IP to identify a node
|
|
988
993
|
# which will cause us to create certificates, DNS records and other artifacts with incorrect information which will cause our deploy to fail.
|
|
989
994
|
# The cloud_id is always correct so lets use 'cloud_desc' to get the correct IPs
|
|
990
|
-
if MU::Cloud
|
|
995
|
+
if MU::Cloud.resourceClass("Google", "VPC").haveRouteToInstance?(cloud_desc, credentials: @config['credentials']) or public_ips.size == 0
|
|
991
996
|
@config['canonical_ip'] = private_ips.first
|
|
992
997
|
return private_ips.first
|
|
993
998
|
else
|
|
@@ -996,10 +1001,109 @@ next if !create
|
|
|
996
1001
|
end
|
|
997
1002
|
end
|
|
998
1003
|
|
|
1004
|
+
# Return all of the IP addresses, public and private, from all of our
|
|
1005
|
+
# network interfaces.
|
|
1006
|
+
# @return [Array<String>]
|
|
1007
|
+
def listIPs
|
|
1008
|
+
ips = []
|
|
1009
|
+
cloud_desc.network_interfaces.each { |iface|
|
|
1010
|
+
ips << iface.network_ip
|
|
1011
|
+
if iface.access_configs
|
|
1012
|
+
iface.access_configs.each { |acfg|
|
|
1013
|
+
ips << acfg.nat_ip if acfg.nat_ip
|
|
1014
|
+
}
|
|
1015
|
+
end
|
|
1016
|
+
}
|
|
1017
|
+
ips
|
|
1018
|
+
end
|
|
1019
|
+
|
|
999
1020
|
# return [String]: A password string.
|
|
1000
|
-
def getWindowsAdminPassword
|
|
1021
|
+
def getWindowsAdminPassword(use_cache: true)
|
|
1022
|
+
@config['windows_auth_vault'] ||= {
|
|
1023
|
+
"vault" => @mu_name,
|
|
1024
|
+
"item" => "windows_credentials",
|
|
1025
|
+
"password_field" => "password"
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
if use_cache
|
|
1029
|
+
begin
|
|
1030
|
+
win_admin_password = @groomer.getSecret(
|
|
1031
|
+
vault: @config['windows_auth_vault']['vault'],
|
|
1032
|
+
item: @config['windows_auth_vault']['item'],
|
|
1033
|
+
field: @config["windows_auth_vault"]["password_field"]
|
|
1034
|
+
)
|
|
1035
|
+
return win_admin_password if win_admin_password
|
|
1036
|
+
rescue MU::Groomer::MuNoSuchSecret, MU::Groomer::RunError
|
|
1037
|
+
end
|
|
1038
|
+
end
|
|
1039
|
+
|
|
1040
|
+
require 'openssl/oaep'
|
|
1041
|
+
timeout = 300
|
|
1042
|
+
|
|
1043
|
+
serial_out = nil
|
|
1044
|
+
key = OpenSSL::PKey::RSA.generate 2048
|
|
1045
|
+
|
|
1046
|
+
missing_response = Proc.new {
|
|
1047
|
+
!serial_out or !serial_out.contents or serial_out.contents.empty? or JSON.parse(serial_out.contents)["userName"] != @config['windows_admin_username']
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
did_metadata = false
|
|
1051
|
+
MU.retrier(loop_if: missing_response, wait: 10, max: timeout/10) {
|
|
1052
|
+
serial_out = MU::Cloud::Google.compute(credentials: @credentials).get_instance_serial_port_output(@project_id, @config['availability_zone'], @cloud_id, port: 4)
|
|
1053
|
+
|
|
1054
|
+
if missing_response.call and
|
|
1055
|
+
!cloud_desc(use_cache: false).metadata.items.map { |i| i.key }.include?("windows-keys")
|
|
1056
|
+
keybytes = Base64.decode64(key.public_key.export.gsub(/-----(?:BEGIN|END) PUBLIC KEY-----/, ''))
|
|
1057
|
+
modulus = keybytes.byteslice(33,256)
|
|
1058
|
+
exponent = keybytes.byteslice(291,3)
|
|
1059
|
+
keydata = {
|
|
1060
|
+
"userName" => @config['windows_admin_username'],
|
|
1061
|
+
"modulus" => Base64.strict_encode64(modulus),
|
|
1062
|
+
"exponent" => Base64.strict_encode64(exponent),
|
|
1063
|
+
"email" => MU.muCfg['mu_admin_email'],
|
|
1064
|
+
"expireOn" => (Time.now.utc+timeout).strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
new_items = cloud_desc.metadata.items.map { |item|
|
|
1068
|
+
MU::Cloud::Google.compute(:Metadata)::Item.new(
|
|
1069
|
+
key: item.key,
|
|
1070
|
+
value: item.value
|
|
1071
|
+
)
|
|
1072
|
+
}
|
|
1073
|
+
new_items.reject! { |item| item.key == "windows-keys" }
|
|
1074
|
+
new_items << MU::Cloud::Google.compute(:Metadata)::Item.new(
|
|
1075
|
+
key: "windows-keys",
|
|
1076
|
+
value: JSON.generate(keydata)
|
|
1077
|
+
)
|
|
1078
|
+
new_metadata = MU::Cloud::Google.compute(:Metadata).new(
|
|
1079
|
+
fingerprint: cloud_desc(use_cache: false).metadata.fingerprint,
|
|
1080
|
+
items: new_items
|
|
1081
|
+
)
|
|
1082
|
+
|
|
1083
|
+
MU::Cloud::Google.compute(credentials: @credentials).set_instance_metadata(@project_id, @config['availability_zone'], @cloud_id, new_metadata)
|
|
1084
|
+
end
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
return nil if missing_response.call
|
|
1088
|
+
|
|
1089
|
+
pwdata = JSON.parse(serial_out.contents)
|
|
1090
|
+
if pwdata['encryptedPassword'] and pwdata['userName'] == @config['windows_admin_username']
|
|
1091
|
+
decrypted_pw = key.private_decrypt_oaep(Base64.strict_decode64(pwdata['encryptedPassword']))
|
|
1092
|
+
creds = {
|
|
1093
|
+
"username" => @config['windows_admin_username'],
|
|
1094
|
+
"password" => decrypted_pw,
|
|
1095
|
+
"sshd_username" => "sshd_service",
|
|
1096
|
+
"sshd_password" => decrypted_pw
|
|
1097
|
+
}
|
|
1098
|
+
@groomer.saveSecret(vault: @mu_name, item: "windows_credentials", data: creds, permissions: "name:#{@mu_name}")
|
|
1099
|
+
|
|
1100
|
+
return decrypted_pw
|
|
1101
|
+
end
|
|
1102
|
+
|
|
1103
|
+
nil
|
|
1001
1104
|
end
|
|
1002
1105
|
|
|
1106
|
+
|
|
1003
1107
|
# Add a volume to this instance
|
|
1004
1108
|
# @param dev [String]: Device name to use when attaching to instance
|
|
1005
1109
|
# @param size [String]: Size (in gb) of the new volume
|
|
@@ -1017,7 +1121,7 @@ next if !create
|
|
|
1017
1121
|
description: description,
|
|
1018
1122
|
zone: @config['availability_zone'],
|
|
1019
1123
|
# type: "projects/#{config['project']}/zones/#{config['availability_zone']}/diskTypes/pd-ssd",
|
|
1020
|
-
type: "projects/#{@project_id}/zones/#{@config['availability_zone']}/diskTypes
|
|
1124
|
+
type: "projects/#{@project_id}/zones/#{@config['availability_zone']}/diskTypes/#{type}",
|
|
1021
1125
|
# Other values include pd-ssd and local-ssd
|
|
1022
1126
|
name: resname
|
|
1023
1127
|
)
|
|
@@ -1045,7 +1149,7 @@ next if !create
|
|
|
1045
1149
|
)
|
|
1046
1150
|
|
|
1047
1151
|
MU.log "Attaching disk #{resname} to #{@cloud_id} at #{devname}"
|
|
1048
|
-
|
|
1152
|
+
MU::Cloud::Google.compute(credentials: @config['credentials']).attach_disk(
|
|
1049
1153
|
@project_id,
|
|
1050
1154
|
@config['availability_zone'],
|
|
1051
1155
|
@cloud_id,
|
|
@@ -1064,7 +1168,7 @@ next if !create
|
|
|
1064
1168
|
# Reverse-map our cloud description into a runnable config hash.
|
|
1065
1169
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
1066
1170
|
# calculate our own accordingly based on what's live in the cloud.
|
|
1067
|
-
def toKitten(
|
|
1171
|
+
def toKitten(**_args)
|
|
1068
1172
|
bok = {
|
|
1069
1173
|
"cloud" => "Google",
|
|
1070
1174
|
"credentials" => @config['credentials'],
|
|
@@ -1186,41 +1290,47 @@ next if !create
|
|
|
1186
1290
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
1187
1291
|
# @param region [String]: The cloud provider region
|
|
1188
1292
|
# @return [void]
|
|
1189
|
-
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
1190
|
-
flags["
|
|
1191
|
-
return if !MU::Cloud
|
|
1192
|
-
|
|
1193
|
-
onlycloud = flags["onlycloud"]
|
|
1293
|
+
def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
1294
|
+
flags["habitat"] ||= MU::Cloud::Google.defaultProject(credentials)
|
|
1295
|
+
return if !MU::Cloud.resourceClass("Google", "Habitat").isLive?(flags["habitat"], credentials)
|
|
1296
|
+
|
|
1194
1297
|
# XXX make damn sure MU.deploy_id is set
|
|
1298
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
|
1299
|
+
if !ignoremaster and MU.mu_public_ip
|
|
1300
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
|
1301
|
+
end
|
|
1195
1302
|
|
|
1196
1303
|
MU::Cloud::Google.listAZs(region).each { |az|
|
|
1197
1304
|
disks = []
|
|
1198
1305
|
resp = MU::Cloud::Google.compute(credentials: credentials).list_instances(
|
|
1199
|
-
flags["
|
|
1306
|
+
flags["habitat"],
|
|
1200
1307
|
az,
|
|
1201
|
-
filter:
|
|
1308
|
+
filter: filter
|
|
1202
1309
|
)
|
|
1203
1310
|
if !resp.items.nil? and resp.items.size > 0
|
|
1204
1311
|
resp.items.each { |instance|
|
|
1205
|
-
saname = instance.tags.items.first.gsub(/[^a-z]/, "") # XXX this nonsense again
|
|
1206
1312
|
MU.log "Terminating instance #{instance.name}"
|
|
1207
1313
|
if !instance.disks.nil? and instance.disks.size > 0
|
|
1208
1314
|
instance.disks.each { |disk|
|
|
1209
1315
|
disks << disk if !disk.auto_delete
|
|
1210
1316
|
}
|
|
1211
1317
|
end
|
|
1212
|
-
|
|
1213
|
-
flags["
|
|
1318
|
+
MU::Cloud::Google.compute(credentials: credentials).delete_instance(
|
|
1319
|
+
flags["habitat"],
|
|
1214
1320
|
az,
|
|
1215
1321
|
instance.name
|
|
1216
1322
|
) if !noop
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1323
|
+
if instance.service_accounts
|
|
1324
|
+
instance.service_accounts.each { |sa|
|
|
1325
|
+
MU.log "Removing service account #{sa.email}"
|
|
1326
|
+
begin
|
|
1327
|
+
MU::Cloud::Google.iam(credentials: credentials).delete_project_service_account(
|
|
1328
|
+
"projects/#{flags["habitat"]}/serviceAccounts/#{sa.email}"
|
|
1329
|
+
) if !noop
|
|
1330
|
+
rescue ::Google::Apis::ClientError => e
|
|
1331
|
+
raise e if !e.message.match(/^notFound: /)
|
|
1332
|
+
end
|
|
1333
|
+
}
|
|
1224
1334
|
end
|
|
1225
1335
|
# XXX wait-loop on pending?
|
|
1226
1336
|
# pp deletia
|
|
@@ -1233,7 +1343,7 @@ next if !create
|
|
|
1233
1343
|
# XXX honor snapshotting
|
|
1234
1344
|
MU::Cloud::Google.compute(credentials: credentials).delete(
|
|
1235
1345
|
"disk",
|
|
1236
|
-
flags["
|
|
1346
|
+
flags["habitat"],
|
|
1237
1347
|
az,
|
|
1238
1348
|
noop
|
|
1239
1349
|
) if !noop
|
|
@@ -1246,7 +1356,11 @@ next if !create
|
|
|
1246
1356
|
def self.schema(config)
|
|
1247
1357
|
toplevel_required = []
|
|
1248
1358
|
schema = {
|
|
1249
|
-
"roles" => MU::Cloud
|
|
1359
|
+
"roles" => MU::Cloud.resourceClass("Google", "User").schema(config)[1]["roles"],
|
|
1360
|
+
"windows_admin_username" => {
|
|
1361
|
+
"type" => "string",
|
|
1362
|
+
"default" => "muadmin"
|
|
1363
|
+
},
|
|
1250
1364
|
"create_image" => {
|
|
1251
1365
|
"properties" => {
|
|
1252
1366
|
"family" => {
|
|
@@ -1353,8 +1467,7 @@ next if !create
|
|
|
1353
1467
|
foundmatch = false
|
|
1354
1468
|
MU::Cloud.availableClouds.each { |cloud|
|
|
1355
1469
|
next if cloud == "Google"
|
|
1356
|
-
|
|
1357
|
-
foreign_types = (cloudbase.listInstanceTypes).values.first
|
|
1470
|
+
foreign_types = (MU::Cloud.cloudClass(cloud).listInstanceTypes).values.first
|
|
1358
1471
|
if foreign_types.size == 1
|
|
1359
1472
|
foreign_types = foreign_types.values.first
|
|
1360
1473
|
end
|
|
@@ -1411,6 +1524,7 @@ next if !create
|
|
|
1411
1524
|
end
|
|
1412
1525
|
|
|
1413
1526
|
if server['service_account']
|
|
1527
|
+
server['service_account'] = server['service_account'].to_h
|
|
1414
1528
|
server['service_account']['cloud'] = "Google"
|
|
1415
1529
|
server['service_account']['habitat'] ||= server['project']
|
|
1416
1530
|
found = MU::Config::Ref.get(server['service_account'])
|
|
@@ -1419,37 +1533,12 @@ next if !create
|
|
|
1419
1533
|
ok = false
|
|
1420
1534
|
end
|
|
1421
1535
|
else
|
|
1422
|
-
|
|
1423
|
-
"name" => server['name'],
|
|
1424
|
-
"cloud" => "Google",
|
|
1425
|
-
"project" => server["project"],
|
|
1426
|
-
"credentials" => server["credentials"],
|
|
1427
|
-
"type" => "service"
|
|
1428
|
-
}
|
|
1429
|
-
if user["name"].length < 6
|
|
1430
|
-
user["name"] += Password.pronounceable(6)
|
|
1431
|
-
end
|
|
1432
|
-
if server['roles']
|
|
1433
|
-
user['roles'] = server['roles'].dup
|
|
1434
|
-
end
|
|
1435
|
-
configurator.insertKitten(user, "users", true)
|
|
1436
|
-
server['dependencies'] ||= []
|
|
1437
|
-
server['service_account'] = MU::Config::Ref.get(
|
|
1438
|
-
type: "users",
|
|
1439
|
-
cloud: "Google",
|
|
1440
|
-
name: user["name"],
|
|
1441
|
-
project: user["project"],
|
|
1442
|
-
credentials: user["credentials"]
|
|
1443
|
-
)
|
|
1444
|
-
server['dependencies'] << {
|
|
1445
|
-
"type" => "user",
|
|
1446
|
-
"name" => user["name"]
|
|
1447
|
-
}
|
|
1536
|
+
server = MU::Cloud.resourceClass("Google", "User").genericServiceAccount(server, configurator)
|
|
1448
1537
|
end
|
|
1449
1538
|
|
|
1450
1539
|
subnets = nil
|
|
1451
1540
|
if !server['vpc']
|
|
1452
|
-
vpcs = MU::Cloud
|
|
1541
|
+
vpcs = MU::Cloud.resourceClass("Google", "VPC").find(credentials: server['credentials'])
|
|
1453
1542
|
if vpcs["default"]
|
|
1454
1543
|
server["vpc"] ||= {}
|
|
1455
1544
|
server["vpc"]["vpc_id"] = vpcs["default"].self_link
|
|
@@ -1464,7 +1553,7 @@ next if !create
|
|
|
1464
1553
|
if !server['vpc']['subnet_id'] and server['vpc']['subnet_name'].nil?
|
|
1465
1554
|
if !subnets
|
|
1466
1555
|
if server["vpc"]["vpc_id"]
|
|
1467
|
-
vpcs = MU::Cloud
|
|
1556
|
+
vpcs = MU::Cloud.resourceClass("Google", "VPC").find(cloud_id: server["vpc"]["vpc_id"])
|
|
1468
1557
|
subnets = vpcs["default"].subnetworks.sample
|
|
1469
1558
|
end
|
|
1470
1559
|
end
|
|
@@ -1509,7 +1598,7 @@ next if !create
|
|
|
1509
1598
|
img_project = Regexp.last_match[1]
|
|
1510
1599
|
img_name = Regexp.last_match[2]
|
|
1511
1600
|
begin
|
|
1512
|
-
|
|
1601
|
+
MU::Cloud::Google.compute(credentials: server['credentials']).get_image(img_project, img_name)
|
|
1513
1602
|
snaps = MU::Cloud::Google.compute(credentials: server['credentials']).list_snapshots(
|
|
1514
1603
|
img_project,
|
|
1515
1604
|
filter: "name eq #{img_name}-.*"
|
|
@@ -1548,8 +1637,6 @@ next if !create
|
|
|
1548
1637
|
ok
|
|
1549
1638
|
end
|
|
1550
1639
|
|
|
1551
|
-
private
|
|
1552
|
-
|
|
1553
1640
|
end #class
|
|
1554
1641
|
end #class
|
|
1555
1642
|
end
|