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
@@ -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,27 @@ 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
+ # existing_deploys
127
+ @deployment[attrs[:cfg_plural]].each_pair { |res_name, data|
128
+ orig_cfg = findResourceConfig(attrs[:cfg_plural], res_name, (scrub_with || @original_config))
129
+
130
+ if orig_cfg.nil? and (!data['mu_name'] or data['mu_name'] =~ /^#{Regexp.quote(@deploy_id)}/)
131
+ MU.log "#{res_type} #{res_name} no longer configured, will remove deployment metadata", MU::NOTICE, details: data
132
+ deletia << res_name
133
+ end
134
+ }
135
+ @deployment[attrs[:cfg_plural]].reject! { |k, v| deletia.include?(k) }
136
+ }
137
+
138
+ if save_now
139
+ save!
140
+ MU.log "New config saved to #{deploy_dir}/basket_of_kittens.json"
141
+ end
112
142
  end
113
143
 
114
144
  @lock_semaphore = Mutex.new
@@ -147,11 +177,11 @@ module MU
147
177
  # @param id [String]: The lock identifier to release.
148
178
  # @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
179
  # return [false, nil]
150
- def self.lock(id, nonblock = false, global = false)
180
+ def self.lock(id, nonblock = false, global = false, retries: 0, deploy_id: MU.deploy_id)
151
181
  raise MuError, "Can't pass a nil id to MU::MommaCat.lock" if id.nil?
152
182
 
153
183
  if !global
154
- lockdir = "#{deploy_dir(MU.deploy_id)}/locks"
184
+ lockdir = "#{deploy_dir(deploy_id)}/locks"
155
185
  else
156
186
  lockdir = File.expand_path(MU.dataDir+"/locks")
157
187
  end
@@ -160,6 +190,7 @@ module MU
160
190
  MU.log "Creating #{lockdir}", MU::DEBUG
161
191
  Dir.mkdir(lockdir, 0700)
162
192
  end
193
+ nonblock = true if retries > 0
163
194
 
164
195
  @lock_semaphore.synchronize {
165
196
  if @locks[Thread.current.object_id].nil?
@@ -168,11 +199,34 @@ module MU
168
199
 
169
200
  @locks[Thread.current.object_id][id] = File.open("#{lockdir}/#{id}.lock", File::CREAT|File::RDWR, 0600)
170
201
  }
171
- MU.log "Getting a lock on #{lockdir}/#{id}.lock (thread #{Thread.current.object_id})...", MU::DEBUG
202
+
203
+ MU.log "Getting a lock on #{lockdir}/#{id}.lock (thread #{Thread.current.object_id})...", MU::DEBUG, details: caller
204
+ show_relevant = Proc.new {
205
+ @locks.each_pair { |thread_id, lock|
206
+ lock.each_pair { |lockid, lockpath|
207
+ if lockid == id
208
+ thread = Thread.list.select { |t| t.object_id == thread_id }.first
209
+ if thread.object_id != Thread.current.object_id
210
+ MU.log "#{thread_id} sitting on #{id}", MU::WARN, thread.backtrace
211
+ end
212
+ end
213
+ }
214
+ }
215
+ }
172
216
  begin
173
217
  if nonblock
174
218
  if !@locks[Thread.current.object_id][id].flock(File::LOCK_EX|File::LOCK_NB)
175
- return false
219
+ if retries > 0
220
+ success = false
221
+ MU.retrier([], loop_if: Proc.new { !success }, loop_msg: "Waiting for lock on #{lockdir}/#{id}.lock...", max: retries) {
222
+ success = @locks[Thread.current.object_id][id].flock(File::LOCK_EX|File::LOCK_NB)
223
+ show_relevant.call() if !success
224
+ }
225
+ show_relevant.call() if !success
226
+ return success
227
+ else
228
+ return false
229
+ end
176
230
  end
177
231
  else
