cloud-mu 3.1.5 → 3.3.2

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -1
  3. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  4. data/ansible/roles/mu-windows/files/config.xml +76 -0
  5. data/ansible/roles/mu-windows/tasks/main.yml +16 -0
  6. data/bin/mu-adopt +16 -12
  7. data/bin/mu-azure-tests +57 -0
  8. data/bin/mu-cleanup +2 -4
  9. data/bin/mu-configure +52 -0
  10. data/bin/mu-deploy +3 -3
  11. data/bin/mu-findstray-tests +25 -0
  12. data/bin/mu-gen-docs +2 -4
  13. data/bin/mu-load-config.rb +2 -1
  14. data/bin/mu-node-manage +15 -16
  15. data/bin/mu-run-tests +37 -12
  16. data/cloud-mu.gemspec +3 -3
  17. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  18. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  19. data/cookbooks/mu-tools/libraries/helper.rb +1 -1
  20. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  21. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  22. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  23. data/cookbooks/mu-tools/recipes/windows-client.rb +25 -22
  24. data/extras/clean-stock-amis +25 -19
  25. data/extras/generate-stock-images +1 -0
  26. data/extras/image-generators/AWS/win2k12.yaml +2 -0
  27. data/extras/image-generators/AWS/win2k16.yaml +2 -0
  28. data/extras/image-generators/AWS/win2k19.yaml +2 -0
  29. data/modules/mommacat.ru +1 -1
  30. data/modules/mu.rb +86 -98
  31. data/modules/mu/adoption.rb +373 -58
  32. data/modules/mu/cleanup.rb +214 -303
  33. data/modules/mu/cloud.rb +128 -1733
  34. data/modules/mu/cloud/database.rb +49 -0
  35. data/modules/mu/cloud/dnszone.rb +44 -0
  36. data/modules/mu/cloud/machine_images.rb +212 -0
  37. data/modules/mu/cloud/providers.rb +81 -0
  38. data/modules/mu/cloud/resource_base.rb +929 -0
  39. data/modules/mu/cloud/server.rb +40 -0
  40. data/modules/mu/cloud/server_pool.rb +1 -0
  41. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  42. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  43. data/modules/mu/cloud/wrappers.rb +169 -0
  44. data/modules/mu/config.rb +123 -81
  45. data/modules/mu/config/alarm.rb +2 -6
  46. data/modules/mu/config/bucket.rb +32 -3
  47. data/modules/mu/config/cache_cluster.rb +2 -2
  48. data/modules/mu/config/cdn.rb +100 -0
  49. data/modules/mu/config/collection.rb +1 -1
  50. data/modules/mu/config/container_cluster.rb +7 -2
  51. data/modules/mu/config/database.rb +84 -105
  52. data/modules/mu/config/database.yml +1 -2
  53. data/modules/mu/config/dnszone.rb +5 -4
  54. data/modules/mu/config/doc_helpers.rb +5 -6
  55. data/modules/mu/config/endpoint.rb +2 -1
  56. data/modules/mu/config/firewall_rule.rb +3 -19
  57. data/modules/mu/config/folder.rb +1 -1
  58. data/modules/mu/config/function.rb +17 -8
  59. data/modules/mu/config/group.rb +1 -1
  60. data/modules/mu/config/habitat.rb +1 -1
  61. data/modules/mu/config/job.rb +89 -0
  62. data/modules/mu/config/loadbalancer.rb +57 -11
  63. data/modules/mu/config/log.rb +1 -1
  64. data/modules/mu/config/msg_queue.rb +1 -1
  65. data/modules/mu/config/nosqldb.rb +1 -1
  66. data/modules/mu/config/notifier.rb +8 -19
  67. data/modules/mu/config/ref.rb +92 -14
  68. data/modules/mu/config/role.rb +1 -1
  69. data/modules/mu/config/schema_helpers.rb +38 -37
  70. data/modules/mu/config/search_domain.rb +1 -1
  71. data/modules/mu/config/server.rb +12 -13
  72. data/modules/mu/config/server_pool.rb +3 -7
  73. data/modules/mu/config/storage_pool.rb +1 -1
  74. data/modules/mu/config/tail.rb +11 -0
  75. data/modules/mu/config/user.rb +1 -1
  76. data/modules/mu/config/vpc.rb +27 -23
  77. data/modules/mu/config/vpc.yml +0 -1
  78. data/modules/mu/defaults/AWS.yaml +90 -90
  79. data/modules/mu/defaults/Azure.yaml +1 -0
  80. data/modules/mu/defaults/Google.yaml +1 -0
  81. data/modules/mu/deploy.rb +34 -20
  82. data/modules/mu/groomer.rb +16 -1
  83. data/modules/mu/groomers/ansible.rb +69 -4
  84. data/modules/mu/groomers/chef.rb +51 -4
  85. data/modules/mu/logger.rb +120 -144
  86. data/modules/mu/master.rb +97 -4
  87. data/modules/mu/mommacat.rb +160 -874
  88. data/modules/mu/mommacat/daemon.rb +23 -14
  89. data/modules/mu/mommacat/naming.rb +110 -3
  90. data/modules/mu/mommacat/search.rb +497 -0
  91. data/modules/mu/mommacat/storage.rb +252 -194
  92. data/modules/mu/{clouds → providers}/README.md +1 -1
  93. data/modules/mu/{clouds → providers}/aws.rb +258 -57
  94. data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
  95. data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
  96. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
  97. data/modules/mu/providers/aws/cdn.rb +782 -0
  98. data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
  99. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +95 -84
  100. data/modules/mu/providers/aws/database.rb +1744 -0
  101. data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
  102. data/modules/mu/providers/aws/endpoint.rb +1072 -0
  103. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
  104. data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
  105. data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
  106. data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
  107. data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
  108. data/modules/mu/providers/aws/job.rb +466 -0
  109. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
  110. data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
  111. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
  112. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
  113. data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
  114. data/modules/mu/{clouds → providers}/aws/role.rb +76 -48
  115. data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
  116. data/modules/mu/{clouds → providers}/aws/server.rb +66 -98
  117. data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
  118. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
  119. data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
  120. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  121. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
  122. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
  123. data/modules/mu/{clouds → providers}/aws/vpc.rb +143 -74
  124. data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
  125. data/modules/mu/{clouds → providers}/azure.rb +13 -0
  126. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
  127. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
  128. data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
  129. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
  130. data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
  131. data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
  132. data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
  133. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  134. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  135. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  136. data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
  137. data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
  138. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  139. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  140. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  141. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  142. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  143. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  144. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  145. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  146. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  147. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  148. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
  149. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  150. data/modules/mu/{clouds → providers}/google.rb +29 -6
  151. data/modules/mu/{clouds → providers}/google/bucket.rb +4 -4
  152. data/modules/mu/{clouds → providers}/google/container_cluster.rb +38 -20
  153. data/modules/mu/{clouds → providers}/google/database.rb +5 -12
  154. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
  155. data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
  156. data/modules/mu/{clouds → providers}/google/function.rb +6 -6
  157. data/modules/mu/{clouds → providers}/google/group.rb +9 -17
  158. data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
  159. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
  160. data/modules/mu/{clouds → providers}/google/role.rb +50 -31
  161. data/modules/mu/{clouds → providers}/google/server.rb +41 -24
  162. data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
  163. data/modules/mu/{clouds → providers}/google/user.rb +34 -24
  164. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  165. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  166. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  167. data/modules/mu/{clouds → providers}/google/vpc.rb +45 -14
  168. data/modules/tests/aws-jobs-functions.yaml +46 -0
  169. data/modules/tests/centos6.yaml +15 -0
  170. data/modules/tests/centos7.yaml +15 -0
  171. data/modules/tests/centos8.yaml +12 -0
  172. data/modules/tests/ecs.yaml +2 -2
  173. data/modules/tests/eks.yaml +1 -1
  174. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  175. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  176. data/modules/tests/microservice_app.yaml +288 -0
  177. data/modules/tests/rds.yaml +108 -0
  178. data/modules/tests/regrooms/rds.yaml +123 -0
  179. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  180. data/modules/tests/super_complex_bok.yml +2 -2
  181. data/modules/tests/super_simple_bok.yml +3 -5
  182. data/spec/mu/clouds/azure_spec.rb +2 -2
  183. metadata +122 -92
  184. data/modules/mu/clouds/aws/database.rb +0 -1974
  185. data/modules/mu/clouds/aws/endpoint.rb +0 -596
