cloud-mu 3.2.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/ansible/roles/mu-nat/tasks/main.yml +3 -0
  4. data/bin/mu-adopt +12 -1
  5. data/bin/mu-aws-setup +41 -7
  6. data/bin/mu-azure-setup +34 -0
  7. data/bin/mu-configure +214 -119
  8. data/bin/mu-gcp-setup +37 -2
  9. data/bin/mu-load-config.rb +2 -1
  10. data/bin/mu-node-manage +3 -0
  11. data/bin/mu-refresh-ssl +67 -0
  12. data/bin/mu-run-tests +28 -6
  13. data/bin/mu-self-update +30 -10
  14. data/bin/mu-upload-chef-artifacts +30 -26
  15. data/cloud-mu.gemspec +10 -8
  16. data/cookbooks/mu-master/attributes/default.rb +5 -1
  17. data/cookbooks/mu-master/metadata.rb +2 -2
  18. data/cookbooks/mu-master/recipes/default.rb +81 -26
  19. data/cookbooks/mu-master/recipes/init.rb +197 -62
  20. data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
  21. data/cookbooks/mu-master/recipes/vault.rb +78 -77
  22. data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
  23. data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
  24. data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
  25. data/cookbooks/mu-tools/attributes/default.rb +12 -0
  26. data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
  27. data/cookbooks/mu-tools/libraries/helper.rb +98 -4
  28. data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
  29. data/cookbooks/mu-tools/recipes/apply_security.rb +31 -9
  30. data/cookbooks/mu-tools/recipes/aws_api.rb +8 -2
  31. data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
  32. data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
  33. data/cookbooks/mu-tools/recipes/google_api.rb +7 -0
  34. data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
  35. data/cookbooks/mu-tools/resources/disk.rb +113 -42
  36. data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
  37. data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
  38. data/extras/Gemfile.lock.bootstrap +394 -0
  39. data/extras/bucketstubs/error.html +0 -0
  40. data/extras/bucketstubs/index.html +0 -0
  41. data/extras/clean-stock-amis +11 -3
  42. data/extras/generate-stock-images +6 -3
  43. data/extras/git_rpm/build.sh +20 -0
  44. data/extras/git_rpm/mugit.spec +53 -0
  45. data/extras/image-generators/AWS/centos7.yaml +19 -16
  46. data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
  47. data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
  48. data/extras/image-generators/VMWare/centos8.yaml +15 -0
  49. data/extras/openssl_rpm/build.sh +19 -0
  50. data/extras/openssl_rpm/mussl.spec +46 -0
  51. data/extras/python_rpm/muthon.spec +14 -4
  52. data/extras/ruby_rpm/muby.spec +9 -5
  53. data/extras/sqlite_rpm/build.sh +19 -0
  54. data/extras/sqlite_rpm/muqlite.spec +47 -0
  55. data/install/installer +7 -5
  56. data/modules/mommacat.ru +2 -2
  57. data/modules/mu.rb +14 -7
  58. data/modules/mu/adoption.rb +5 -5
  59. data/modules/mu/cleanup.rb +47 -25
  60. data/modules/mu/cloud.rb +29 -1
  61. data/modules/mu/cloud/dnszone.rb +0 -2
  62. data/modules/mu/cloud/machine_images.rb +1 -1
  63. data/modules/mu/cloud/providers.rb +6 -1
  64. data/modules/mu/cloud/resource_base.rb +16 -7
  65. data/modules/mu/cloud/ssh_sessions.rb +5 -1
  66. data/modules/mu/cloud/wrappers.rb +20 -7
  67. data/modules/mu/config.rb +28 -12
  68. data/modules/mu/config/bucket.rb +31 -2
  69. data/modules/mu/config/cache_cluster.rb +1 -1
  70. data/modules/mu/config/cdn.rb +100 -0
  71. data/modules/mu/config/container_cluster.rb +1 -1
  72. data/modules/mu/config/database.rb +3 -3
  73. data/modules/mu/config/dnszone.rb +4 -3
  74. data/modules/mu/config/endpoint.rb +1 -0
  75. data/modules/mu/config/firewall_rule.rb +1 -1
  76. data/modules/mu/config/function.rb +16 -7
  77. data/modules/mu/config/job.rb +89 -0
  78. data/modules/mu/config/notifier.rb +7 -18
  79. data/modules/mu/config/ref.rb +55 -9
  80. data/modules/mu/config/schema_helpers.rb +12 -3
  81. data/modules/mu/config/server.rb +11 -5
  82. data/modules/mu/config/server_pool.rb +2 -2
  83. data/modules/mu/config/vpc.rb +11 -10
  84. data/modules/mu/defaults/AWS.yaml +106 -106
  85. data/modules/mu/deploy.rb +40 -14
  86. data/modules/mu/groomers/chef.rb +2 -2
  87. data/modules/mu/master.rb +70 -3
  88. data/modules/mu/mommacat.rb +28 -9
  89. data/modules/mu/mommacat/daemon.rb +13 -7
  90. data/modules/mu/mommacat/naming.rb +2 -2
  91. data/modules/mu/mommacat/search.rb +16 -5
  92. data/modules/mu/mommacat/storage.rb +67 -32
  93. data/modules/mu/providers/aws.rb +298 -85
  94. data/modules/mu/providers/aws/alarm.rb +5 -5
  95. data/modules/mu/providers/aws/bucket.rb +284 -50
  96. data/modules/mu/providers/aws/cache_cluster.rb +26 -26
  97. data/modules/mu/providers/aws/cdn.rb +782 -0
  98. data/modules/mu/providers/aws/collection.rb +16 -16
  99. data/modules/mu/providers/aws/container_cluster.rb +84 -64
  100. data/modules/mu/providers/aws/database.rb +59 -55
  101. data/modules/mu/providers/aws/dnszone.rb +29 -12
  102. data/modules/mu/providers/aws/endpoint.rb +535 -50
  103. data/modules/mu/providers/aws/firewall_rule.rb +32 -26
  104. data/modules/mu/providers/aws/folder.rb +1 -1
  105. data/modules/mu/providers/aws/function.rb +300 -134
  106. data/modules/mu/providers/aws/group.rb +16 -14
  107. data/modules/mu/providers/aws/habitat.rb +4 -4
  108. data/modules/mu/providers/aws/job.rb +469 -0
  109. data/modules/mu/providers/aws/loadbalancer.rb +67 -45
  110. data/modules/mu/providers/aws/log.rb +17 -17
  111. data/modules/mu/providers/aws/msg_queue.rb +22 -13
  112. data/modules/mu/providers/aws/nosqldb.rb +99 -8
  113. data/modules/mu/providers/aws/notifier.rb +137 -65
  114. data/modules/mu/providers/aws/role.rb +119 -83
  115. data/modules/mu/providers/aws/search_domain.rb +166 -30
  116. data/modules/mu/providers/aws/server.rb +209 -118
  117. data/modules/mu/providers/aws/server_pool.rb +95 -130
  118. data/modules/mu/providers/aws/storage_pool.rb +19 -11
  119. data/modules/mu/providers/aws/user.rb +5 -5
  120. data/modules/mu/providers/aws/userdata/linux.erb +5 -4
  121. data/modules/mu/providers/aws/vpc.rb +109 -54
  122. data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
  123. data/modules/mu/providers/azure.rb +78 -12
  124. data/modules/mu/providers/azure/server.rb +20 -4
  125. data/modules/mu/providers/cloudformation/server.rb +1 -1
  126. data/modules/mu/providers/google.rb +21 -5
  127. data/modules/mu/providers/google/bucket.rb +1 -1
  128. data/modules/mu/providers/google/container_cluster.rb +1 -1
  129. data/modules/mu/providers/google/database.rb +1 -1
  130. data/modules/mu/providers/google/firewall_rule.rb +1 -1
  131. data/modules/mu/providers/google/folder.rb +7 -3
  132. data/modules/mu/providers/google/function.rb +66 -31
  133. data/modules/mu/providers/google/group.rb +1 -1
  134. data/modules/mu/providers/google/habitat.rb +1 -1
  135. data/modules/mu/providers/google/loadbalancer.rb +1 -1
  136. data/modules/mu/providers/google/role.rb +6 -3
  137. data/modules/mu/providers/google/server.rb +1 -1
  138. data/modules/mu/providers/google/server_pool.rb +1 -1
  139. data/modules/mu/providers/google/user.rb +1 -1
  140. data/modules/mu/providers/google/vpc.rb +28 -3
  141. data/modules/tests/aws-jobs-functions.yaml +46 -0
  142. data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
  143. data/modules/tests/centos6.yaml +4 -0
  144. data/modules/tests/centos7.yaml +4 -0
  145. data/modules/tests/ecs.yaml +2 -2
  146. data/modules/tests/eks.yaml +1 -1
  147. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  148. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  149. data/modules/tests/k8s.yaml +1 -1
  150. data/modules/tests/microservice_app.yaml +288 -0
  151. data/modules/tests/rds.yaml +5 -5
  152. data/modules/tests/regrooms/rds.yaml +5 -5
  153. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  154. data/modules/tests/super_complex_bok.yml +2 -2
  155. data/modules/tests/super_simple_bok.yml +2 -2
  156. metadata +42 -17
