cloud-mu 3.1.3 → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +10 -2
  3. data/bin/mu-adopt +5 -1
  4. data/bin/mu-load-config.rb +2 -3
  5. data/bin/mu-run-tests +112 -27
  6. data/cloud-mu.gemspec +20 -20
  7. data/cookbooks/mu-tools/libraries/helper.rb +2 -1
  8. data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
  9. data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
  10. data/cookbooks/mu-tools/resources/disk.rb +1 -1
  11. data/extras/image-generators/Google/centos6.yaml +1 -0
  12. data/extras/image-generators/Google/centos7.yaml +1 -1
  13. data/modules/mommacat.ru +5 -15
  14. data/modules/mu.rb +10 -14
  15. data/modules/mu/adoption.rb +20 -14
  16. data/modules/mu/cleanup.rb +13 -9
  17. data/modules/mu/cloud.rb +26 -26
  18. data/modules/mu/clouds/aws.rb +100 -59
  19. data/modules/mu/clouds/aws/alarm.rb +4 -2
  20. data/modules/mu/clouds/aws/bucket.rb +25 -21
  21. data/modules/mu/clouds/aws/cache_cluster.rb +25 -23
  22. data/modules/mu/clouds/aws/collection.rb +21 -20
  23. data/modules/mu/clouds/aws/container_cluster.rb +47 -26
  24. data/modules/mu/clouds/aws/database.rb +57 -68
  25. data/modules/mu/clouds/aws/dnszone.rb +14 -14
  26. data/modules/mu/clouds/aws/endpoint.rb +20 -16
  27. data/modules/mu/clouds/aws/firewall_rule.rb +19 -16
  28. data/modules/mu/clouds/aws/folder.rb +7 -7
  29. data/modules/mu/clouds/aws/function.rb +15 -12
  30. data/modules/mu/clouds/aws/group.rb +14 -10
  31. data/modules/mu/clouds/aws/habitat.rb +16 -13
  32. data/modules/mu/clouds/aws/loadbalancer.rb +16 -15
  33. data/modules/mu/clouds/aws/log.rb +13 -10
  34. data/modules/mu/clouds/aws/msg_queue.rb +15 -8
  35. data/modules/mu/clouds/aws/nosqldb.rb +18 -11
  36. data/modules/mu/clouds/aws/notifier.rb +11 -6
  37. data/modules/mu/clouds/aws/role.rb +87 -70
  38. data/modules/mu/clouds/aws/search_domain.rb +30 -19
  39. data/modules/mu/clouds/aws/server.rb +102 -72
  40. data/modules/mu/clouds/aws/server_pool.rb +47 -28
  41. data/modules/mu/clouds/aws/storage_pool.rb +5 -6
  42. data/modules/mu/clouds/aws/user.rb +13 -10
  43. data/modules/mu/clouds/aws/vpc.rb +135 -121
  44. data/modules/mu/clouds/azure.rb +16 -9
  45. data/modules/mu/clouds/azure/container_cluster.rb +2 -3
  46. data/modules/mu/clouds/azure/firewall_rule.rb +10 -10
  47. data/modules/mu/clouds/azure/habitat.rb +8 -6
  48. data/modules/mu/clouds/azure/loadbalancer.rb +5 -5
  49. data/modules/mu/clouds/azure/role.rb +8 -10
  50. data/modules/mu/clouds/azure/server.rb +65 -25
  51. data/modules/mu/clouds/azure/user.rb +5 -7
  52. data/modules/mu/clouds/azure/vpc.rb +12 -15
  53. data/modules/mu/clouds/cloudformation.rb +8 -7
  54. data/modules/mu/clouds/cloudformation/vpc.rb +2 -4
  55. data/modules/mu/clouds/google.rb +39 -24
  56. data/modules/mu/clouds/google/bucket.rb +9 -11
  57. data/modules/mu/clouds/google/container_cluster.rb +27 -42
  58. data/modules/mu/clouds/google/database.rb +6 -9
  59. data/modules/mu/clouds/google/firewall_rule.rb +11 -10
  60. data/modules/mu/clouds/google/folder.rb +16 -9
  61. data/modules/mu/clouds/google/function.rb +127 -161
  62. data/modules/mu/clouds/google/group.rb +21 -18
  63. data/modules/mu/clouds/google/habitat.rb +18 -15
  64. data/modules/mu/clouds/google/loadbalancer.rb +14 -16
  65. data/modules/mu/clouds/google/role.rb +48 -31
  66. data/modules/mu/clouds/google/server.rb +105 -105
  67. data/modules/mu/clouds/google/server_pool.rb +12 -31
  68. data/modules/mu/clouds/google/user.rb +67 -13
  69. data/modules/mu/clouds/google/vpc.rb +58 -65
  70. data/modules/mu/config.rb +89 -1738
  71. data/modules/mu/config/bucket.rb +3 -3
  72. data/modules/mu/config/collection.rb +3 -3
  73. data/modules/mu/config/container_cluster.rb +2 -2
  74. data/modules/mu/config/dnszone.rb +5 -5
  75. data/modules/mu/config/doc_helpers.rb +517 -0
  76. data/modules/mu/config/endpoint.rb +3 -3
  77. data/modules/mu/config/firewall_rule.rb +118 -3
  78. data/modules/mu/config/folder.rb +3 -3
  79. data/modules/mu/config/function.rb +2 -2
  80. data/modules/mu/config/group.rb +3 -3
  81. data/modules/mu/config/habitat.rb +3 -3
  82. data/modules/mu/config/loadbalancer.rb +3 -3
  83. data/modules/mu/config/log.rb +3 -3
  84. data/modules/mu/config/msg_queue.rb +3 -3
  85. data/modules/mu/config/nosqldb.rb +3 -3
  86. data/modules/mu/config/notifier.rb +2 -2
  87. data/modules/mu/config/ref.rb +333 -0
  88. data/modules/mu/config/role.rb +3 -3
  89. data/modules/mu/config/schema_helpers.rb +508 -0
  90. data/modules/mu/config/search_domain.rb +3 -3
  91. data/modules/mu/config/server.rb +86 -58
  92. data/modules/mu/config/server_pool.rb +2 -2
  93. data/modules/mu/config/tail.rb +189 -0
  94. data/modules/mu/config/user.rb +3 -3
  95. data/modules/mu/config/vpc.rb +44 -4
  96. data/modules/mu/defaults/Google.yaml +2 -2
  97. data/modules/mu/deploy.rb +13 -10
  98. data/modules/mu/groomer.rb +1 -1
  99. data/modules/mu/groomers/ansible.rb +69 -24
  100. data/modules/mu/groomers/chef.rb +52 -44
  101. data/modules/mu/logger.rb +17 -14
  102. data/modules/mu/master.rb +317 -2
  103. data/modules/mu/master/chef.rb +3 -4
  104. data/modules/mu/master/ldap.rb +3 -3
  105. data/modules/mu/master/ssl.rb +12 -2
  106. data/modules/mu/mommacat.rb +85 -1766
  107. data/modules/mu/mommacat/daemon.rb +394 -0
  108. data/modules/mu/mommacat/naming.rb +366 -0
  109. data/modules/mu/mommacat/storage.rb +689 -0
  110. data/modules/tests/bucket.yml +4 -0
  111. data/modules/tests/{win2k12.yaml → needwork/win2k12.yaml} +0 -0
  112. data/modules/tests/regrooms/aws-iam.yaml +201 -0
  113. data/modules/tests/regrooms/bucket.yml +19 -0
  114. metadata +112 -102