178
232
  @locks[Thread.current.object_id][id].flock(File::LOCK_EX)
@@ -186,11 +240,11 @@ module MU
186
240
 
187
241
  # Release a flock() lock.
188
242
  # @param id [String]: The lock identifier to release.
189
- def self.unlock(id, global = false)
243
+ def self.unlock(id, global = false, deploy_id: MU.deploy_id)
190
244
  raise MuError, "Can't pass a nil id to MU::MommaCat.unlock" if id.nil?
191
245
  lockdir = nil
192
246
  if !global
193
- lockdir = "#{deploy_dir(MU.deploy_id)}/locks"
247
+ lockdir = "#{deploy_dir(deploy_id)}/locks"
194
248
  else
195
249
  lockdir = File.expand_path(MU.dataDir+"/locks")
196
250
  end
@@ -332,32 +386,17 @@ module MU
332
386
  Dir.mkdir(deploy_dir, 0700)
333
387
  end
334
388
 
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
389
+ writeFile("origin.json", JSON.pretty_generate(origin)) if !origin.nil?
390
+ writeFile("private_key", @private_key) if !@private_key.nil?
391
+ writeFile("public_key", @public_key) if !@public_key.nil?
352
392
 
353
393
  if !@deployment.nil? and @deployment.size > 0
354
394
  @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
395
+ [:public_key, :timestamp, :seed, :appname, :handle, :ssh_public_key].each { |var|
396
+ value = instance_variable_get(("@"+var.to_s).to_sym)
397
+ @deployment[var.to_s] = value if value
398
+ }
399
+
361
400
  begin
362
401
  # XXX doing this to trigger JSON errors before stomping the stored
363
402
  # file...
@@ -380,36 +419,15 @@ module MU
380
419
  end
381
420
 
382
421
  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
422
+ writeFile("basket_of_kittens.json", JSON.pretty_generate(MU::Config.manxify(@original_config)))
386
423
  end
387
424
 
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
425
+ writeFile("node_ssh.key", @ssh_private_key) if !@ssh_private_key.nil?
426
+ writeFile("node_ssh.pub", @ssh_public_key) if !@ssh_public_key.nil?
427
+ writeFile("ssh_key_name", @ssh_key_name) if !@ssh_key_name.nil?
428
+ writeFile("environment_name", @environment) if !@environment.nil?
429
+ writeFile("deploy_secret", @deploy_secret) if !@deploy_secret.nil?
430
+
413
431
  if !@secrets.nil?
414
432
  secretdir = "#{deploy_dir}/secrets"
415
433
  if !Dir.exist?(secretdir)
@@ -418,9 +436,7 @@ module MU
418
436
  end
419
437
  @secrets.each_pair { |type, servers|
420
438
  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
439
+ writeFile("secrets/#{type}.#{server}", svr_secret)
424
440
  }
425
441
  }
426
442
  end
@@ -430,146 +446,64 @@ module MU
430
446
  syncLitter(@deployment['servers'].keys, triggering_node: triggering_node, save_only: true) if @deployment.has_key?("servers")
431
447
  end
432
448
 
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
-
449
+ # Read all of our +deployment.json+ files in and stick them in a hash. Used
450
+ # by search routines that just need to skim this data without loading
451
+ # entire {MU::MommaCat} objects.
452
+ def self.cacheDeployMetadata(deploy_id = nil, use_cache: false)
469
453
  deploy_root = File.expand_path(MU.dataDir+"/deployments")
470
454
  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
455
+ @@deploy_cache ||= {}
456
+ return if !Dir.exist?(deploy_root)
485
457
 