@@ -30,8 +30,7 @@ module MU
30
30
  :omnibus => "Jam everything into one monolothic configuration"
31
31
  }
32
32
 
33
-
34
- def initialize(clouds: MU::Cloud.supportedClouds, types: MU::Cloud.resource_types.keys, parent: nil, billing: nil, sources: nil, credentials: nil, group_by: :logical, savedeploys: false, diff: false, habitats: [], scrub_mu_isms: false, regions: [], merge: false)
33
+ def initialize(clouds: MU::Cloud.supportedClouds, types: MU::Cloud.resource_types.keys, parent: nil, billing: nil, sources: nil, credentials: nil, group_by: :logical, savedeploys: false, diff: false, habitats: [], scrub_mu_isms: false, regions: [], merge: false, pattern: nil)
35
34
  @scraped = {}
36
35
  @clouds = clouds
37
36
  @types = types
@@ -49,6 +48,7 @@ module MU
49
48
  @habitats ||= []
50
49
  @scrub_mu_isms = scrub_mu_isms
51
50
  @merge = merge
51
+ @pattern = pattern
52
52
  end
53
53
 
54
54
  # Walk cloud providers with available credentials to discover resources
@@ -127,6 +127,7 @@ module MU
127
127
  if obj.habitat and !cloudclass.listHabitats(credset).include?(obj.habitat)
128
128
  next
129
129
  end
130
+
130
131
  # XXX apply any filters (e.g. MU-ID tags)
131
132
  if obj.cloud_id.nil?
132
133
  MU.log "This damn thing gave me no cloud id, what do I even do with that", MU::ERR, details: obj
@@ -292,7 +293,7 @@ module MU
292
293
  start = Time.now
293
294
 
294
295
  kitten_cfg = obj.toKitten(rootparent: @default_parent, billing: @billing, habitats: @habitats, types: @types)
295
- if kitten_cfg
296
+ if kitten_cfg and (!@pattern or @pattern.match(kitten_cfg['name']))
296
297
  print "."
297
298
  kitten_cfg.delete("credentials") if @target_creds
298
299
  class_semaphore.synchronize {
@@ -791,8 +792,7 @@ module MU
791
792
  elsif hashcfg["id"] and !hashcfg["name"]
792
793
  hashcfg.delete("deploy_id")
793
794
  else
794
- pp parent.cloud_desc
795
- raise Incomplete, "Failed to resolve reference on behalf of #{parent}"
795
+ raise Incomplete.new "Failed to resolve reference on behalf of #{parent}", details: hashcfg
796
796
  end
797
797
  hashcfg.delete("deploy_id") if hashcfg['deploy_id'] == deploy.deploy_id
798
798
 
@@ -32,7 +32,7 @@ module MU
32
32
 
33
33
  # Resource types, in the order in which we generally have to clean them up
34
34
  # to disentangle them from one another.
35
- TYPES_IN_ORDER = ["Collection", "Endpoint", "Function", "ServerPool", "ContainerCluster", "SearchDomain", "Server", "MsgQueue", "Database", "CacheCluster", "StoragePool", "LoadBalancer", "NoSQLDB", "FirewallRule", "Alarm", "Notifier", "Log", "VPC", "Role", "Group", "User", "Bucket", "DNSZone", "Collection"]
35
+ TYPES_IN_ORDER = ["Collection", "CDN", "Endpoint", "Function", "ServerPool", "ContainerCluster", "SearchDomain", "Server", "MsgQueue", "Database", "CacheCluster", "StoragePool", "LoadBalancer", "NoSQLDB", "FirewallRule", "Alarm", "Notifier", "Log", "Job", "VPC", "Role", "Group", "User", "Bucket", "DNSZone", "Collection"]
36
36
 
37
37
  # Purge all resources associated with a deployment.
38
38
  # @param deploy_id [String]: The identifier of the deployment to remove (typically seen in the MU-ID tag on a resource).
@@ -52,6 +52,7 @@ module MU
52
52
  @onlycloud = onlycloud
53
53
  @skipcloud = skipcloud
54
54
  @ignoremaster = ignoremaster
55
+ @deploy_id = deploy_id
55
56
 
56
57
  if @skipcloud and @onlycloud # you actually mean noop
57
58
  @onlycloud = @skipcloud = false
@@ -217,51 +218,69 @@ module MU
217
218
  cloudclass = MU::Cloud.cloudClass(cloud)
218
219
  habitatclass = MU::Cloud.resourceClass(cloud, "Habitat")
219
220
 
220
- projects = []
221
- if habitats
222
- projects = habitats
223
- else
221
+ if !habitats
222
+ habitats = []
224
223
  if $MU_CFG and $MU_CFG[cloud.downcase] and
225
224
  $MU_CFG[cloud.downcase][credset] and
226
225
  $MU_CFG[cloud.downcase][credset]["project"]
227
226
  # XXX GCP credential schema needs an array for projects
228
- projects << $MU_CFG[cloud.downcase][credset]["project"]
227
+ habitats << $MU_CFG[cloud.downcase][credset]["project"]
229
228
  end
230
229
  begin
231
- projects.concat(cloudclass.listHabitats(credset, use_cache: false))
230
+ habitats.concat(cloudclass.listHabitats(credset, use_cache: false))
232
231
  rescue NoMethodError
233
232
  end
234
233
  end
235
234
 
236
- if projects == []
237
- projects << "" # dummy
235
+ if habitats == []
236
+ habitats << "" # dummy
238
237
  MU.log "Checking for #{cloud}/#{credset} resources from #{MU.deploy_id} in #{region}", MU::NOTICE
239
238
  end
240
- projects.uniq!
239
+ habitats.uniq!
241
240
 
242
241
  # We do these in an order that unrolls dependent resources
243
242
  # sensibly, and we hit :Collection twice because AWS
244
243
  # CloudFormation sometimes fails internally.
245
- projectthreads = []
246
- projects.each { |project|
247
- if habitats and !habitats.empty? and project != ""
248
- next if !habitats.include?(project)
244
+ habitat_threads = []
245
+ habitats.each { |habitat|
246
+ if habitats and !habitats.empty? and habitat != ""
247
+ next if !habitats.include?(habitat)
249
248
  end
250
- if @habitatsused and !@habitatsused.empty? and project != ""
251
- next if !@habitatsused.include?(project)
249
+ if @habitatsused and !@habitatsused.empty? and habitat != ""
250
+ next if !@habitatsused.include?(habitat)
252
251
  end
253
- next if !habitatclass.isLive?(project, credset)
252
+ next if !habitatclass.isLive?(habitat, credset)
254
253
 
255
- projectthreads << Thread.new {
254
+ habitat_threads << Thread.new {
255
+ Thread.current.thread_variable_set("name", "#{cloud}/#{credset}/#{habitat}/#{region}")
256
256
  Thread.abort_on_exception = false
257
- if !cleanHabitat(cloud, credset, region, project, global_vs_region_semaphore, global_done)
257
+ if !cleanHabitat(cloud, credset, region, habitat, global_vs_region_semaphore, global_done)
258
258
  had_failures = true
259
259
  end
260
260
  } # TYPES_IN_ORDER.each { |t|
261
- } # projects.each { |project|
262
- projectthreads.each do |t|
263
- t.join
264
- end
261
+ } # habitats.each { |habitat|
262
+
263
+ last_checkin = Time.now
264
+ begin
265
+ deletia = []
266
+ habitat_threads.each { |t|
267
+ if !t.status
268
+ t.join
269
+ deletia << t
270
+ end
271
+ }
272
+ deletia.each { |t|
273
+ habitat_threads.delete(t)
274
+ }
275
+ if (Time.now - last_checkin) > 120
276
+ list = habitat_threads.map { |t|
277
+ t.thread_variable_get("name") + (t.thread_variable_get("type") ? "/"+t.thread_variable_get("type") : "")
278
+ }
279
+ MU.log "Waiting on #{habitat_threads.size.to_s} habitat#{habitat_threads.size > 1 ? "s" : ""} in region #{region}", MU::NOTICE, details: list
280
+ last_checkin = Time.now
281
+ end
282
+ sleep 10 if !habitat_threads.empty?
283
+ end while !habitat_threads.empty?
265
284
 
266
285
  had_failures
267
286
  end
@@ -311,7 +330,8 @@ module MU
311
330
  next
312
331
  end
313
332
  }
314
- had_failures = true
333
+
334
+ had_failures
315
335
  end
316
336
  private_class_method :cleanHabitat
317
337
 
@@ -322,6 +342,7 @@ module MU
322
342
  # @param flags [Hash]:
323
343
  # @param region [String]:
324
344
  def self.call_cleanup(type, credset, provider, flags, region)
345
+ Thread.current.thread_variable_set("type", type)
325
346
  if @mommacat.nil? or @mommacat.numKittens(types: [type]) > 0
326
347
  if @mommacat
327
348
 
@@ -344,7 +365,8 @@ module MU
344
365
  region: region,
345
366
  cloud: provider,
346
367
  flags: flags,
347
- credentials: credset
368
+ credentials: credset,
369
+ deploy_id: @deploy_id
348
370
  )