@@ -14,7 +14,7 @@
14
14
 
15
15
  module MU
16
16
  class Config
17
- # Basket of Kittens config schema and parser logic. See modules/mu/clouds/*/msg_queue.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/msg_queue.rb
18
18
  class MsgQueue
19
19
 
20
20
  # Base configuration schema for a MsgQueue
@@ -14,7 +14,7 @@
14
14
 
15
15
  module MU
16
16
  class Config
17
- # Basket of Kittens config schema and parser logic. See modules/mu/clouds/*/nosqldb.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/nosqldb.rb
18
18
  class NoSQLDB
19
19
 
20
20
  # Base configuration schema for a Bucket
@@ -14,7 +14,7 @@
14
14
 
15
15
  module MU
16
16
  class Config
17
- # Basket of Kittens config schema and parser logic. See modules/mu/clouds/*/notifier.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/notifier.rb
18
18
  class Notifier
19
19
 
20
20
  # Base configuration schema for a Notifier
@@ -36,12 +36,12 @@ module MU
36
36
  "items" => {
37
37
  "type" => "object",
38
38
  "description" => "A list of people or resources which should receive notifications",
39
- "required" => ["endpoint"],
40
39
  "properties" => {
41
40
  "endpoint" => {
42
41
  "type" => "string",
43
- "description" => "The endpoint which should be subscribed to this notifier, typically an email address or SMS-enabled phone number."
44
- }
42
+ "description" => "Shorthand for an endpoint which should be subscribed to this notifier, typically an email address or SMS-enabled phone number. For complex cases, such as referencing an AWS Lambda function defined elsewhere in your Mu stack, use +resource+ instead."
43
+ },
44
+ "resource" => MU::Config::Ref.schema(desc: "A cloud resource that is a valid notification target for this notifier. For simple use cases, such as external email addresses or SMS, use +endpoint+ instead.")
45
45
  }