486
- next
487
- end
458
+ Dir.entries(deploy_root).each { |deploy|
459
+ this_deploy_dir = deploy_root+"/"+deploy
460
+ this_deploy_file = this_deploy_dir+"/deployment.json"
461
+
462
+ if deploy == "." or deploy == ".." or !Dir.exist?(this_deploy_dir) or
463
+ (deploy_id and deploy_id != deploy) or
464
+ !File.size?(this_deploy_file) or
465
+ (use_cache and @@deploy_cache[deploy] and @@deploy_cache[deploy]['mtime'] == File.mtime(this_deploy_file))
466
+ next
467
+ end
488
468
 
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")
469
+ @@deploy_cache[deploy] ||= {}
494
470
 
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
- }
471
+ MU.log "Caching deploy #{deploy}", MU::DEBUG
472
+ lock = File.open(this_deploy_file, File::RDONLY)
473
+ lock.flock(File::LOCK_EX)
474
+ @@deploy_cache[deploy]['mtime'] = File.mtime(this_deploy_file)
475
+
476
+ begin
477
+ @@deploy_cache[deploy]['data'] = JSON.parse(File.read(this_deploy_file))
478
+ next if @@deploy_cache[deploy]['data'].nil?
479
+ # Populate some generable entries that should be in the deploy
480
+ # data. Also, bounce out if we realize we've found exactly what
481
+ # we needed already.
482
+ MU::Cloud.resource_types.values.each { |attrs|
483
+
484
+ next if @@deploy_cache[deploy]['data'][attrs[:cfg_plural]].nil?
485
+ if attrs[:has_multiples]
486
+ @@deploy_cache[deploy]['data'][attrs[:cfg_plural]].each_pair { |node_class, nodes|
487
+ next if nodes.nil? or !nodes.is_a?(Hash)
488
+ nodes.each_pair { |nodename, data|
489
+ next if !data.is_a?(Hash)
490
+ data['#MU_NODE_CLASS'] ||= node_class
491
+ data['#MU_NAME'] ||= nodename
492
+ data["cloud"] ||= MU::Config.defaultCloud
528
493
  }
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
494
+ }
495
+ end
496
+ }
497
+ rescue JSON::ParserError
498
+ raise MuError, "JSON parse failed on #{this_deploy_file}\n\n"+File.read(this_deploy_file)
499
+ ensure
534
500
  lock.flock(File::LOCK_UN)
535
501
  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
502
  end
554
503
  }
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
504
+ }
571
505
 
572
- return matches
506
+ @@deploy_cache
573
507
  end
574
508
 
575
509
  # Get the deploy directory
@@ -604,6 +538,105 @@ module MU
604
538
  end
605
539
 
606
540
  private
541
+
542
+ def writeFile(filename, contents)
543
+ file = File.new("#{deploy_dir}/#{filename}", File::CREAT|File::TRUNC|File::RDWR, 0600)
544
+ file.puts contents
545
+ file.close
546
+ end
547
+
548
+ # Helper for +initialize+
549
+ def setDeploySecret
550
+ credsets = {}
551
+ MU::Cloud.resource_types.values.each { |attrs|
552
+ if !@original_config[attrs[:cfg_plural]].nil? and @original_config[attrs[:cfg_plural]].size > 0
553
+ @original_config[attrs[:cfg_plural]].each { |resource|
554
+
555
+ credsets[resource['cloud']] ||= []
556
+ credsets[resource['cloud']] << resource['credentials']
557
+ @clouds[resource['cloud']] = 0 if !@clouds.has_key?(resource['cloud'])
558
+ @clouds[resource['cloud']] = @clouds[resource['cloud']] + 1
559
+
560
+ }
561
+ end
562
+ }
563
+
564
+ MU.log "Creating deploy secret for #{MU.deploy_id}"
565
+ @deploy_secret = Password.random(256)
566
+ if !@original_config['scrub_mu_isms'] and !@no_artifacts
567
+ credsets.each_pair { |cloud, creds|
568
+ creds.uniq!
569
+ creds.each { |credentials|
570
+ MU::Cloud.cloudClass(cloud).writeDeploySecret(@deploy_id, @deploy_secret, credentials: credentials)
571
+ }
572
+ }
573
+ end
574
+ end
575
+
576
+ def loadObjects(delay_descriptor_load)
577
+ # Load up MU::Cloud objects for all our kittens in this deploy
578
+
579
+ MU::Cloud.resource_types.each_pair { |res_type, attrs|
580
+ type = attrs[:cfg_plural]
581
+ next if !@deployment.has_key?(type)
582
+
583
+ deletia = {}
584
+ @deployment[type].each_pair { |res_name, data|
585
+ orig_cfg = findResourceConfig(type, res_name)
586
+
587
+ if orig_cfg.nil?
588
+ 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
589
+ next
590
+ end
591
+
592
+ if orig_cfg['vpc']
593
+ ref = if orig_cfg['vpc']['id'] and orig_cfg['vpc']['id'].is_a?(Hash)
594
+ orig_cfg['vpc']['id']['mommacat'] = self
595
+ MU::Config::Ref.get(orig_cfg['vpc']['id'])
596
+ else
597
+ orig_cfg['vpc']['mommacat'] = self
598
+ MU::Config::Ref.get(orig_cfg['vpc'])
599
+ end
600
+ orig_cfg['vpc'].delete('mommacat')
601
+ orig_cfg['vpc'] = ref if ref.kitten(shallow: true)
602
+ end
603
+
604
+ begin
605
+ if attrs[:has_multiples]
606
+ data.keys.each { |mu_name|
607
+ addKitten(type, res_name, attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: mu_name, delay_descriptor_load: delay_descriptor_load))
608
+ }
609
+ else
610
+ addKitten(type, res_name, attrs[:interface].new(mommacat: self, kitten_cfg: orig_cfg, mu_name: data['mu_name'], cloud_id: data['cloud_id']))
611
+ end
612
+ rescue StandardError => e
613
+ if e.class != MU::Cloud::MuCloudResourceNotImplemented
614
+ MU.log "Failed to load an existing resource of type '#{type}' in #{@deploy_id}: #{e.inspect}", MU::WARN, details: e.backtrace
615
+ end
616
+ end
617
+ }
618
+
619
+ }
620
+ end
621
+
622
+ # Helper for +initialize+
623
+ def initDeployDirectory
624
+ if !Dir.exist?(MU.dataDir+"/deployments")
625
+ MU.log "Creating #{MU.dataDir}/deployments", MU::DEBUG
626
+ Dir.mkdir(MU.dataDir+"/deployments", 0700)
627
+ end
628
+ path = File.expand_path(MU.dataDir+"/deployments")+"/"+@deploy_id
629
+ if !Dir.exist?(path)
630
+ MU.log "Creating #{path}", MU::DEBUG
631
+ Dir.mkdir(path, 0700)
632
+ end
633
+
634
+ @ssh_key_name, @ssh_private_key, @ssh_public_key = self.SSHKey
635
+ if !File.exist?(deploy_dir+"/private_key")
636
+ @private_key, @public_key = createDeployKey
637
+ end
638
+
639
+ end
607
640
 
608
641
  ###########################################################################
609
642
  ###########################################################################
@@ -685,5 +718,30 @@ module MU
685
718
  }
686
719
  end
687
720
 
721
+ def findResourceConfig(type, name, config = @original_config)
722
+ orig_cfg = nil
723
+ if config.has_key?(type)
724
+ config[type].each { |resource|
725
+ if resource["name"] == name
726
+ orig_cfg = resource
727
+ break
728
+ end
729
+ }
730
+ end
731
+
732
+ # Some Server objects originated from ServerPools, get their
733
+ # configs from there
734
+ if type == "servers" and orig_cfg.nil? and config.has_key?("server_pools")
735
+ config["server_pools"].each { |resource|
736
+ if resource["name"] == name
737
+ orig_cfg = resource
738
+ break
739
+ end
740
+ }
741
+ end
742
+
743
+ orig_cfg
744
+ end
745
+
688
746
  end #class
689
747
  end #module