349
371
  else
350
372
  true
data/modules/mu/cloud.rb CHANGED
@@ -148,6 +148,12 @@ module MU
148
148
  # Stub base class; real implementations generated at runtime
149
149
  class NoSQLDB;
150
150
  end
151
+ # Stub base class; real implementations generated at runtime
152
+ class Job;
153
+ end
154
+ # Stub base class; real implementations generated at runtime
155
+ class CDN;
156
+ end
151
157
 
152
158
  # Denotes a resource implementation which is missing significant
153
159
  # functionality or is largely untested.
@@ -436,7 +442,29 @@ module MU
436
442
  :cfg_plural => "nosqldbs",
437
443
  :interface => self.const_get("NoSQLDB"),
438
444
  :deps_wait_on_my_creation => true,
439
- :waits_on_parent_completion => true,
445
+ :waits_on_parent_completion => false,
446
+ :class => @@generic_class_methods,
447
+ :instance => @@generic_instance_methods + [:groom]
448
+ },
449
+ :Job => {
450
+ :has_multiples => false,
451
+ :can_live_in_vpc => false,
452
+ :cfg_name => "job",
453
+ :cfg_plural => "jobs",
454
+ :interface => self.const_get("Job"),
455
+ :deps_wait_on_my_creation => true,
456
+ :waits_on_parent_completion => false,
457
+ :class => @@generic_class_methods,
458
+ :instance => @@generic_instance_methods + [:groom]
459
+ },
460
+ :CDN => {
461
+ :has_multiples => false,
462
+ :can_live_in_vpc => false,
463
+ :cfg_name => "cdn",
464
+ :cfg_plural => "cdns",
465
+ :interface => self.const_get("CDN"),
466
+ :deps_wait_on_my_creation => true,
467
+ :waits_on_parent_completion => false,
440
468
  :class => @@generic_class_methods,
441
469
  :instance => @@generic_instance_methods + [:groom]
442
470
  }
