cloud-mu 3.1.4 → 3.3.1

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 (203) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -1
  3. data/ansible/roles/mu-windows/README.md +33 -0
  4. data/ansible/roles/mu-windows/defaults/main.yml +2 -0
  5. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  6. data/ansible/roles/mu-windows/files/config.xml +76 -0
  7. data/ansible/roles/mu-windows/handlers/main.yml +2 -0
  8. data/ansible/roles/mu-windows/meta/main.yml +53 -0
  9. data/ansible/roles/mu-windows/tasks/main.yml +36 -0
  10. data/ansible/roles/mu-windows/tests/inventory +2 -0
  11. data/ansible/roles/mu-windows/tests/test.yml +5 -0
  12. data/ansible/roles/mu-windows/vars/main.yml +2 -0
  13. data/bin/mu-adopt +16 -12
  14. data/bin/mu-azure-tests +57 -0
  15. data/bin/mu-cleanup +2 -4
  16. data/bin/mu-configure +52 -0
  17. data/bin/mu-deploy +3 -3
  18. data/bin/mu-findstray-tests +25 -0
  19. data/bin/mu-gen-docs +2 -4
  20. data/bin/mu-load-config.rb +2 -1
  21. data/bin/mu-node-manage +15 -16
  22. data/bin/mu-run-tests +37 -12
  23. data/cloud-mu.gemspec +5 -3
  24. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  25. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  26. data/cookbooks/mu-tools/libraries/helper.rb +1 -1
  27. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  28. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  29. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  30. data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
  31. data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
  32. data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
  33. data/extras/clean-stock-amis +25 -19
  34. data/extras/generate-stock-images +1 -0
  35. data/extras/image-generators/AWS/win2k12.yaml +18 -13
  36. data/extras/image-generators/AWS/win2k16.yaml +18 -13
  37. data/extras/image-generators/AWS/win2k19.yaml +21 -0
  38. data/modules/mommacat.ru +1 -1
  39. data/modules/mu.rb +158 -107
  40. data/modules/mu/adoption.rb +386 -59
  41. data/modules/mu/cleanup.rb +214 -303
  42. data/modules/mu/cloud.rb +128 -1632
  43. data/modules/mu/cloud/database.rb +49 -0
  44. data/modules/mu/cloud/dnszone.rb +44 -0
  45. data/modules/mu/cloud/machine_images.rb +212 -0
  46. data/modules/mu/cloud/providers.rb +81 -0
  47. data/modules/mu/cloud/resource_base.rb +926 -0
  48. data/modules/mu/cloud/server.rb +40 -0
  49. data/modules/mu/cloud/server_pool.rb +1 -0
  50. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  51. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  52. data/modules/mu/cloud/wrappers.rb +169 -0
  53. data/modules/mu/config.rb +135 -82
  54. data/modules/mu/config/alarm.rb +2 -6
  55. data/modules/mu/config/bucket.rb +32 -3
  56. data/modules/mu/config/cache_cluster.rb +2 -2
  57. data/modules/mu/config/cdn.rb +100 -0
  58. data/modules/mu/config/collection.rb +1 -1
  59. data/modules/mu/config/container_cluster.rb +7 -2
  60. data/modules/mu/config/database.rb +84 -105
  61. data/modules/mu/config/database.yml +1 -2
  62. data/modules/mu/config/dnszone.rb +5 -4
  63. data/modules/mu/config/doc_helpers.rb +5 -6
  64. data/modules/mu/config/endpoint.rb +2 -1
  65. data/modules/mu/config/firewall_rule.rb +3 -19
  66. data/modules/mu/config/folder.rb +1 -1
  67. data/modules/mu/config/function.rb +17 -8
  68. data/modules/mu/config/group.rb +1 -1
  69. data/modules/mu/config/habitat.rb +1 -1
  70. data/modules/mu/config/job.rb +89 -0
  71. data/modules/mu/config/loadbalancer.rb +57 -11
  72. data/modules/mu/config/log.rb +1 -1
  73. data/modules/mu/config/msg_queue.rb +1 -1
  74. data/modules/mu/config/nosqldb.rb +1 -1
  75. data/modules/mu/config/notifier.rb +8 -19
  76. data/modules/mu/config/ref.rb +92 -14
  77. data/modules/mu/config/role.rb +1 -1
  78. data/modules/mu/config/schema_helpers.rb +38 -37
  79. data/modules/mu/config/search_domain.rb +1 -1
  80. data/modules/mu/config/server.rb +12 -13
  81. data/modules/mu/config/server.yml +1 -0
  82. data/modules/mu/config/server_pool.rb +3 -7
  83. data/modules/mu/config/storage_pool.rb +1 -1
  84. data/modules/mu/config/tail.rb +11 -0
  85. data/modules/mu/config/user.rb +1 -1
  86. data/modules/mu/config/vpc.rb +27 -23
  87. data/modules/mu/config/vpc.yml +0 -1
  88. data/modules/mu/defaults/AWS.yaml +91 -68
  89. data/modules/mu/defaults/Azure.yaml +1 -0
  90. data/modules/mu/defaults/Google.yaml +1 -0
  91. data/modules/mu/deploy.rb +33 -19
  92. data/modules/mu/groomer.rb +16 -1
  93. data/modules/mu/groomers/ansible.rb +123 -21
  94. data/modules/mu/groomers/chef.rb +64 -11
  95. data/modules/mu/logger.rb +120 -144
  96. data/modules/mu/master.rb +97 -4
  97. data/modules/mu/master/ssl.rb +0 -1
  98. data/modules/mu/mommacat.rb +154 -867
  99. data/modules/mu/mommacat/daemon.rb +23 -14
  100. data/modules/mu/mommacat/naming.rb +110 -3
  101. data/modules/mu/mommacat/search.rb +495 -0
  102. data/modules/mu/mommacat/storage.rb +225 -192
  103. data/modules/mu/{clouds → providers}/README.md +1 -1
  104. data/modules/mu/{clouds → providers}/aws.rb +281 -64
  105. data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
  106. data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
  107. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
  108. data/modules/mu/providers/aws/cdn.rb +782 -0
  109. data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
  110. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +708 -749
  111. data/modules/mu/providers/aws/database.rb +1744 -0
  112. data/modules/mu/{clouds → providers}/aws/dnszone.rb +75 -57
  113. data/modules/mu/providers/aws/endpoint.rb +1072 -0
  114. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +212 -242
  115. data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
  116. data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
  117. data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
  118. data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
  119. data/modules/mu/providers/aws/job.rb +466 -0
  120. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +50 -41
  121. data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
  122. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
  123. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
  124. data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
  125. data/modules/mu/{clouds → providers}/aws/role.rb +94 -57
  126. data/modules/mu/{clouds → providers}/aws/search_domain.rb +173 -42
  127. data/modules/mu/{clouds → providers}/aws/server.rb +782 -1107
  128. data/modules/mu/{clouds → providers}/aws/server_pool.rb +36 -46
  129. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
  130. data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
  131. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  132. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
  133. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
  134. data/modules/mu/{clouds → providers}/aws/vpc.rb +429 -849
  135. data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
  136. data/modules/mu/{clouds → providers}/azure.rb +13 -0
  137. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
  138. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
  139. data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
  140. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
  141. data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
  142. data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
  143. data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
  144. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  145. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  146. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  147. data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
  148. data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
  149. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  150. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  151. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  152. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  153. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  154. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  155. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  156. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  157. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  158. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  159. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
  160. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  161. data/modules/mu/{clouds → providers}/google.rb +29 -6
  162. data/modules/mu/{clouds → providers}/google/bucket.rb +5 -5
  163. data/modules/mu/{clouds → providers}/google/container_cluster.rb +59 -37
  164. data/modules/mu/{clouds → providers}/google/database.rb +5 -12
  165. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
  166. data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
  167. data/modules/mu/{clouds → providers}/google/function.rb +14 -8
  168. data/modules/mu/{clouds → providers}/google/group.rb +9 -17
  169. data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
  170. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
  171. data/modules/mu/{clouds → providers}/google/role.rb +50 -31
  172. data/modules/mu/{clouds → providers}/google/server.rb +142 -55
  173. data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
  174. data/modules/mu/{clouds → providers}/google/user.rb +34 -24
  175. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  176. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  177. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  178. data/modules/mu/{clouds → providers}/google/vpc.rb +46 -15
  179. data/modules/tests/aws-jobs-functions.yaml +46 -0
  180. data/modules/tests/centos6.yaml +15 -0
  181. data/modules/tests/centos7.yaml +15 -0
  182. data/modules/tests/centos8.yaml +12 -0
  183. data/modules/tests/ecs.yaml +23 -0
  184. data/modules/tests/eks.yaml +1 -1
  185. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  186. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  187. data/modules/tests/includes-and-params.yaml +2 -1
  188. data/modules/tests/microservice_app.yaml +288 -0
  189. data/modules/tests/rds.yaml +108 -0
  190. data/modules/tests/regrooms/rds.yaml +123 -0
  191. data/modules/tests/server-with-scrub-muisms.yaml +2 -1
  192. data/modules/tests/super_complex_bok.yml +2 -2
  193. data/modules/tests/super_simple_bok.yml +3 -5
  194. data/modules/tests/win2k12.yaml +25 -0
  195. data/modules/tests/win2k16.yaml +25 -0
  196. data/modules/tests/win2k19.yaml +25 -0
  197. data/requirements.txt +1 -0
  198. data/spec/mu/clouds/azure_spec.rb +2 -2
  199. metadata +169 -93
  200. data/extras/image-generators/AWS/windows.yaml +0 -18
  201. data/modules/mu/clouds/aws/database.rb +0 -1974
  202. data/modules/mu/clouds/aws/endpoint.rb +0 -596
  203. data/modules/tests/needwork/win2k12.yaml +0 -13