@@ -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 => e
90
+ rescue ::Google::Apis::ClientError
91
91
  end
92
92
 
93
93
  return DateTime.new
@@ -247,15 +247,22 @@ next if !create
247
247
  subnet_cfg = config['vpc']['subnets'].sample
248
248
 
249
249
  end
250
+
250
251
  subnet = vpc.getSubnet(name: subnet_cfg['subnet_name'], cloud_id: subnet_cfg['subnet_id'])
251
252
  if subnet.nil?
252
- 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})"
253
+ if config['vpc']['name']
254
+ subnet = vpc.getSubnet(name: config['vpc']['name']+subnet_cfg['subnet_name'], cloud_id: subnet_cfg['subnet_id'])
255
+ end
256
+ if subnet.nil?
257
+ 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})"
258
+ end
253
259
  end
254
260
 
255
261
  base_iface_obj = {
256
262
  :network => vpc.url,
257
263
  :subnetwork => subnet.url
258
264
  }
265
+
259
266
  if config['associate_public_ip']
260
267
  base_iface_obj[:access_configs] = [
261
268
  MU::Cloud::Google.compute(:AccessConfig).new
@@ -348,7 +355,7 @@ next if !create
348
355
  desc[:labels]["name"] = @mu_name.downcase
349
356
 
350
357
  if @config['network_tags'] and @config['network_tags'].size > 0
351
- desc[:tags] = U::Cloud::Google.compute(:Tags).new(
358
+ desc[:tags] = MU::Cloud::Google.compute(:Tags).new(
352
359
  items: @config['network_tags']
353
360
  )
354
361
  end
@@ -369,7 +376,7 @@ next if !create
369
376
  sleep 10
370
377
  end
371
378
  rescue ::Google::Apis::ClientError => e
372
- MU.log e.message, MU::ERR
379
+ MU.log e.message+" inserting instance into #{@project_id}/#{@config['availability_zone']}", MU::ERR, details: instanceobj
373
380
  raise e
374
381
  end while @cloud_id.nil?
375
382
 
@@ -394,7 +401,7 @@ next if !create
394
401
 
395
402
  notify
396
403
 
397
- rescue Exception => e
404
+ rescue StandardError => e
398
405
  if !cloud_desc.nil? and !done
399
406
  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
407
  MU::MommaCat.unlockAll
@@ -445,7 +452,7 @@ next if !create
445
452
  )
446
453
  begin
447
454
  sleep 5
448
- end while cloud_desc.status != "TERMINATED" # means STOPPED
455
+ end while cloud_desc(use_cache: false).status != "TERMINATED" # means STOPPED
449
456
  end
450
457
 
451
458
  # Ask the Google API to start this node
@@ -462,30 +469,30 @@ next if !create
462
469
  end
463
470
 
464
471
  # Ask the Google API to restart this node
465
- # XXX unimplemented
466
- def reboot(hard = false)
472
+ # @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.
473
+ def reboot(_hard = false)
467
474
  return if @cloud_id.nil?
468
-
475
+ stop
476
+ start
469
477
  end
470
478
 
471
479
  # Figure out what's needed to SSH into this server.
472
480
  # @return [Array<String>]: nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name, alternate_names
473
481
  def getSSHConfig
474
- node, config, deploydata = describe(cloud_id: @cloud_id)
482
+ describe(cloud_id: @cloud_id)
475
483
  # XXX add some awesome alternate names from metadata and make sure they end
476
484
  # up in MU::MommaCat's ssh config wangling
477
- ssh_keydir = Etc.getpwuid(Process.uid).dir+"/.ssh"
478
485
  return nil if @config.nil? or @deploy.nil?
479
486
 
480
487
  nat_ssh_key = nat_ssh_user = nat_ssh_host = nil
481
- if !@config["vpc"].nil? and !MU::Cloud::Google::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
488
+ if !@config["vpc"].nil? and !MU::Cloud::Google::VPC.haveRouteToInstance?(cloud_desc, credentials: @config['credentials'])
482
489
 
483
490
  if !@nat.nil?
484
491
  if @nat.cloud_desc.nil?
485
492
  MU.log "NAT was missing cloud descriptor when called in #{@mu_name}'s getSSHConfig", MU::ERR
486
493
  return nil
487
494
  end
488
- foo, bar, baz, nat_ssh_host, nat_ssh_user, nat_ssh_key = @nat.getSSHConfig
495
+ _foo, _bar, _baz, nat_ssh_host, nat_ssh_user, nat_ssh_key = @nat.getSSHConfig
489
496
  if nat_ssh_user.nil? and !nat_ssh_host.nil?
490
497
  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
498
  nat_ssh_user = "root"
@@ -512,26 +519,24 @@ next if !create
512
519
  @cloud_id = instance_id
513
520
  end
514
521
 
515
- instance = cloud_desc
516
-
517
- node, config, deploydata = describe(cloud_id: @cloud_id)
522
+ node, _config, deploydata = describe(cloud_id: @cloud_id)
518
523
  instance = cloud_desc
519
524
  raise MuError, "Couldn't find instance of #{@mu_name} (#{@cloud_id})" if !instance
520
525
  return false if !MU::MommaCat.lock(@cloud_id+"-orchestrate", true)
521
526
  return false if !MU::MommaCat.lock(@cloud_id+"-groom", true)
522
527
 
523
528
  # MU::Cloud::AWS.createStandardTags(@cloud_id, region: @config['region'])
524
- # MU::MommaCat.createTag(@cloud_id, "Name", node, region: @config['region'])
529
+ # MU::Cloud::AWS.createTag(@cloud_id, "Name", node, region: @config['region'])
525
530
  #
526
531
  # if @config['optional_tags']
527
532
  # MU::MommaCat.listOptionalTags.each { |key, value|
528
- # MU::MommaCat.createTag(@cloud_id, key, value, region: @config['region'])
533
+ # MU::Cloud::AWS.createTag(@cloud_id, key, value, region: @config['region'])
529
534
  # }
530
535
  # end
531
536
  #
532
537
  # if !@config['tags'].nil?
533
538
  # @config['tags'].each { |tag|
534
- # MU::MommaCat.createTag(@cloud_id, tag['key'], tag['value'], region: @config['region'])
539
+ # MU::Cloud::AWS.createTag(@cloud_id, tag['key'], tag['value'], region: @config['region'])
535
540
  # }
536
541
  # end
537
542
  # MU.log "Tagged #{node} (#{@cloud_id}) with MU-ID=#{MU.deploy_id}", MU::DEBUG
@@ -609,8 +614,8 @@ next if !create
609
614
  @named = true
610
615
  end
611
616
 
612
- nat_ssh_key, nat_ssh_user, nat_ssh_host, canonical_ip, ssh_user, ssh_key_name = getSSHConfig
613
- if !nat_ssh_host and !MU::Cloud::Google::VPC.haveRouteToInstance?(cloud_desc, region: @config['region'], credentials: @config['credentials'])
617
+ _nat_ssh_key, _nat_ssh_user, nat_ssh_host, _canonical_ip, _ssh_user, _ssh_key_name = getSSHConfig
618
+ if !nat_ssh_host and !MU::Cloud::Google::VPC.haveRouteToInstance?(cloud_desc, credentials: @config['credentials'])
614
619
  # XXX check if canonical_ip is in the private ranges
615
620
  # raise MuError, "#{node} has no NAT host configured, and I have no other route to it"
616
621
  end
@@ -641,8 +646,8 @@ next if !create
641
646
  # Locate an existing instance or instances and return an array containing matching AWS resource descriptors for those that match.
642
647
  # @return [Array<Hash<String,OpenStruct>>]: The cloud provider's complete descriptions of matching instances
643
648
  def self.find(**args)
644
- args[:project] ||= args[:habitat]
645
- args[:project] ||= MU::Cloud::Google.defaultProject(args[:credentials])
649
+ args = MU::Cloud::Google.findLocationArgs(args)
650
+
646
651
  if !args[:region].nil? and MU::Cloud::Google.listRegions.include?(args[:region])
647
652
  regions = [args[:region]]
648
653
  else
@@ -720,9 +725,6 @@ next if !create
720
725
  # Return a description of this resource appropriate for deployment
721
726
  # metadata. Arguments reflect the return values of the MU::Cloud::[Resource].describe method
722
727
  def notify
723
- node, config, deploydata = describe(cloud_id: @cloud_id, update_cache: true)
724
- deploydata = {} if deploydata.nil?
725
-
726
728
  if cloud_desc.nil?
727
729
  raise MuError, "Failed to load instance metadata for #{@config['mu_name']}/#{@cloud_id}"
728
730
  end
@@ -783,7 +785,7 @@ next if !create
783
785
 
784
786
  MU::MommaCat.lock(@cloud_id+"-groom")
785
787
 
786
- node, config, deploydata = describe(cloud_id: @cloud_id)
788
+ node, _config, deploydata = describe(cloud_id: @cloud_id)
787
789
 
788
790
  if node.nil? or node.empty?
789
791
  raise MuError, "MU::Cloud::Google::Server.groom was called without a mu_name"
@@ -859,9 +861,9 @@ next if !create
859
861
  project: @project_id,
860
862
  exclude_storage: img_cfg['image_exclude_storage'],
861
863
  make_public: img_cfg['public'],
862
- tags: @config['tags'],
864
+ tags: @tags,
863
865
  zone: @config['availability_zone'],
864
- family: @config['family'],
866
+ family: img_cfg['family'],
865
867
  credentials: @config['credentials']
866
868
  )