@@ -29,8 +29,6 @@ module MU
29
29
 
30
30
  # Wrapper for {MU::Cloud::AWS::DNSZone.manageRecord}. Spawns threads to create all
31
31
  # requested records in background and returns immediately.
32
- # @param cfg [Array]: An array of parsed {MU::Config::BasketofKittens::dnszones::records} objects.
33
- # @param target [String]: Optional target for the records to be created. Overrides targets embedded in cfg records.
34
32
  def self.createRecordsFromConfig(*flags)
35
33
  cloudclass = MU::Cloud.resourceClass(MU::Config.defaultCloud, "DNSZone")
36
34
  if !flags.nil? and flags.size == 1
@@ -94,7 +94,7 @@ module MU
94
94
  else
95
95
  begin
96
96
  Timeout.timeout(2) do
97
- response = open("#{base_url}/#{cloud}.yaml").read
97
+ response = URI.open("#{base_url}/#{cloud}.yaml").read
98
98
  images ||= {}
99
99
  images.deep_merge!(YAML.load(response))
100
100
  break
@@ -64,7 +64,12 @@ module MU
64
64
  # code for each of its supported resource type classes.
65
65
  failed = []
66
66
  MU::Cloud.supportedClouds.each { |cloud|
67
- require "mu/providers/#{cloud.downcase}"
67
+ begin
68
+ require "mu/providers/#{cloud.downcase}"
69
+ rescue LoadError, Gem::MissingSpecError => e
70
+ MU.log "Error loading #{cloud} library, calls into this provider will fail", MU::ERR, details: e.message
71
+ next
72
+ end
68
73
  cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
69
74
  @@generic_class_methods_toplevel.each { |method|
70
75
  if !cloudclass.respond_to?(method)
@@ -227,6 +227,10 @@ module MU
227
227
  }
228
228
  end
229
229
 
230
+ MU::MommaCat.listOptionalTags.each_pair { |k, v|
231
+ @tags[k] ||= v if v
232
+ }
233
+
230
234
  if @cloudparentclass.respond_to?(:resourceInitHook)
231
235
  @cloudparentclass.resourceInitHook(self, @deploy)
232
236
  end
@@ -265,6 +269,7 @@ module MU
265
269
  attr_accessor :mu_windows_name # XXX might be ok as reader now
266
270
  end
267
271
  end
272
+ @tags["Name"] ||= @mu_name if @mu_name
268
273
  end
269
274
 
270
275
  end
@@ -733,7 +738,7 @@ module MU
733
738
  MU.log "Couldn't find existing resource #{ext_deploy["cloud_id"]}, #{ext_deploy["cloud_type"]}", MU::ERR if found.nil?
734
739
  @deploy.notify(ext_deploy["cloud_type"], found.config["name"], found.deploydata, mu_name: found.mu_name, triggering_node: @mu_name)
735
740
  elsif ext_deploy["mu_name"] && ext_deploy["deploy_id"]
736
- MU.log "#{ext_deploy["mu_name"]} / #{ext_deploy["deploy_id"]}"
741
+ MU.log "#{self}: Importing metadata for #{ext_deploy["cloud_type"]} #{ext_deploy["mu_name"]} from #{ext_deploy["deploy_id"]}"
737
742
  found = MU::MommaCat.findStray(
738
743
  @config['cloud'],
739
744
  ext_deploy["cloud_type"],
@@ -743,8 +748,11 @@ module MU
743
748
  dummy_ok: false
744
749
  ).first
745
750
 
746
- MU.log "Couldn't find existing resource #{ext_deploy["mu_name"]}/#{ext_deploy["deploy_id"]}, #{ext_deploy["cloud_type"]}", MU::ERR if found.nil?
747
- @deploy.notify(ext_deploy["cloud_type"], found.config["name"], found.deploydata, mu_name: ext_deploy["mu_name"], triggering_node: @mu_name)
751
+ if found.nil?
752
+ MU.log "Couldn't find existing resource #{ext_deploy["mu_name"]}/#{ext_deploy["deploy_id"]}, #{ext_deploy["cloud_type"]}", MU::ERR
753
+ else
754
+ @deploy.notify(ext_deploy["cloud_type"], found.config["name"], found.deploydata, mu_name: ext_deploy["mu_name"], triggering_node: @mu_name)
755
+ end
748
756
  else
749
757
  MU.log "Trying to find existing deploy, but either the cloud_id is not valid or no mu_name and deploy_id where provided", MU::ERR
750
758
  end
@@ -893,17 +901,18 @@ module MU
893
901
  elsif method == :notify
894
902
  if retval.nil?
895
903
  MU.log self.to_s+" didn't return any metadata from notify", MU::WARN, details: @cloudobj.cloud_desc
904
+ else
905
+ retval['cloud_id'] = @cloudobj.cloud_id.to_s if !@cloudobj.cloud_id.nil?
906
+ retval['mu_name'] = @cloudobj.mu_name if !@cloudobj.mu_name.nil?
907
+ @deploy.notify(self.class.cfg_plural, @config['name'], retval, triggering_node: @cloudobj, delayed_save: @delayed_save) if !@deploy.nil?
896
908
  end
897
- retval['cloud_id'] = @cloudobj.cloud_id.to_s if !@cloudobj.cloud_id.nil?
898
- retval['mu_name'] = @cloudobj.mu_name if !@cloudobj.mu_name.nil?
899
- @deploy.notify(self.class.cfg_plural, @config['name'], retval, triggering_node: @cloudobj, delayed_save: @delayed_save) if !@deploy.nil?
900
909
  end
901
910
  @method_semaphore.synchronize {
902
911
  @method_locks.delete(method)
903
912
  }
904
913
 
905
914
  @deploydata = @cloudobj.deploydata
906
- @config = @cloudobj.config
915
+ @config = MU::Config.manxify(@cloudobj.config)
907
916
  retval
908
917
  end
909
918
  } # end instance method list
