cloud-mu 3.2.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }