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.
- checksums.yaml +4 -4
- data/Dockerfile +5 -1
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/tasks/main.yml +16 -0
- data/bin/mu-adopt +16 -12
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -1
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +37 -12
- data/cloud-mu.gemspec +3 -3
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +1 -1
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/windows-client.rb +25 -22
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +2 -0
- data/extras/image-generators/AWS/win2k16.yaml +2 -0
- data/extras/image-generators/AWS/win2k19.yaml +2 -0
- data/modules/mommacat.ru +1 -1
- data/modules/mu.rb +86 -98
- data/modules/mu/adoption.rb +373 -58
- data/modules/mu/cleanup.rb +214 -303
- data/modules/mu/cloud.rb +128 -1733
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +929 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +169 -0
- data/modules/mu/config.rb +123 -81
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +7 -2
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +5 -4
- data/modules/mu/config/doc_helpers.rb +5 -6
- data/modules/mu/config/endpoint.rb +2 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +17 -8
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +8 -19
- data/modules/mu/config/ref.rb +92 -14
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +38 -37
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +12 -13
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +11 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +27 -23
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +90 -90
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +34 -20
- data/modules/mu/groomer.rb +16 -1
- data/modules/mu/groomers/ansible.rb +69 -4
- data/modules/mu/groomers/chef.rb +51 -4
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +97 -4
- data/modules/mu/mommacat.rb +160 -874
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +110 -3
- data/modules/mu/mommacat/search.rb +497 -0
- data/modules/mu/mommacat/storage.rb +252 -194
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +258 -57
- data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +95 -84
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +26 -12
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +39 -32
- data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
- data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
- data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +77 -47
- data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
- data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
- data/modules/mu/{clouds → providers}/aws/role.rb +76 -48
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
- data/modules/mu/{clouds → providers}/aws/server.rb +66 -98
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +42 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
- data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/vpc.rb +143 -74
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
- data/modules/mu/{clouds → providers}/azure.rb +13 -0
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +29 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +4 -4
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +38 -20
- data/modules/mu/{clouds → providers}/google/database.rb +5 -12
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +6 -6
- data/modules/mu/{clouds → providers}/google/group.rb +9 -17
- data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/google/role.rb +50 -31
- data/modules/mu/{clouds → providers}/google/server.rb +41 -24
- data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
- data/modules/mu/{clouds → providers}/google/user.rb +34 -24
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +45 -14
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +2 -2
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +122 -92
- data/modules/mu/clouds/aws/database.rb +0 -1974
- 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
|
-
|
|
111
|
-
MU.
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
337
|
-
|
|
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
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
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
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
434
|
-
#
|
|
435
|
-
#
|
|
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
|
-
|
|
472
|
-
|
|
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
|
-
|
|
487
|
-
|
|
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
|
-
|
|
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
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|