@@ -125,7 +125,7 @@ module MU
125
125
  end
126
126
  end
127
127
  end
128
- rescue RuntimeError => e
128
+ rescue RuntimeError, IOError => e
129
129
  raise MU::Cloud::BootstrapTempFail, "Got #{e.inspect} performing initial SSH connect tasks, will try again"
130
130
  end
131
131
 
@@ -187,6 +187,10 @@ module MU
187
187
  retry
188
188
  # rescue SystemCallError, Timeout::Error, Errno::ECONNRESET, Errno::EHOSTUNREACH, Net::SSH::Proxy::ConnectError, SocketError, Net::SSH::Disconnect, Net::SSH::AuthenticationFailed, IOError, Net::SSH::ConnectionTimeout, Net::SSH::Proxy::ConnectError, MU::Cloud::NetSSHFail => e
189
189
  rescue SystemExit, Timeout::Error, Net::SSH::AuthenticationFailed, Net::SSH::Disconnect, Net::SSH::ConnectionTimeout, Net::SSH::Proxy::ConnectError, Net::SSH::Exception, Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::EPIPE, SocketError, IOError => e
190
+ if !active?
191
+ raise MuError, "Server #{@mu_name} disappeared while I was attempting to log into it"
192
+ end
193
+
190
194
  begin