@@ -88,16 +88,28 @@ module MU
88
88
  }
89
89
  end
90
90
 
91
+
91
92
  # Overwrite this deployment's configuration with a new version. Save the
92
93
  # previous version as well.
93
94
  # @param new_conf [Hash]: A new configuration, fully resolved by {MU::Config}
94
- def updateBasketofKittens(new_conf)
95
+ def updateBasketofKittens(new_conf, skip_validation: false, new_metadata: nil, save_now: false)
95
96
  loadDeploy
96
97
  if new_conf == @original_config
97
- MU.log "#{@deploy_id}", MU::WARN
98
98
  return
99
99
  end
100
100
 
101
+ scrub_with = nil
102
+
103
+ # Make sure the new config that we were just handed resolves and makes
104
+ # sense
105
+ if !skip_validation
106
+ f = Tempfile.new(@deploy_id)
107
+ f.write JSON.parse(JSON.generate(new_conf)).to_yaml
108
+ conf_engine = MU::Config.new(f.path) # will throw an exception if it's bad, adoption should catch this and cope reasonably
109
+ scrub_with = conf_engine.config
110
+ f.close
111
+ end
112
+
101
113
  backup = "#{deploy_dir}/basket_of_kittens.json.#{Time.now.to_i.to_s}"
102
114
  MU.log "Saving previous config of #{@deploy_id} to #{backup}"
103
115
  config = File.new(backup, File::CREAT|File::TRUNC|File::RDWR, 0600)
@@ -106,9 +118,26 @@ module MU
106
118
  config.flock(File::LOCK_UN)
107
119
  config.close
108
120
 
109
- @original_config = new_conf
110
- # save! # XXX this will happen later, more sensibly
111
- MU.log "New config saved to #{deploy_dir}/basket_of_kittens.json"
121
+ @original_config = new_conf.clone
122
+
123
+ MU::Cloud.resource_types.each_pair { |res_type, attrs|
124
+ next if !@deployment.has_key?(attrs[:cfg_plural])
125
+ deletia = []
126
+ @deployment[attrs[:cfg_plural]].each_pair { |res_name, data|
127
+ orig_cfg = findResourceConfig(attrs[:cfg_plural], res_name, (scrub_with || @original_config))
128
+
129
+ if orig_cfg.nil?
130
+ MU.log "#{res_type} #{res_name} no longer configured, will remove deployment metadata", MU::NOTICE
131
+ deletia << res_name
132
+ end
133
+ }
134
+ @deployment[attrs[:cfg_plural]].reject! { |k, v| deletia.include?(k) }
135
+ }
136
+
137
+ if save_now
138
+ save!
139
+ MU.log "New config saved to #{deploy_dir}/basket_of_kittens.json"
140
+ end
112
141
  end
113
142
 
114
143
  @lock_semaphore = Mutex.new
@@ -147,11 +176,11 @@ module MU
147
176
  # @param id [String]: The lock identifier to release.
148
177
  # @param nonblock [Boolean]: Whether to block while waiting for the lock. In non-blocking mode, we simply return false if the lock is not available.
149
178
  # return [false, nil]
150
- def self.lock(id, nonblock = false, global = false)
179
+ def self.lock(id, nonblock = false, global = false, deploy_id: MU.deploy_id)
151
180
  raise MuError, "Can't pass a nil id to MU::MommaCat.lock" if id.nil?
152
181
 
153
182
  if !global
154
- lockdir = "#{deploy_dir(MU.deploy_id)}/locks"
183
+ lockdir = "#{deploy_dir(deploy_id)}/locks"
155
184
  else
156
185
  lockdir = File.expand_path(MU.dataDir+"/locks")
157
186
  end
@@ -186,11 +215,11 @@ module MU
186
215
 
187
216
  # Release a flock() lock.
188
217
  # @param id [String]: The lock identifier to release.
189
- def self.unlock(id, global = false)
218
+ def self.unlock(id, global = false, deploy_id: MU.deploy_id)
190
219
  raise MuError, "Can't pass a nil id to MU::MommaCat.unlock" if id.nil?
191
220
  lockdir = nil
192
221
  if !global
193
- lockdir = "#{deploy_dir(MU.deploy_id)}/locks"
222
+ lockdir = "#{deploy_dir(deploy_id)}/locks"
194
223
  else
195
224
  lockdir = File.expand_path(MU.dataDir+"/locks")
196
225
  end
@@ -332,32 +361,17 @@ module MU
332
361
  Dir.mkdir(deploy_dir, 0700)
333
362
  end
334
363
 
335
- if !origin.nil?
336
- o_file = File.new("#{deploy_dir}/origin.json", File::CREAT|File::TRUNC|File::RDWR, 0600)
337
- o_file.puts JSON.pretty_generate(origin)
338
- o_file.close
339
- end
340
-
341
- if !@private_key.nil?
342
- privkey = File.new("#{deploy_dir}/private_key", File::CREAT|File::TRUNC|File::RDWR, 0600)
343
- privkey.puts @private_key
344
- privkey.close
345
- end
346
-
347
- if !@public_key.nil?
348
- pubkey = File.new("#{deploy_dir}/public_key", File::CREAT|File::TRUNC|File::RDWR, 0600)
349
- pubkey.puts @public_key
350
- pubkey.close
351
- end
364
+ writeFile("origin.json", JSON.pretty_generate(origin)) if !origin.nil?
365
+ writeFile("private_key", @private_key) if !@private_key.nil?
366
+ writeFile("public_key", @public_key) if !@public_key.nil?
352
367
 
353
368
  if !@deployment.nil? and @deployment.size > 0
354
369
  @deployment['handle'] = MU.handle if @deployment['handle'].nil? and !MU.handle.nil?
355
- @deployment['public_key'] = @public_key
356
- @deployment['timestamp'] ||= @timestamp
357
- @deployment['seed'] ||= @seed
358
- @deployment['appname'] ||= @appname
359
- @deployment['handle'] ||= @handle
360
- @deployment['ssh_public_key'] ||= @ssh_public_key if @ssh_public_key
370
+ [:public_key, :timestamp, :seed, :appname, :handle, :ssh_public_key].each { |var|
371
+ value = instance_variable_get(("@"+var.to_s).to_sym)
372
+ @deployment[var.to_s] = value if value
373
+ }
374
+
361
375
  begin
362
376
  # XXX doing this to trigger JSON errors before stomping the stored
363
377
  # file...
@@ -380,36 +394,15 @@ module MU
380
394
  end
381
395
 
382
396
  if !@original_config.nil? and @original_config.is_a?(Hash)
383
- config = File.new("#{deploy_dir}/basket_of_kittens.json", File::CREAT|File::TRUNC|File::RDWR, 0600)
384
- config.puts JSON.pretty_generate(MU::Config.manxify(@original_config))
385
- config.close
397
+ writeFile("basket_of_kittens.json", JSON.pretty_generate(MU::Config.manxify(@original_config)))
386
398
  end
387
399
 
388
- if !@ssh_private_key.nil?
389
- key = File.new("#{deploy_dir}/node_ssh.key", File::CREAT|File::TRUNC|File::RDWR, 0600)
390
- key.puts @ssh_private_key
391
- key.close
392
- end
393
- if !@ssh_public_key.nil?
394
- key = File.new("#{deploy_dir}/node_ssh.pub", File::CREAT|File::TRUNC|File::RDWR, 0600)
395
- key.puts @ssh_public_key
396
- key.close
397
- end
398
- if !@ssh_key_name.nil?
399
- key = File.new("#{deploy_dir}/ssh_key_name", File::CREAT|File::TRUNC|File::RDWR, 0600)
400
- key.puts @ssh_key_name
401
- key.close
402
- end
403
- if !@environment.nil?
404
- env = File.new("#{deploy_dir}/environment_name", File::CREAT|File::TRUNC|File::RDWR, 0600)
405
- env.puts @environment
406
- env.close
407
- end
408
- if !@deploy_secret.nil?
409
- secret = File.new("#{deploy_dir}/deploy_secret", File::CREAT|File::TRUNC|File::RDWR, 0600)
410
- secret.print @deploy_secret
411
- secret.close
412
- end
400
+ writeFile("node_ssh.key", @ssh_private_key) if !@ssh_private_key.nil?
401
+ writeFile("node_ssh.pub", @ssh_public_key) if !@ssh_public_key.nil?
402
+ writeFile("ssh_key_name", @ssh_key_name) if !@ssh_key_name.nil?
403
+ writeFile("environment_name", @environment) if !@environment.nil?
404
+ writeFile("deploy_secret", @deploy_secret) if !@deploy_secret.nil?
405
+
413
406
  if !@secrets.nil?
414
407
  secretdir = "#{deploy_dir}/secrets"
415
408
  if !Dir.exist?(secretdir)
@@ -418,9 +411,7 @@ module MU
418
411
  end
419
412
  @secrets.each_pair { |type, servers|
420
413
  servers.each_pair { |server, svr_secret|
421
- key = File.new("#{secretdir}/#{type}.#{server}", File::CREAT|File::TRUNC|File::RDWR, 0600)
422
- key.puts svr_secret
423
- key.close
414
+ writeFile("secrets/#{type}.#{server}", svr_secret)
424
415
  }
425
416
  }
426
417
  end
@@ -430,146 +421,64 @@ module MU
430
421
  syncLitter(@deployment['servers'].keys, triggering_node: triggering_node, save_only: true) if @deployment.has_key?("servers")
431
422
  end
432
423
 
433
- # Find one or more resources by their Mu resource name, and return
434
- # MommaCat objects for their containing deploys, their BoK config data,
435
- # and their deployment data.
436
- #
437
- # @param type [String]: The type of resource, e.g. "vpc" or "server."
438
- # @param name [String]: The Mu resource class, typically the name field of a Basket of Kittens resource declaration.
439
- # @param mu_name [String]: The fully-expanded Mu resource name, e.g. MGMT-PROD-2015040115-FR-ADMGMT2
440
- # @param deploy_id [String]: The deployment to search. Will search all deployments if not specified.
441
- # @return [Hash,Array<Hash>]
442
- def self.getResourceMetadata(type, name: nil, deploy_id: nil, use_cache: true, mu_name: nil)
443
- if type.nil?
444
- raise MuError, "Can't call getResourceMetadata without a type argument"
445
- end
446
- _shortclass, _cfg_name, type, _classname = MU::Cloud.getResourceNames(type)
447
-
448
- # first, check our in-memory deploys, which may or may not have been
449
- # written to disk yet.
450
- littercache = nil
451
- begin
452
- @@litter_semaphore.synchronize {
453
- littercache = @@litters.dup
454
- }
455
- rescue ThreadError => e
456
- # already locked by a parent caller and this is a read op, so this is ok
457
- raise e if !e.message.match(/recursive locking/)
458
- littercache = @@litters.dup
459
- end
460
- littercache.each_pair { |deploy, momma|
461
- @@deploy_struct_semaphore.synchronize {
462
- @deploy_cache[deploy] = {
463
- "mtime" => Time.now,
464
- "data" => momma.deployment
465
- }
466
- }
467
- }
468
-
424
+ # Read all of our +deployment.json+ files in and stick them in a hash. Used
425
+ # by search routines that just need to skim this data without loading
426
+ # entire {MU::MommaCat} objects.
427
+ def self.cacheDeployMetadata(deploy_id = nil, use_cache: false)
469
428
  deploy_root = File.expand_path(MU.dataDir+"/deployments")