46
46
  }
47
47
  }
@@ -56,23 +56,12 @@ module MU
56
56
  def self.validate(notifier, _configurator)
57
57
  ok = true
58
58
 
59
+
59
60
  if notifier['subscriptions']
60
61
  notifier['subscriptions'].each { |sub|
61
- if !sub["type"]
62
- if sub["endpoint"].match(/^http:/i)
63
- sub["type"] = "http"
64
- elsif sub["endpoint"].match(/^https:/i)
65
- sub["type"] = "https"
66
- elsif sub["endpoint"].match(/^sqs:/i)
67
- sub["type"] = "sqs"
68
- elsif sub["endpoint"].match(/^\+?[\d\-]+$/)
69
- sub["type"] = "sms"
70
- elsif sub["endpoint"].match(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i)
71
- sub["type"] = "email"
72
- else
73
- MU.log "Notifier #{notifier['name']} subscription #{sub['endpoint']} did not specify a type, and I'm unable to guess one", MU::ERR
74
- ok = false
75
- end
62
+ if !sub['endpoint'] and !sub['resource']
63
+ MU.log "Notifier '#{notifier['name']}' must specify either resource or endpoint in subscription", MU::ERR, details: sub
64
+ ok = false
76
65
  end
77
66
  }
78
67
  end
@@ -121,6 +121,10 @@ module MU
121
121
  @deploy_id = @mommacat.deploy_id
122
122
  end
123
123
 