191
195
  session.close if !session.nil?
192
196
  rescue Net::SSH::Disconnect, IOError => e
@@ -103,14 +103,23 @@ module MU
103
103
  next
104
104
  end
105
105
 
106
- found = cloudclass.find(args)
107
- if !found.nil?
108
- if found.is_a?(Hash)
109
- allfound.merge!(found)
110
- else
111
- raise MuError, "#{cloudclass}.find returned a non-Hash result"
112
- end
106
+ credsets = if args[:credentials]
107
+ [args[:credentials]]
108
+ else
109
+ cloudbase.listCredentials
113
110
  end
111
+
112
+ credsets.each { |creds|
113
+ args[:credentials] = creds
114
+ found = cloudclass.find(args)
115
+ if !found.nil?
116
+ if found.is_a?(Hash)
117
+ allfound.merge!(found)
118
+ else
119
+ raise MuError, "#{cloudclass}.find returned a non-Hash result"
120
+ end
121
+ end
122
+ }
114
123
  rescue MuCloudResourceNotImplemented
115
124
  end
116
125
  }
@@ -126,6 +135,10 @@ module MU
126
135
  clouds = [params[:cloud]]
127
136
  params.delete(:cloud)
128
137
  end
138
+ params[:deploy_id] ||= MU.deploy_id
139
+ if !params[:deploy_id] or params[:deploy_id].empty?
140
+ raise MuError, "Can't call cleanup methods without a deploy id"
141
+ end
129
142
 