470
429
  MU::MommaCat.deploy_struct_semaphore.synchronize {
471
- if Dir.exist?(deploy_root)
472
- Dir.entries(deploy_root).each { |deploy|
473
- this_deploy_dir = deploy_root+"/"+deploy
474
- next if deploy == "." or deploy == ".." or !Dir.exist?(this_deploy_dir)
475
- next if deploy_id and deploy_id != deploy
476
-
477
- if !File.size?(this_deploy_dir+"/deployment.json")
478
- MU.log "#{this_deploy_dir}/deployment.json doesn't exist, skipping when loading cache", MU::DEBUG
479
- next
480
- end
481
- if @deploy_cache[deploy].nil? or !use_cache
482
- @deploy_cache[deploy] = Hash.new
483
- elsif @deploy_cache[deploy]['mtime'] == File.mtime("#{this_deploy_dir}/deployment.json")
484
- MU.log "Using cached copy of deploy #{deploy} from #{@deploy_cache[deploy]['mtime']}", MU::DEBUG
430
+ @@deploy_cache ||= {}
431
+ return if !Dir.exist?(deploy_root)
485
432
 
486
- next
487
- end
433
+ Dir.entries(deploy_root).each { |deploy|
434
+ this_deploy_dir = deploy_root+"/"+deploy
435
+ this_deploy_file = this_deploy_dir+"/deployment.json"
436
+
437
+ if deploy == "." or deploy == ".." or !Dir.exist?(this_deploy_dir) or
438
+ (deploy_id and deploy_id != deploy) or
439
+ !File.size?(this_deploy_file) or
440
+ (use_cache and @@deploy_cache[deploy] and @@deploy_cache[deploy]['mtime'] == File.mtime(this_deploy_file))
441
+ next
442
+ end
488
443
 
489
- @deploy_cache[deploy] = Hash.new if !@deploy_cache.has_key?(deploy)
490
- MU.log "Caching deploy #{deploy}", MU::DEBUG
491
- lock = File.open("#{this_deploy_dir}/deployment.json", File::RDONLY)
492
- lock.flock(File::LOCK_EX)
493
- @deploy_cache[deploy]['mtime'] = File.mtime("#{this_deploy_dir}/deployment.json")
444
+ @@deploy_cache[deploy] ||= {}
494
445
 
495
- begin
496
- @deploy_cache[deploy]['data'] = JSON.parse(File.read("#{this_deploy_dir}/deployment.json"))
497
- lock.flock(File::LOCK_UN)
498
-
499
- next if @deploy_cache[deploy].nil? or @deploy_cache[deploy]['data'].nil?
500
- # Populate some generable entries that should be in the deploy
501
- # data. Also, bounce out if we realize we've found exactly what
502
- # we needed already.
503
- MU::Cloud.resource_types.values.each { |attrs|
504
-
505
- next if @deploy_cache[deploy]['data'][attrs[:cfg_plural]].nil?
506
- if !attrs[:has_multiples]
507
- @deploy_cache[deploy]['data'][attrs[:cfg_plural]].each_pair { |nodename, data|
508
- # XXX we don't actually store node names for some resources, need to farm them
509
- # and fix metadata
510
- # if !mu_name.nil? and nodename == mu_name
511
- # return { deploy => [data] }
512
- # end
513
- }
514
- else
515
- @deploy_cache[deploy]['data'][attrs[:cfg_plural]].each_pair { |node_class, nodes|
516
- next if nodes.nil? or !nodes.is_a?(Hash)
517
- nodes.each_pair { |nodename, data|
518
- next if !data.is_a?(Hash)
519
- data['#MU_NODE_CLASS'] = node_class
520
- if !data.has_key?("cloud") # XXX kludge until old metadata gets fixed
521
- data["cloud"] = MU::Config.defaultCloud
522
- end
523
- data['#MU_NAME'] = nodename
524
- if !mu_name.nil? and nodename == mu_name
525
- return {deploy => [data]} if deploy_id && deploy == deploy_id
526
- end
527
- }
446
+ MU.log "Caching deploy #{deploy}", MU::DEBUG
447
+ lock = File.open(this_deploy_file, File::RDONLY)
448
+ lock.flock(File::LOCK_EX)
449
+ @@deploy_cache[deploy]['mtime'] = File.mtime(this_deploy_file)
450
+
451
+ begin
452
+ @@deploy_cache[deploy]['data'] = JSON.parse(File.read(this_deploy_file))
453
+ next if @@deploy_cache[deploy]['data'].nil?
454
+ # Populate some generable entries that should be in the deploy
455
+ # data. Also, bounce out if we realize we've found exactly what
456
+ # we needed already.
457
+ MU::Cloud.resource_types.values.each { |attrs|
458
+
459
+ next if @@deploy_cache[deploy]['data'][attrs[:cfg_plural]].nil?
460
+ if attrs[:has_multiples]
461
+ @@deploy_cache[deploy]['data'][attrs[:cfg_plural]].each_pair { |node_class, nodes|
462
+ next if nodes.nil? or !nodes.is_a?(Hash)
463
+ nodes.each_pair { |nodename, data|
464
+ next if !data.is_a?(Hash)
465
+ data['#MU_NODE_CLASS'] ||= node_class
466
+ data['#MU_NAME'] ||= nodename
467
+ data["cloud"] ||= MU::Config.defaultCloud
528
468
  }
529
- end
530
- }
531
- rescue JSON::ParserError => e
532
- raise MuError, "JSON parse failed on #{this_deploy_dir}/deployment.json\n\n"+File.read("#{this_deploy_dir}/deployment.json")
533
- end
469
+ }
470
+ end
471
+ }
472
+ rescue JSON::ParserError
473
+ raise MuError, "JSON parse failed on #{this_deploy_file}\n\n"+File.read(this_deploy_file)
474
+ ensure
534
475
  lock.flock(File::LOCK_UN)
535
476
  lock.close
536
- }
537
- end
538
- }
539
-
540
- matches = {}
541
-
542
- if deploy_id.nil?
543
- @deploy_cache.each_key { |deploy|
544
- next if !@deploy_cache[deploy].has_key?('data')
545
- next if !@deploy_cache[deploy]['data'].has_key?(type)
546
- if !name.nil?
547
- next if @deploy_cache[deploy]['data'][type][name].nil?
548
- matches[deploy] ||= []
549
- matches[deploy] << @deploy_cache[deploy]['data'][type][name].dup
550
- else
551
- matches[deploy] ||= []
552
- matches[deploy].concat(@deploy_cache[deploy]['data'][type].values)
553
477
  end
554
478
  }
555
- return matches
556
- elsif !@deploy_cache[deploy_id].nil?
557
- if !@deploy_cache[deploy_id]['data'].nil? and
558
- !@deploy_cache[deploy_id]['data'][type].nil?
559
- if !name.nil?
560
- if !@deploy_cache[deploy_id]['data'][type][name].nil?
561
- matches[deploy_id] ||= []
562
- matches[deploy_id] << @deploy_cache[deploy_id]['data'][type][name].dup
563
- else
564
- return matches # nothing, actually
565
- end
566
- else
567
- matches[deploy_id] = @deploy_cache[deploy_id]['data'][type].values
568
- end
569
- end
570
- end
479
+ }
571
480
 
572
- return matches
481
+ @@deploy_cache
573
482
  end
574
483
 
575
484
  # Get the deploy directory
@@ -604,6 +513,105 @@ module MU
604
513
  end
605
514
 
606
515
  private
516
+
517
+ def writeFile(filename, contents)
518
+ file = File.new("#{deploy_dir}/#{filename}", File::CREAT|File::TRUNC|File::RDWR, 0600)
519
+ file.puts contents
520
+ file.close
521
+ end
522
+
523
+ # Helper for +initialize+
524
+ def setDeploySecret
525
+ credsets = {}
526
+ MU::Cloud.resource_types.values.each { |attrs|
527
+ if !@original_config[attrs[:cfg_plural]].nil? and @original_config[attrs[:cfg_plural]].size > 0
528
+ @original_config[attrs[:cfg_plural]].each { |resource|
529
+
530
+ credsets[resource['cloud']] ||= []
531
+ credsets[resource['cloud']] << resource['credentials']
532
+ @clouds[resource['cloud']] = 0 if !@clouds.has_key?(resource['cloud'])
533
+ @clouds[resource['cloud']] = @clouds[resource['cloud']] + 1
534
+
535
+ }
536
+ end
537
+ }
538
+
539
+ MU.log "Creating deploy secret for #{MU.deploy_id}"
540
+ @deploy_secret = Password.random(256)
541
+ if !@original_config['scrub_mu_isms'] and !@no_artifacts
542
+ credsets.each_pair { |cloud, creds|
543
+ creds.uniq!
544
+ creds.each { |credentials|
545
+ MU::Cloud.cloudClass(cloud).writeDeploySecret(@deploy_id, @deploy_secret, credentials: credentials)
546
+ }
547
+ }
548
+ end
549
+ end
550
+
551
+ def loadObjects(delay_descriptor_load)
552
+ # Load up MU::Cloud objects for all our kittens in this deploy
553
+
554
+ MU::Cloud.resource_types.each_pair { |res_type, attrs|
555
+ type = attrs[:cfg_plural]
556
+ next if !@deployment.has_key?(type)
557
+
558
+ deletia = {}
559
+ @deployment[type].each_pair { |res_name, data|
560
+ orig_cfg = findResourceConfig(type, res_name)
561
+
562
+ if orig_cfg.nil?
563
+ MU.log "Failed to locate original config for #{attrs[:cfg_name]} #{res_name} in #{@deploy_id}", MU::WARN if !["firewall_rules", "databases", "storage_pools", "cache_clusters", "alarms"].include?(type) # XXX shaddap
564
+ next
565
+ end
566
+
567
+ if orig_cfg['vpc']
568
+ ref = if orig_cfg['vpc']['id'] and orig_cfg['vpc']['id'].is_a?(Hash)
569
+ orig_cfg['vpc']['id']['mommacat'] = self
570
+ MU::Config::Ref.get(orig_cfg['vpc']['id'])
571
+ else
572
+ orig_cfg['vpc']['mommacat'] = self
573
+ MU::Config::Ref.get(orig_cfg['vpc'])
574
+ end
575
+ orig_cfg['vpc'].delete('mommacat')
576
+ orig_cfg['vpc'] = ref if ref.kitten(shallow: true)
577
+ end
578
+
579
+ begin
580
+ if attrs[:has_multiples]
581
+ data.keys.each { |mu_name|
582
+ addKitten(type, res_name, attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: mu_name, delay_descriptor_load: delay_descriptor_load))
583
+ }
584
+ else
585
+ addKitten(type, res_name, attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: data['mu_name'], cloud_id: data['cloud_id']))
586
+ end
587
+ rescue StandardError => e
588
+ if e.class != MU::Cloud::MuCloudResourceNotImplemented
589
+ MU.log "Failed to load an existing resource of type '#{type}' in #{@deploy_id}: #{e.inspect}", MU::WARN, details: e.backtrace
590
+ end
591
+ end
592
+ }
593
+
594
+ }
595
+ end
596
+
597
+ # Helper for +initialize+
598
+ def initDeployDirectory
599
+ if !Dir.exist?(MU.dataDir+"/deployments")
600
+ MU.log "Creating #{MU.dataDir}/deployments", MU::DEBUG
601
+ Dir.mkdir(MU.dataDir+"/deployments", 0700)
602
+ end
603
+ path = File.expand_path(MU.dataDir+"/deployments")+"/"+@deploy_id
604
+ if !Dir.exist?(path)
605
+ MU.log "Creating #{path}", MU::DEBUG
606
+ Dir.mkdir(path, 0700)
607
+ end
608
+
609
+ @ssh_key_name, @ssh_private_key, @ssh_public_key = self.SSHKey
610
+ if !File.exist?(deploy_dir+"/private_key")
611
+ @private_key, @public_key = createDeployKey
612
+ end
613
+
614
+ end
607
615
 
608
616
  ###########################################################################
609
617
  ###########################################################################
@@ -685,5 +693,30 @@ module MU
685
693
  }
686
694
  end
687
695
 
696
+ def findResourceConfig(type, name, config = @original_config)
697
+ orig_cfg = nil
698
+ if config.has_key?(type)
699
+ config[type].each { |resource|
700
+ if resource["name"] == name
701
+ orig_cfg = resource
702
+ break
703
+ end
704
+ }
705
+ end
706
+
707
+ # Some Server objects originated from ServerPools, get their
708
+ # configs from there
709
+ if type == "servers" and orig_cfg.nil? and config.has_key?("server_pools")
710
+ config["server_pools"].each { |resource|
711
+ if resource["name"] == name
712
+ orig_cfg = resource
713
+ break
714
+ end
715
+ }
716
+ end
717
+
718
+ orig_cfg
719
+ end
720
+
688
721
  end #class
689
722
  end #module