124
+ # canonicalize the 'type' argument
125
+ _shortclass, _cfg_name, cfg_plural, _classname, _attrs = MU::Cloud.getResourceNames(@type, false)
126
+ @type = cfg_plural if cfg_plural
127
+
124
128
  kitten(shallow: true) if @mommacat # try to populate the actual cloud object for this
125
129
  end
126
130
 
@@ -130,10 +134,34 @@ module MU
130
134
  self.to_s <=> other.to_s
131
135
  end
132
136
 
137
+ # Lets callers access us like a {Hash}
138
+ # @param attribute [String,Symbol]
139
+ def [](attribute)
140
+ if respond_to?(attribute.to_sym)
141
+ send(attribute.to_sym)
142
+ else
143
+ nil
144
+ end
145
+ end
146
+
147
+ # Lets callers set attributes like a {Hash}
148
+ # @param attribute [String,Symbol]
149
+ def []=(attribute, value)
150
+ instance_variable_set("@#{attribute.to_s}".to_sym, value)
151
+ self.class.define_reader(attribute)
152
+ end
153
+
154
+ # Unset an attribute. Sort of. We can't actually do that, so nil it out
155
+ # and we get the behavior we want.
156
+ def delete(attribute)
157
+ attribute = ("@"+attribute).to_sym if attribute.to_s !~ /^@/
158
+ instance_variable_set(attribute.to_sym, nil)
159
+ end
160
+
133
161
  # Base configuration schema for declared kittens referencing other cloud objects. This is essentially a set of filters that we're going to pass to {MU::MommaCat.findStray}.
134
162
  # @param aliases [Array<Hash>]: Key => value mappings to set backwards-compatibility aliases for attributes, such as the ubiquitous +vpc_id+ (+vpc_id+ => +id+).
135
163
  # @return [Hash]
136
- def self.schema(aliases = [], type: nil, parent_obj: nil, desc: nil, omit_fields: [])
164
+ def self.schema(aliases = [], type: nil, parent_obj: nil, desc: nil, omit_fields: [], any_type: false)
137
165
  parent_obj ||= caller[1].gsub(/.*?\/([^\.\/]+)\.rb:.*/, '\1')
138
166
  desc ||= "Reference a #{type ? "'#{type}' resource" : "resource" } from this #{parent_obj ? "'#{parent_obj}'" : "" } resource"
139
167
  schema = {
@@ -188,7 +216,9 @@ module MU
188
216
  }
189
217
  end
190
218
 
191
- if !type.nil?
219
+ if any_type
220
+ schema["properties"]["type"].delete("enum")
221
+ elsif !type.nil?
192
222
  schema["required"] = ["type"]
193
223
  schema["properties"]["type"]["default"] = type
194
224
  schema["properties"]["type"]["enum"] = [type]
@@ -208,6 +238,13 @@ module MU
208
238
  schema
209
239
  end
210
240
 
241
+ # Is our +@type+ attribute a Mu-supported type, or some rando string?
242
+ # @return [Boolean]
243
+ def is_mu_type?
244
+ _shortclass, _cfg_name, type, _classname, _attrs = MU::Cloud.getResourceNames(@type, false)
245
+ !type.nil?
246
+ end
247
+
211
248
  # Decompose into a plain-jane {MU::Config::BasketOfKittens} hash fragment,
212
249
  # of the sort that would have been used to declare this reference in the
213
250
  # first place.
@@ -249,23 +286,46 @@ module MU
249
286
  # called in a live deploy, which is to say that if called during initial
250
287
  # configuration parsing, results may be incorrect.
251
288
  # @param mommacat [MU::MommaCat]: A deploy object which will be searched for the referenced resource if provided, before restoring to broader, less efficient searches.