867
869
  @deploy.notify("images", @config['name'], {"image_id" => image_id})
@@ -897,50 +899,50 @@ next if !create
897
899
  raise MuError, "Failed to find instance '#{instance_id}' in createImage"
898
900
  end
899
901
 
900
- labels = {}
901
- MU::MommaCat.listStandardTags.each_pair { |key, value|
902
- if !value.nil?
903
- labels[key.downcase] = value.downcase.gsub(/[^a-z0-9\-\_]/i, "_")
904
- end
905
- }
902
+ labels = Hash[tags.keys.map { |k|
903
+ [k.downcase, tags[k].downcase.gsub(/[^-_a-z0-9]/, '-')] }
904
+ ]
905
+ labels["name"] = name
906
906
 
907
907
  bootdisk = nil
908
908
  threads = []
909
909
  parent_thread_id = Thread.current.object_id
910
- instance[instance_id].disks.each { |disk|
911
- threads << Thread.new {
912
- Thread.abort_on_exception = false
913
- MU.dupGlobals(parent_thread_id)
914
- if disk.boot
915
- bootdisk = disk.source
916
- else
917
- snapobj = MU::Cloud::Google.compute(:Snapshot).new(
918
- name: name+"-"+disk.device_name,
919
- description: "Mu image created from #{name} (#{disk.device_name})"
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
- })
910
+ if !exclude_storage
911
+ instance[instance_id].disks.each { |disk|
912
+ threads << Thread.new {
913
+ Thread.abort_on_exception = false
914
+ MU.dupGlobals(parent_thread_id)
915
+ if disk.boot
916
+ bootdisk = disk.source
917
+ else
918
+ snapobj = MU::Cloud::Google.compute(:Snapshot).new(
919
+ name: name+"-"+disk.device_name,
920
+ description: "Mu image created from #{name} (#{disk.device_name})"
939
921
  )
940
- )
941
- end
922
+ diskname = disk.source.gsub(/.*?\//, "")
923
+ MU.log "Creating snapshot of #{diskname} in #{zone}", MU::NOTICE, details: snapobj
924
+ snap = MU::Cloud::Google.compute(credentials: credentials).create_disk_snapshot(
925
+ project,
926
+ zone,
927
+ diskname,
928
+ snapobj
929
+ )
930
+ MU::Cloud::Google.compute(credentials: credentials).set_snapshot_labels(
931
+ project,
932
+ snap.name,
933
+ MU::Cloud::Google.compute(:GlobalSetLabelsRequest).new(
934
+ label_fingerprint: snap.label_fingerprint,
935
+ labels: labels.merge({
936
+ "mu-device-name" => disk.device_name,
937
+ "mu-parent-image" => name,
938
+ "mu-orig-zone" => zone
939
+ })
940
+ )
941
+ )
942
+ end
943
+ }
942
944
  }
943
- }
945
+ end
944
946
  threads.each do |t|
945
947
  t.join
946
948
  end
@@ -954,10 +956,28 @@ next if !create
954
956
  }
955
957
  image_desc[:family] = family if family
956
958
 
957
- newimage = MU::Cloud::Google.compute(credentials: @config['credentials']).insert_image(
959
+ MU.log "Creating image of #{name}", MU::NOTICE, details: image_desc
960
+ newimage = MU::Cloud::Google.compute(credentials: credentials).insert_image(
958
961
  project,
959
962
  MU::Cloud::Google.compute(:Image).new(image_desc)
960
963
  )
964
+
965
+ if make_public
966
+ MU.log "Making image #{newimage.name} public"
967
+ MU::Cloud::Google.compute(credentials: credentials).set_image_iam_policy(
968
+ project,
969
+ newimage.name,
970
+ MU::Cloud::Google.compute(:GlobalSetPolicyRequest).new(
971
+ bindings: [
972
+ MU::Cloud::Google.compute(:Binding).new(
973
+ members: ["allAuthenticatedUsers"],
974
+ role: "roles/compute.imageUser"
975
+ )
976
+ ],
977
+ )
978
+ )
979
+ end
980
+
961
981
  newimage.name
962
982
  end
963
983
 
@@ -966,7 +986,7 @@ next if !create
966
986
  # bastion hosts that may be in the path, see getSSHConfig if that's what
967
987
  # you need.
968
988
  def canonicalIP
969
- mu_name, config, deploydata = describe(cloud_id: @cloud_id)
989
+ describe(cloud_id: @cloud_id)
970
990
 
971
991
  if !cloud_desc
972
992
  raise MuError, "Couldn't retrieve cloud descriptor for server #{self}"
@@ -1017,7 +1037,7 @@ next if !create
1017
1037
  description: description,
1018
1038
  zone: @config['availability_zone'],
1019
1039
  # type: "projects/#{config['project']}/zones/#{config['availability_zone']}/diskTypes/pd-ssd",
1020
- type: "projects/#{@project_id}/zones/#{@config['availability_zone']}/diskTypes/pd-standard",
1040
+ type: "projects/#{@project_id}/zones/#{@config['availability_zone']}/diskTypes/#{type}",
1021
1041
  # Other values include pd-ssd and local-ssd
1022
1042
  name: resname
1023
1043
  )
@@ -1045,7 +1065,7 @@ next if !create
1045
1065
  )
1046
1066
 
1047
1067
  MU.log "Attaching disk #{resname} to #{@cloud_id} at #{devname}"
1048
- attachment = MU::Cloud::Google.compute(credentials: @config['credentials']).attach_disk(
1068
+ MU::Cloud::Google.compute(credentials: @config['credentials']).attach_disk(
1049
1069
  @project_id,
1050
1070
  @config['availability_zone'],
1051
1071
  @cloud_id,
@@ -1064,7 +1084,7 @@ next if !create
1064
1084
  # Reverse-map our cloud description into a runnable config hash.
1065
1085
  # We assume that any values we have in +@config+ are placeholders, and
1066
1086
  # calculate our own accordingly based on what's live in the cloud.
1067
- def toKitten(rootparent: nil, billing: nil, habitats: nil)
1087
+ def toKitten(**_args)
1068
1088
  bok = {
1069
1089
  "cloud" => "Google",
1070
1090
  "credentials" => @config['credentials'],
@@ -1189,16 +1209,19 @@ next if !create
1189
1209
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
1190
1210
  flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
1191
1211
  return if !MU::Cloud::Google::Habitat.isLive?(flags["project"], credentials)
1192
- skipsnapshots = flags["skipsnapshots"]
1193
- onlycloud = flags["onlycloud"]
1212
+
1194
1213
  # XXX make damn sure MU.deploy_id is set
1214
+ filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
1215
+ if !ignoremaster and MU.mu_public_ip
1216
+ filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
1217
+ end
1195
1218
 
1196
1219
  MU::Cloud::Google.listAZs(region).each { |az|
1197
1220
  disks = []
1198
1221
  resp = MU::Cloud::Google.compute(credentials: credentials).list_instances(
1199
1222
  flags["project"],
1200
1223
  az,
1201
- filter: "description eq #{MU.deploy_id}"
1224
+ filter: filter
1202
1225
  )
1203
1226
  if !resp.items.nil? and resp.items.size > 0
1204
1227
  resp.items.each { |instance|
@@ -1209,7 +1232,7 @@ next if !create
1209
1232
  disks << disk if !disk.auto_delete
1210
1233
  }
1211
1234
  end
1212
- deletia = MU::Cloud::Google.compute(credentials: credentials).delete_instance(
1235
+ MU::Cloud::Google.compute(credentials: credentials).delete_instance(
1213
1236
  flags["project"],
1214
1237
  az,
1215
1238
  instance.name
@@ -1247,6 +1270,10 @@ next if !create
1247
1270
  toplevel_required = []
1248
1271
  schema = {
1249
1272
  "roles" => MU::Cloud::Google::User.schema(config)[1]["roles"],
1273
+ "windows_admin_username" => {
1274
+ "type" => "string",
1275
+ "default" => "Administrator"
1276
+ },
1250
1277
  "create_image" => {
1251
1278
  "properties" => {
1252
1279
  "family" => {
@@ -1419,32 +1446,7 @@ next if !create
1419
1446
  ok = false
1420
1447
  end
1421
1448
  else
1422
- user = {
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
- }
1449
+ server = MU::Cloud::Google::User.genericServiceAccount(server, configurator)
1448
1450
  end
1449
1451
 
1450
1452
  subnets = nil
@@ -1509,7 +1511,7 @@ next if !create
1509
1511
  img_project = Regexp.last_match[1]
1510
1512
  img_name = Regexp.last_match[2]
1511
1513
  begin
1512
- img = MU::Cloud::Google.compute(credentials: server['credentials']).get_image(img_project, img_name)
1514
+ MU::Cloud::Google.compute(credentials: server['credentials']).get_image(img_project, img_name)
1513
1515
  snaps = MU::Cloud::Google.compute(credentials: server['credentials']).list_snapshots(
1514
1516
  img_project,
1515
1517
  filter: "name eq #{img_name}-.*"
@@ -1548,8 +1550,6 @@ next if !create
1548
1550
  ok
1549
1551
  end
1550
1552
 
1551
- private
1552
-
1553
1553
  end #class
1554
1554
  end #class
1555
1555
  end
@@ -64,10 +64,9 @@ module MU
64
64
  size = @config['basis']['launch_config']['size']
65
65
  @config['image_id'] = @config['basis']['launch_config']['image_id']
66
66
  end
67
- az = @config['availability_zone']
68
- if az.nil?
69
- az = MU::Cloud::Google.listAZs(@config['region']).sample
70
- end
67
+ # XXX this should create a non-regional instance group
68
+ # az = @config['availability_zone']
69
+ # az ||= MU::Cloud::Google.listAZs(@config['region']).sample
71
70
 
72
71
  metadata = { # :items?
73
72
  "startup-script" => @userdata
@@ -170,8 +169,7 @@ module MU
170
169
  # Locate an existing ServerPool or ServerPools and return an array containing matching Google resource descriptors for those that match.
171
170
  # @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching ServerPools
172
171
  def self.find(**args)
173
- args[:project] ||= args[:habitat]
174
- args[:project] ||= MU::Cloud::Google.defaultProject(args[:credentials])
172
+ args = MU::Cloud::Google.findLocationArgs(args)
175
173
 
176
174
  regions = if args[:region]
177
175
  [args[:region]]
@@ -213,7 +211,7 @@ module MU
213
211
  # Reverse-map our cloud description into a runnable config hash.
214
212
  # We assume that any values we have in +@config+ are placeholders, and
215
213
  # calculate our own accordingly based on what's live in the cloud.
216
- def toKitten(rootparent: nil, billing: nil, habitats: nil)
214
+ def toKitten(**_args)
217
215
  bok = {
218
216
  "cloud" => "Google",
219
217
  "credentials" => @credentials,
@@ -362,7 +360,7 @@ end
362
360
  # @return [Boolean]: True if validation succeeded, False otherwise
363
361
  def self.validateConfig(pool, configurator)
364
362
  ok = true
365
- start = Time.now
363
+ #start = Time.now
366
364
  pool['project'] ||= MU::Cloud::Google.defaultProject(pool['credentials'])
367
365
  if pool['service_account']
368
366
  pool['service_account']['cloud'] = "Google"
@@ -373,29 +371,7 @@ start = Time.now
373
371
  ok = false
374
372
  end
375
373
  else
376
- user = {
377
- "name" => pool['name'],
378
- "cloud" => "Google",
379
- "project" => pool["project"],
380
- "credentials" => pool["credentials"],
381
- "type" => "service"
382
- }
383
- if user["name"].length < 6
384
- user["name"] += Password.pronounceable(6)
385
- end
386
- configurator.insertKitten(user, "users", true)
387
- pool['dependencies'] ||= []
388
- pool['service_account'] = MU::Config::Ref.get(
389
- type: "users",
390
- cloud: "Google",
391
- name: pool["name"],
392
- project: pool["project"],
393
- credentials: pool["credentials"]
394
- )
395
- pool['dependencies'] << {
396
- "type" => "user",
397
- "name" => pool["name"]
398
- }
374
+ pool = MU::Cloud::Google::User.genericServiceAccount(pool, configurator)
399
375
  end
400
376
 
401
377
  pool['named_ports'] ||= []
@@ -458,6 +434,11 @@ start = Time.now
458
434
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
459
435
  flags["project"] ||= MU::Cloud::Google.defaultProject(credentials)
460
436
  return if !MU::Cloud::Google::Habitat.isLive?(flags["project"], credentials)
437
+ filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
438
+ if !ignoremaster and MU.mu_public_ip
439
+ filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
440
+ end
441
+ MU.log "Placeholder: Google ServerPool artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
461
442
 
462
443
  if !flags["global"]
463
444
  ["region_autoscaler", "region_instance_group_manager"].each { |type|