130
143
  clouds.each { |cloud|
131
144
  begin
data/modules/mu/config.rb CHANGED
@@ -437,27 +437,27 @@ module MU
437
437
  # @param type [String]
438
438
  # @param phase [String]
439
439
  # @param no_create_wait [Boolean]
440
- def self.addDependency(resource, name, type, phase: nil, no_create_wait: false)
441
- if ![nil, "create", "groom"].include?(phase)
442
- raise MuError, "Invalid phase '#{phase}' while adding dependency #{type} #{name} to #{resource['name']}"
440
+ def self.addDependency(resource, name, type, their_phase: "create", my_phase: nil)
441
+ if ![nil, "create", "groom"].include?(their_phase)
442
+ raise MuError, "Invalid their_phase '#{their_phase}' while adding dependency #{type} #{name} to #{resource['name']}"
443
443
  end
444
444
  resource['dependencies'] ||= []
445
445
  _shortclass, cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(type)
446
446
 
447
447
  resource['dependencies'].each { |dep|
448
448
  if dep['type'] == cfg_name and dep['name'].to_s == name.to_s
449
- dep["no_create_wait"] = no_create_wait
450
- dep["phase"] = phase if phase
449
+ dep["their_phase"] = their_phase if their_phase
450
+ dep["my_phase"] = my_phase if my_phase
451
451
  return
452
452
  end
453
453
  }
454
454
 
455
455
  newdep = {
456
456
  "type" => cfg_name,
457
- "name" => name.to_s,
458
- "no_create_wait" => no_create_wait
457
+ "name" => name.to_s
459
458
  }
460
- newdep["phase"] = phase if phase
459
+ newdep["their_phase"] = their_phase if their_phase
460
+ newdep["my_phase"] = my_phase if my_phase
461
461
 
462
462
  resource['dependencies'] << newdep
463
463
 
@@ -746,7 +746,7 @@ module MU
746
746
  next if !acl_include["name"] and !acl_include["rule_name"]
747
747
  acl_include["name"] ||= acl_include["rule_name"]
748
748
  if haveLitterMate?(acl_include["name"], "firewall_rules")
749
- MU::Config.addDependency(descriptor, acl_include["name"], "firewall_rule", no_create_wait: (cfg_name == "vpc"))
749
+ MU::Config.addDependency(descriptor, acl_include["name"], "firewall_rule", my_phase: ((cfg_name == "vpc") ? "groom" : "create"))
750
750
  elsif acl_include["name"]
751
751
  MU.log shortclass.to_s+" #{descriptor['name']} depends on FirewallRule #{acl_include["name"]}, but no such rule declared.", MU::ERR
752
752
  ok = false
@@ -892,6 +892,10 @@ module MU
892
892
  deleteme = []
893
893
 
894
894
  resource["dependencies"].each { |dependency|
895
+ dependency["their_phase"] ||= dependency["phase"]
896
+ dependency.delete("phase")
897
+ dependency["my_phase"] ||= dependency["no_create_wait"] ? "groom" : "create"
898
+ dependency.delete("no_create_wait")
895
899
  # make sure the thing we depend on really exists
896
900
  sibling = haveLitterMate?(dependency['name'], dependency['type'])
897
901
  if !sibling
@@ -929,10 +933,22 @@ module MU
929
933
  end
930
934
  end
931
935
 
936
+ if dependency['their_phase'] == "groom"
937
+ sibling['dependencies'].each { |sib_dep|
938
+ next if sib_dep['type'] != cfg_name or sib_dep['their_phase'] != "groom"
939
+ cousin = haveLitterMate?(sib_dep['name'], sib_dep['type'])
940
+ if cousin and cousin['name'] == resource['name']
941
+ MU.log "Circular dependency between #{type} #{resource['name']} <=> #{dependency['type']} #{dependency['name']}", MU::ERR, details: [ resource['name'] => dependency, sibling['name'] => sib_dep ]
942
+ ok = false
943
+ end
944
+ }
945
+ end
946
+
932
947
  # Check for a circular relationship that will lead to a deadlock
933
948
  # when creating resource. This only goes one layer deep, and does
934
949
  # not consider groom-phase deadlocks.
935
- if dependency['phase'] == "groom" or dependency['no_create_wait'] or (
950
+ if dependency['their_phase'] == "groom" or
951
+ dependency['my_phase'] == "groom" or (
936
952
  !MU::Cloud.resourceClass(sibling['cloud'], type).deps_wait_on_my_creation and
937
953
  !MU::Cloud.resourceClass(resource['cloud'], type).waits_on_parent_completion
938
954
  )
@@ -941,7 +957,7 @@ module MU
941
957
 
942
958
  if sibling['dependencies']
943
959
  sibling['dependencies'].each { |sib_dep|
944
- next if sib_dep['type'] != cfg_name or sib_dep['no_create_wait']
960
+ next if sib_dep['type'] != cfg_name or sib_dep['my_phase'] == "groom"
945
961
  cousin = haveLitterMate?(sib_dep['name'], sib_dep['type'])
946
962
  if cousin and cousin['name'] == resource['name']
947
963
  MU.log "Circular dependency between #{type} #{resource['name']} <=> #{dependency['type']} #{dependency['name']}", MU::ERR, details: [ resource['name'] => dependency, sibling['name'] => sib_dep ]
@@ -1238,7 +1254,7 @@ module MU
1238
1254
  "port" => db["port"],
1239
1255
  "sgs" => [cfg_name+server['name']]
1240
1256
  }
1241
- MU::Config.addDependency(ruleset, cfg_name+server['name'], "firewall_rule", no_create_wait: true)
1257
+ MU::Config.addDependency(ruleset, cfg_name+server['name'], "firewall_rule", my_phase: "groom")
1242
1258
  end
1243
1259
  }
1244
1260
  }