252
- def kitten(mommacat = @mommacat, shallow: false)
253
- return nil if !@cloud or !@type
289
+ def kitten(mommacat = @mommacat, shallow: false, debug: false, cloud: nil)
290
+ cloud ||= @cloud
291
+ return nil if !cloud or !@type
292
+
293
+ _shortclass, _cfg_name, cfg_plural, _classname, _attrs = MU::Cloud.getResourceNames(@type, false)
294
+ if cfg_plural
295
+ @type = cfg_plural # make sure this is the thing we expect
296
+ else
297
+ return nil # we don't do non-muish resources
298
+ end
299
+
300
+ loglevel = debug ? MU::NOTICE : MU::DEBUG
301
+
302
+ if debug
303
+ MU.log "this mf kitten", MU::WARN, details: caller
304
+ end
254
305
 
255
306
  if @obj
256
307
  @deploy_id ||= @obj.deploy_id
257
308
  @id ||= @obj.cloud_id
258
- @name ||= @obj.config['name']
309
+ @name ||= @obj.config['name'] if @obj.config
259
310
  return @obj
260
311
  end
261
312
 
262
- if mommacat
263
- @obj = mommacat.findLitterMate(type: @type, name: @name, cloud_id: @id, credentials: @credentials, debug: false)
313
+ if mommacat and !caller.grep(/`findLitterMate'/) # XXX the dumbest
314
+ MU.log "Looking for #{@type} #{@name} #{@id} in deploy #{mommacat.deploy_id}", loglevel
315
+ begin
316
+ @obj = mommacat.findLitterMate(type: @type, name: @name, cloud_id: @id, credentials: @credentials, debug: debug)
317
+ rescue StandardError => e
318
+ if e.message =~ /deadlock/
319
+ MU.log "Saw a recursive deadlock trying to fetch kitten for Ref object in deploy #{mmommacat.deploy_id}", MU::ERR, details: to_h
320
+ end
321
+ raise e
322
+ end
264
323
  if @obj # initialize missing attributes, if we can
265
324
  @id ||= @obj.cloud_id
266
325
  @mommacat ||= mommacat
267
326
  @obj.intoDeploy(@mommacat) # make real sure these are set
268
327
  @deploy_id ||= mommacat.deploy_id
328
+
269
329
  if !@name
270
330
  if @obj.config and @obj.config['name']
271
331
  @name = @obj.config['name']
@@ -282,7 +342,8 @@ end
282
342
  end
283
343
  end
284
344
 
285
- if !@obj and !(@cloud == "Google" and @id and @type == "users" and MU::Cloud::Google::User.cannedServiceAcctName?(@id)) and !shallow
345
+ if !@obj and !(cloud == "Google" and @id and @type == "users" and MU::Cloud.resourceClass("Google", "User").cannedServiceAcctName?(@id)) and !shallow
346
+ try_deploy_id = @deploy_id
286
347
 
287
348
  begin
288
349
  hab_arg = if @habitat.nil?
@@ -295,27 +356,44 @@ end
295
356
  [@habitat.to_s]
296
357
  end
297
358
 
359
+ MU.log "Ref#kitten calling findStray", loglevel, details: {
360
+ cloud: cloud,
361
+ type: @type,
362
+ name: @name,
363
+ cloud_id: @id,
364
+ deploy_id: try_deploy_id,
365
+ region: @region,
366
+ habitats: hab_arg,
367
+ credentials: @credentials,
368
+ dummy_ok: (["habitats", "folders", "users", "groups", "vpcs"].include?(@type))
369
+ }
370
+
298
371
  found = MU::MommaCat.findStray(
299
- @cloud,
372
+ cloud,
300
373
  @type,
301
374
  name: @name,
302
375
  cloud_id: @id,
303
- deploy_id: @deploy_id,
376
+ deploy_id: try_deploy_id,
304
377
  region: @region,
305
378
  habitats: hab_arg,
306
379
  credentials: @credentials,
307
380
  dummy_ok: (["habitats", "folders", "users", "groups", "vpcs"].include?(@type))
308
381
  )
382
+ MU.log "Ref#kitten results from findStray", loglevel, details: found
309
383
  @obj ||= found.first if found
384
+ rescue MU::MommaCat::MultipleMatches => e
385
+ if try_deploy_id.nil? and MU.deploy_id
386
+ MU.log "Attempting to narrow down #{cloud} #{@type} to #{MU.deploy_id}", MU::NOTICE
387
+ try_deploy_id = MU.deploy_id
388
+ retry
389
+ else
390
+ raise e
391
+ end
310
392
  rescue ThreadError => e
311
393
  # Sometimes MommaCat calls us in a potential deadlock situation;
312
394
  # don't be the cause of a fatal error if so, we don't need this
313
395
  # object that badly.
314
396
  raise e if !e.message.match(/recursive locking/)
315
- rescue SystemExit
316
- # XXX this is temporary, to cope with some debug stuff that's in findStray
317
- # for the nonce
318
- return
319
397
  end
320
398
  end
321
399
 
@@ -14,7 +14,7 @@
14
14
 
15
15
  module MU
16
16
  class Config
17
- # Basket of Kittens config schema and parser logic. See modules/mu/clouds/*/role.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/role.rb
18
18
  class Role
19
19
 
20
20
  # Base configuration schema for a Group
@@ -22,10 +22,9 @@ module MU
22
22
  def self.defaultCloud
23
23
  configured = {}
24
24
  MU::Cloud.supportedClouds.each { |cloud|
25
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
26
25
  if $MU_CFG[cloud.downcase] and !$MU_CFG[cloud.downcase].empty?
27
26
  configured[cloud] = $MU_CFG[cloud.downcase].size
28
- configured[cloud] += 0.5 if cloudclass.hosted? # tiebreaker
27
+ configured[cloud] += 0.5 if MU::Cloud.cloudClass(cloud).hosted? # tiebreaker
29
28
  end
30
29
  }
31
30
  if configured.size > 0
@@ -34,8 +33,7 @@ module MU
34
33
  }.first
35
34
  else
36
35
  MU::Cloud.supportedClouds.each { |cloud|
37
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
38
- return cloud if cloudclass.hosted?
36
+ return cloud if MU::Cloud.cloudClass(cloud).hosted?
39
37
  }
40
38
  return MU::Cloud.supportedClouds.first
41
39
  end
@@ -83,9 +81,8 @@ module MU
83
81
  @@loadfails = []
84
82
  MU::Cloud.availableClouds.each { |cloud|
85
83
  next if @@loadfails.include?(cloud)
86
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
87
84
  begin
88
- regions = cloudclass.listRegions()
85
+ regions = MU::Cloud.cloudClass(cloud).listRegions()
89
86
  @@allregions.concat(regions) if regions
90
87
  rescue MU::MuError => e
91
88
  @@loadfails << cloud
@@ -100,7 +97,7 @@ module MU
100
97
  @@allregions = []
101
98
  MU::Cloud.availableClouds.each { |cloud|
102
99
  next if @@loadfails.include?(cloud)
103
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud)
100
+ cloudclass = MU::Cloud.cloudClass(cloud)
104
101
  begin
105
102
  return @@allregions if !cloudclass.listRegions()
106
103
  @@allregions.concat(cloudclass.listRegions())
@@ -178,27 +175,27 @@ module MU
178
175
  {
179
176
  "type" => "array",
180
177
  "items" => {
181
- "type" => "object",
182
- "description" => "Declare other objects which this resource requires. This resource will wait until the others are available to create itself.",
183
- "required" => ["name", "type"],
184
- "additionalProperties" => false,
185
- "properties" => {
186
- "name" => {"type" => "string"},
187
- "type" => {
188
- "type" => "string",
189
- "enum" => MU::Cloud.resource_types.values.map { |v| v[:cfg_name] }
190
- },
191
- "phase" => {
192
- "type" => "string",
193
- "description" => "Which part of the creation process of the resource we depend on should we wait for before starting our own creation? Defaults are usually sensible, but sometimes you want, say, a Server to wait on another Server to be completely ready (through its groom phase) before starting up.",
194
- "enum" => ["create", "groom"]
195
- },
196
- "no_create_wait" => {
197
- "type" => "boolean",
198
- "default" => false,
199
- "description" => "By default, it's assumed that we want to wait on our parents' creation phase, in addition to whatever is declared in this stanza. Setting this flag will bypass waiting on our parent resource's creation, so that our create or groom phase can instead depend only on the parent's groom phase. "
200
- }
178
+ "type" => "object",
179
+ "description" => "Declare other objects which this resource requires. This resource will wait until the others are available to create itself.",
180
+ "required" => ["name", "type"],
181
+ "additionalProperties" => false,
182
+ "properties" => {
183
+ "name" => {"type" => "string"},
184
+ "type" => {
185
+ "type" => "string",
186
+ "enum" => MU::Cloud.resource_types.values.map { |v| v[:cfg_name] }
187
+ },
188
+ "phase" => {
189
+ "type" => "string",
190
+ "description" => "Which part of the creation process of the resource we depend on should we wait for before starting our own creation? Defaults are usually sensible, but sometimes you want, say, a Server to wait on another Server to be completely ready (through its groom phase) before starting up.",
191
+ "enum" => ["create", "groom"]
192
+ },
193
+ "no_create_wait" => {
194
+ "type" => "boolean",
195
+ "default" => false,
196
+ "description" => "By default, it's assumed that we want to wait on our parents' creation phase, in addition to whatever is declared in this stanza. Setting this flag will bypass waiting on our parent resource's creation, so that our create or groom phase can instead depend only on the parent's groom phase. "
201
197
  }
198
+ }
202
199
  }
203
200
  }
204
201
  end
@@ -244,7 +241,7 @@ module MU
244
241
  schema["title"] = type.to_s
245
242
 
246
243
  if cloud
247
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(cloud).const_get(shortclass)
244
+ cloudclass = MU::Cloud.resourceClass(cloud, type)
248
245
 
249
246
  if cloudclass.respond_to?(:schema)
250
247
  _reqd, cloudschema = cloudclass.schema
@@ -276,15 +273,20 @@ module MU
276
273
  schema_chunk["properties"]["creation_style"] != "existing"
277
274
  schema_chunk["properties"].each_pair { |key, subschema|
278
275
  shortclass = if conf_chunk[key]
279
- shortclass, _cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(key)
276
+ shortclass, _cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(key, false)
280
277
  shortclass
281
278
  else
282
279
  nil
283
280
  end
284
281
 
285
282
  new_val = applySchemaDefaults(conf_chunk[key], subschema, depth+1, conf_chunk, type: shortclass).dup
286
-
287
- conf_chunk[key] = Marshal.load(Marshal.dump(new_val)) if !new_val.nil?
283
+ if !new_val.nil?
284
+ begin
285
+ conf_chunk[key] = Marshal.load(Marshal.dump(new_val))
286
+ rescue TypeError
287
+ conf_chunk[key] = new_val.clone
288
+ end
289
+ end
288
290
  }
289
291
  end
290
292
  elsif schema_chunk["type"] == "array" and conf_chunk.kind_of?(Array)
@@ -293,11 +295,10 @@ module MU
293
295
  # schema information so that we set those defaults correctly.
294
296
  realschema = if type and schema_chunk["items"] and schema_chunk["items"]["properties"] and item["cloud"] and MU::Cloud.supportedClouds.include?(item['cloud'])
295
297
 
296
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(item["cloud"]).const_get(type)
297
- _toplevel_required, cloudschema = cloudclass.schema(self)
298
+ _toplevel_required, cloudschema = MU::Cloud.resourceClass(item["cloud"], type).schema(self)
298
299
 
299
300
  newschema = schema_chunk["items"].dup
300
- newschema["properties"].merge!(cloudschema)
301
+ MU::Config.schemaMerge(newschema["properties"], cloudschema, item["cloud"])
301
302
  newschema
302
303
  else
303
304
  schema_chunk["items"].dup
@@ -334,9 +335,9 @@ module MU
334
335
  return
335
336
  end
336
337
 
337
- cloudclass = Object.const_get("MU").const_get("Cloud").const_get(kitten['cloud'])
338
- shortclass, _cfg_name, _cfg_plural, _classname = MU::Cloud.getResourceNames(type)
339
- resclass = Object.const_get("MU").const_get("Cloud").const_get(kitten['cloud']).const_get(shortclass)
338
+ cloudclass = MU::Cloud.cloudClass(kitten['cloud'])
339
+
340
+ resclass = MU::Cloud.resourceClass(kitten['cloud'], type)
340
341
 
341
342
  schema_fields = ["us_only", "scrub_mu_isms", "credentials", "billing_acct"]
342
343
  if !resclass.isGlobal?
@@ -14,7 +14,7 @@
14
14
 
15
15
  module MU
16
16
  class Config
17
- # Basket of Kittens config schema and parser logic. See modules/mu/clouds/*/search_domain.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/search_domain.rb
18
18
  class SearchDomain
19
19
 
20
20
  # Base configuration schema for a SearchDomain
@@ -14,7 +14,7 @@
14
14
 
15
15
  module MU
16
16
  class Config
17
- # Basket of Kittens config schema and parser logic. See modules/mu/clouds/*/server.rb
17
+ # Basket of Kittens config schema and parser logic. See modules/mu/providers/*/server.rb
18
18
  class Server
19
19
 
20
20
  # Verify that a server or server_pool has a valid LDAP config referencing
@@ -546,7 +546,7 @@ module MU
546
546
  "additionalProperties" => false,
547
547
  "description" => "Create individual server instances.",
548
548
  "properties" => {
549
- "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "A", need_zone: true),
549
+ "dns_records" => MU::Config::DNSZone.records_primitive(need_target: false, default_type: "A", need_zone: true, embedded_type: "server"),
550
550
  "bastion" => {
551
551
  "type" => "boolean",
552
552
  "default" => false,
@@ -625,6 +625,13 @@ module MU
625
625
  server['vault_access'] << {"vault" => "splunk", "item" => "admin_user"}
626
626
  ok = false if !MU::Config::Server.checkVaultRefs(server)
627
627
 
628
+ server['groomer'] ||= self.defaultGroomer
629
+ groomclass = MU::Groomer.loadGroomer(server['groomer'])
630
+ if !groomclass.available?(server['platform'].match(/^win/))
631
+ MU.log "Groomer #{server['groomer']} for #{server['name']} is missing or has incomplete dependencies", MU::ERR
632
+ ok = false
633
+ end
634
+
628
635
  if server["cloud"] != "Azure"
629
636
  server['dependencies'] << configurator.adminFirewallRuleset(vpc: server['vpc'], region: server['region'], cloud: server['cloud'], credentials: server['credentials'])
630
637
  end
@@ -643,20 +650,12 @@ module MU
643
650
  end
644
651
 
645
652
  if !server["vpc"]["subnet_name"].nil? and configurator.nat_routes.has_key?(server["vpc"]["subnet_name"]) and !configurator.nat_routes[server["vpc"]["subnet_name"]].empty?
646
- server["dependencies"] << {
647
- "type" => "server",
648
- "name" => configurator.nat_routes[server["vpc"]["subnet_name"]],
649
- "phase" => "groom"
650
- }
653
+ MU::Config.addDependency(server, configurator.nat_routes[server["vpc"]["subnet_name"]], "server", phase: "groom", no_create_wait: true)
651
654
  elsif !server["vpc"]["name"].nil?
652
655
  siblingvpc = configurator.haveLitterMate?(server["vpc"]["name"], "vpcs")
653
656
  if siblingvpc and siblingvpc['bastion'] and
654
- server['name'] != siblingvpc['bastion'].to_h['name']
655
- server["dependencies"] << {
656
- "type" => "server",
657
- "name" => siblingvpc['bastion'].to_h['name'],
658
- "phase" => "groom"
659
- }
657
+ server['name'] != siblingvpc['bastion']['name']
658
+ MU::Config.addDependency(server, siblingvpc['bastion']['name'], "server", phase: "groom", no_create_wait: true)
660
659
  end
661
660
  end
662
661
  end