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
data/modules/mu/groomer.rb
CHANGED
|
@@ -30,6 +30,21 @@ module MU
|
|
|
30
30
|
["Chef", "Ansible"]
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
# List of known/supported groomers which are installed and appear to be working
|
|
34
|
+
# @return [Array<String>]
|
|
35
|
+
def self.availableGroomers
|
|
36
|
+
available = []
|
|
37
|
+
MU::Groomer.supportedGroomers.each { |groomer|
|
|
38
|
+
begin
|
|
39
|
+
groomerbase = loadGroomer(groomer)
|
|
40
|
+
available << groomer if groomerbase.available?
|
|
41
|
+
rescue LoadError
|
|
42
|
+
end
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
available
|
|
46
|
+
end
|
|
47
|
+
|
|
33
48
|
# Instance methods that any Groomer plugin must implement
|
|
34
49
|
def self.requiredMethods
|
|
35
50
|
[:preClean, :bootstrap, :haveBootstrapped?, :run, :saveDeployData, :getSecret, :saveSecret, :deleteSecret, :reinstall]
|
|
@@ -37,7 +52,7 @@ module MU
|
|
|
37
52
|
|
|
38
53
|
# Class methods that any Groomer plugin must implement
|
|
39
54
|
def self.requiredClassMethods
|
|
40
|
-
[:getSecret, :cleanup, :saveSecret, :deleteSecret]
|
|
55
|
+
[:getSecret, :cleanup, :saveSecret, :deleteSecret, :available?]
|
|
41
56
|
end
|
|
42
57
|
|
|
43
58
|
class Ansible;
|
|
@@ -24,6 +24,10 @@ module MU
|
|
|
24
24
|
class NoAnsibleExecError < MuError;
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# One or more Python dependencies missing
|
|
28
|
+
class AnsibleLibrariesError < MuError;
|
|
29
|
+
end
|
|
30
|
+
|
|
27
31
|
# Location in which we'll find our Ansible executables. This only applies
|
|
28
32
|
# to full-grown Mu masters; minimalist gem installs will have to make do
|
|
29
33
|
# with whatever Ansible executables they can find in $PATH.
|
|
@@ -40,6 +44,10 @@ module MU
|
|
|
40
44
|
@ansible_path = node.deploy.deploy_dir+"/ansible"
|
|
41
45
|
@ansible_execs = MU::Groomer::Ansible.ansibleExecDir
|
|
42
46
|
|
|
47
|
+
if !MU::Groomer::Ansible.checkPythonDependencies(@server.windows?)
|
|
48
|
+
raise AnsibleLibrariesError, "One or more python dependencies not available"
|
|
49
|
+
end
|
|
50
|
+
|
|
43
51
|
if !@ansible_execs or @ansible_execs.empty?
|
|
44
52
|
raise NoAnsibleExecError, "No Ansible executables found in visible paths"
|
|
45
53
|
end
|
|
@@ -54,6 +62,10 @@ module MU
|
|
|
54
62
|
installRoles
|
|
55
63
|
end
|
|
56
64
|
|
|
65
|
+
# Are Ansible executables and key libraries present and accounted for?
|
|
66
|
+
def self.available?(windows = false)
|
|
67
|
+
MU::Groomer::Ansible.checkPythonDependencies(windows)
|
|
68
|
+
end
|
|
57
69
|
|
|
58
70
|
# Indicate whether our server has been bootstrapped with Ansible
|
|
59
71
|
def haveBootstrapped?
|
|
@@ -245,7 +257,7 @@ module MU
|
|
|
245
257
|
"#{@server.config['name']}.yml"
|
|
246
258
|
end
|
|
247
259
|
|
|
248
|
-
cmd = %Q{cd #{@ansible_path} && echo "#{purpose}" && #{@ansible_execs}/ansible-playbook -i hosts #{playbook} --limit=#{@server.mu_name} --vault-password-file #{pwfile} --timeout=30 --vault-password-file #{@ansible_path}/.vault_pw -u #{ssh_user}}
|
|
260
|
+
cmd = %Q{cd #{@ansible_path} && echo "#{purpose}" && #{@ansible_execs}/ansible-playbook -i hosts #{playbook} --limit=#{@server.windows? ? @server.canonicalIP : @server.mu_name} --vault-password-file #{pwfile} --timeout=30 --vault-password-file #{@ansible_path}/.vault_pw -u #{ssh_user}}
|
|
249
261
|
|
|
250
262
|
retries = 0
|
|
251
263
|
begin
|
|
@@ -294,7 +306,7 @@ module MU
|
|
|
294
306
|
# Bootstrap our server with Ansible- basically, just make sure this node
|
|
295
307
|
# is listed in our deployment's Ansible inventory.
|
|
296
308
|
def bootstrap
|
|
297
|
-
@inventory.add(@server.config['name'], @server.mu_name)
|
|
309
|
+
@inventory.add(@server.config['name'], @server.windows? ? @server.canonicalIP : @server.mu_name)
|
|
298
310
|
play = {
|
|
299
311
|
"hosts" => @server.config['name']
|
|
300
312
|
}
|
|
@@ -387,11 +399,18 @@ module MU
|
|
|
387
399
|
allvars['deployment']
|
|
388
400
|
end
|
|
389
401
|
|
|
402
|
+
# Nuke everything associated with a deploy. Since we're just some files
|
|
403
|
+
# in the deploy directory, this doesn't have to do anything.
|
|
404
|
+
def self.cleanup(deploy_id, noop = false)
|
|
405
|
+
# deploy = MU::MommaCat.new(MU.deploy_id)
|
|
406
|
+
# inventory = Inventory.new(deploy)
|
|
407
|
+
end
|
|
408
|
+
|
|
390
409
|
# Expunge Ansible resources associated with a node.
|
|
391
410
|
# @param node [String]: The Mu name of the node in question.
|
|
392
411
|
# @param _vaults_to_clean [Array<Hash>]: Dummy argument, part of this method's interface but not used by the Ansible layer
|
|
393
412
|
# @param noop [Boolean]: Skip actual deletion, just state what we'd do
|
|
394
|
-
def self.
|
|
413
|
+
def self.purge(node, _vaults_to_clean = [], noop = false)
|
|
395
414
|
deploy = MU::MommaCat.new(MU.deploy_id)
|
|
396
415
|
inventory = Inventory.new(deploy)
|
|
397
416
|
# ansible_path = deploy.deploy_dir+"/ansible"
|
|
@@ -427,6 +446,50 @@ module MU
|
|
|
427
446
|
output
|
|
428
447
|
end
|
|
429
448
|
|
|
449
|
+
# Hunt down and return a path for a Python executable
|
|
450
|
+
# @return [String]
|
|
451
|
+
def self.pythonExecDir
|
|
452
|
+
path = nil
|
|
453
|
+
|
|
454
|
+
if File.exist?(BINDIR+"/python")
|
|
455
|
+
path = BINDIR
|
|
456
|
+
else
|
|
457
|
+
paths = [ansibleExecDir]
|
|
458
|
+
paths.concat(ENV['PATH'].split(/:/))
|
|
459
|
+
paths << "/usr/bin" # not always in path, esp in pared-down Docker images
|
|
460
|
+
paths.reject! { |p| p.nil? }
|
|
461
|
+
paths.uniq.each { |bindir|
|
|
462
|
+
if File.exist?(bindir+"/python")
|
|
463
|
+
path = bindir
|
|
464
|
+
break
|
|
465
|
+
end
|
|
466
|
+
}
|
|
467
|
+
end
|
|
468
|
+
path
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
# Make sure what's in our Python requirements.txt is reflected in the
|
|
472
|
+
# Python we're about to run for Ansible
|
|
473
|
+
def self.checkPythonDependencies(windows = false)
|
|
474
|
+
return nil if !ansibleExecDir
|
|
475
|
+
|
|
476
|
+
execline = File.readlines(ansibleExecDir+"/ansible-playbook").first.chomp.sub(/^#!/, '')
|
|
477
|
+
if !execline
|
|
478
|
+
MU.log "Unable to extract a Python executable from #{ansibleExecDir}/ansible-playbook", MU::ERR
|
|
479
|
+
return false
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
require 'tempfile'
|
|
483
|
+
f = Tempfile.new("pythoncheck")
|
|
484
|
+
f.puts "import ansible"
|
|
485
|
+
f.puts "import winrm" if windows
|
|
486
|
+
f.close
|
|
487
|
+
|
|
488
|
+
system(%Q{#{execline} #{f.path}})
|
|
489
|
+
f.unlink
|
|
490
|
+
$?.exitstatus == 0 ? true : false
|
|
491
|
+
end
|
|
492
|
+
|
|
430
493
|
# Hunt down and return a path for Ansible executables
|
|
431
494
|
# @return [String]
|
|
432
495
|
def self.ansibleExecDir
|
|
@@ -434,7 +497,9 @@ module MU
|
|
|
434
497
|
if File.exist?(BINDIR+"/ansible-playbook")
|
|
435
498
|
path = BINDIR
|
|
436
499
|
else
|
|
437
|
-
ENV['PATH'].split(/:/)
|
|
500
|
+
paths = ENV['PATH'].split(/:/)
|
|
501
|
+
paths << "/usr/bin"
|
|
502
|
+
paths.uniq.each { |bindir|
|
|
438
503
|
if File.exist?(bindir+"/ansible-playbook")
|
|
439
504
|
path = bindir
|
|
440
505
|
if !File.exist?(bindir+"/ansible-vault")
|
data/modules/mu/groomers/chef.rb
CHANGED
|
@@ -35,6 +35,12 @@ module MU
|
|
|
35
35
|
end
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
# Are the Chef libraries present and accounted for?
|
|
39
|
+
def self.available?(windows = false)
|
|
40
|
+
loadChefLib
|
|
41
|
+
@chefloaded
|
|
42
|
+
end
|
|
43
|
+
|
|
38
44
|
@chefloaded = false
|
|
39
45
|
@chefload_semaphore = Mutex.new
|
|
40
46
|
# Autoload is too brain-damaged to get Chef's subclasses/submodules, so
|
|
@@ -362,7 +368,7 @@ module MU
|
|
|
362
368
|
}
|
|
363
369
|
|
|
364
370
|
if resp.exitcode == 1 and output_lines.join("\n").match(/Chef Client finished/)
|
|
365
|
-
MU.log
|
|
371
|
+
MU.log output_lines.last
|
|
366
372
|
elsif resp.exitcode != 0
|
|
367
373
|
raise MU::Cloud::BootstrapTempFail if resp.exitcode == 35 or output_lines.join("\n").match(/REBOOT_SCHEDULED| WARN: Reboot requested:|Rebooting server at a recipe's request|Chef::Exceptions::Reboot/)
|
|
368
374
|
raise MU::Groomer::RunError, output_lines.slice(output_lines.length-50, output_lines.length).join("")
|
|
@@ -619,15 +625,16 @@ module MU
|
|
|
619
625
|
kb.name_args = [@server.mu_name]
|
|
620
626
|
kb.config[:manual] = true
|
|
621
627
|
kb.config[:winrm_transport] = :ssl
|
|
622
|
-
kb.config[:host] = @server.mu_name
|
|
623
628
|
kb.config[:winrm_port] = 5986
|
|
624
629
|
kb.config[:session_timeout] = timeout
|
|
625
630
|
kb.config[:operation_timeout] = timeout
|
|
626
631
|
if retries % 2 == 0
|
|
632
|
+
kb.config[:host] = canonical_addr
|
|
627
633
|
kb.config[:winrm_authentication_protocol] = :basic
|
|
628
634
|
kb.config[:winrm_user] = @server.config['windows_admin_username']
|
|
629
635
|
kb.config[:winrm_password] = @server.getWindowsAdminPassword
|
|
630
636
|
else
|
|
637
|
+
kb.config[:host] = @server.mu_name
|
|
631
638
|
kb.config[:winrm_authentication_protocol] = :cert
|
|
632
639
|
kb.config[:winrm_client_cert] = "#{MU.mySSLDir}/#{@server.mu_name}-winrm.crt"
|
|
633
640
|
kb.config[:winrm_client_key] = "#{MU.mySSLDir}/#{@server.mu_name}-winrm.key"
|
|
@@ -681,7 +688,7 @@ module MU
|
|
|
681
688
|
preClean(false) # it's ok for this to fail
|
|
682
689
|
rescue StandardError => e
|
|
683
690
|
end
|
|
684
|
-
MU::Groomer::Chef.
|
|
691
|
+
MU::Groomer::Chef.purge(@server.mu_name, nodeonly: true)
|
|
685
692
|
@config['forced_preclean'] = true
|
|
686
693
|
@server.reboot if @server.windows? # *sigh*
|
|
687
694
|
end
|
|
@@ -798,12 +805,52 @@ retry
|
|
|
798
805
|
end
|
|
799
806
|
end
|
|
800
807
|
|
|
808
|
+
# Purge Chef resources matching a particular deploy
|
|
809
|
+
# @param deploy_id [String]
|
|
810
|
+
# @param noop [Boolean]
|
|
811
|
+
def self.cleanup(deploy_id, noop = false)
|
|
812
|
+
return nil if deploy_id.nil? or deploy_id.empty?
|
|
813
|
+
begin
|
|
814
|
+
if File.exist?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
|
|
815
|
+
::Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
|
|
816
|
+
end
|
|
817
|
+
deadnodes = []
|
|
818
|
+
::Chef::Config[:environment] ||= MU.environment
|
|
819
|
+
q = ::Chef::Search::Query.new
|
|
820
|
+
begin
|
|
821
|
+
q.search("node", "tags_MU-ID:#{deploy_id}").each { |item|
|
|
822
|
+
next if item.is_a?(Integer)
|
|
823
|
+
item.each { |node|
|
|
824
|
+
deadnodes << node.name
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
rescue Net::HTTPServerException
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
begin
|
|
831
|
+
q.search("node", "name:#{deploy_id}-*").each { |item|
|
|
832
|
+
next if item.is_a?(Integer)
|
|
833
|
+
item.each { |node|
|
|
834
|
+
deadnodes << node.name
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
rescue Net::HTTPServerException
|
|
838
|
+
end
|
|
839
|
+
MU.log "Missed some Chef resources in node cleanup, purging now", MU::NOTICE if deadnodes.size > 0
|
|
840
|
+
deadnodes.uniq.each { |node|
|
|
841
|
+
MU::Groomer::Chef.purge(node, [], noop)
|
|
842
|
+
}
|
|
843
|
+
rescue LoadError
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
end
|
|
847
|
+
|
|
801
848
|
# Expunge Chef resources associated with a node.
|
|
802
849
|
# @param node [String]: The Mu name of the node in question.
|
|
803
850
|
# @param vaults_to_clean [Array<Hash>]: Some vaults to expunge
|
|
804
851
|
# @param noop [Boolean]: Skip actual deletion, just state what we'd do
|
|
805
852
|
# @param nodeonly [Boolean]: Just delete the node and its keys, but leave other artifacts
|
|
806
|
-
def self.
|
|
853
|
+
def self.purge(node, vaults_to_clean = [], noop = false, nodeonly: false)
|
|
807
854
|
loadChefLib
|
|
808
855
|
MU.log "Deleting Chef resources associated with #{node}"
|
|
809
856
|
if !nodeonly
|
data/modules/mu/logger.rb
CHANGED
|
@@ -33,6 +33,33 @@ module MU
|
|
|
33
33
|
# Show DEBUG log entries and extra call stack and threading info
|
|
34
34
|
LOUD = 2.freeze
|
|
35
35
|
|
|
36
|
+
# stash a hash map for color outputs
|
|
37
|
+
COLORMAP = {
|
|
38
|
+
MU::DEBUG => { :html => "orange", :ansi => :yellow },
|
|
39
|
+
MU::INFO => { :html => "green", :ansi => :green },
|
|
40
|
+
MU::NOTICE => { :html => "yellow", :ansi => :yellow },
|
|
41
|
+
MU::WARN => { :html => "orange", :ansi => :light_red },
|
|
42
|
+
MU::ERR => { :html => "red", :ansi => :red }
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
# minimum log verbosity at which we'll print various types of messages
|
|
46
|
+
PRINT_MSG_IF = {
|
|
47
|
+
MU::DEBUG => { :msg => LOUD, :details => LOUD },
|
|
48
|
+
MU::INFO => { :msg => NORMAL, :details => LOUD },
|
|
49
|
+
MU::NOTICE => { :msg => nil, :details => QUIET },
|
|
50
|
+
MU::WARN => { :msg => nil, :details => SILENT },
|
|
51
|
+
MU::ERR => { :msg => nil, :details => nil }
|
|
52
|
+
}.freeze
|
|
53
|
+
|
|
54
|
+
# Syslog equivalents of our log levels
|
|
55
|
+
SYSLOG_MAP = {
|
|
56
|
+
MU::DEBUG => Syslog::LOG_DEBUG,
|
|
57
|
+
MU::INFO => Syslog::LOG_NOTICE,
|
|
58
|
+
MU::NOTICE => Syslog::LOG_NOTICE,
|
|
59
|
+
MU::WARN => Syslog::LOG_WARNING,
|
|
60
|
+
MU::ERR => Syslog::LOG_ERR
|
|
61
|
+
}.freeze
|
|
62
|
+
|
|
36
63
|
attr_accessor :verbosity
|
|
37
64
|
@verbosity = MU::Logger::NORMAL
|
|
38
65
|
@quiet = false
|
|
@@ -76,59 +103,28 @@ module MU
|
|
|
76
103
|
html ||= @html
|
|
77
104
|
handle ||= @handle
|
|
78
105
|
color ||= @color
|
|
79
|
-
return if verbosity == MU::Logger::SILENT
|
|
80
|
-
return if verbosity < MU::Logger::LOUD and level == DEBUG
|
|
81
|
-
return if verbosity < MU::Logger::NORMAL and level == INFO
|
|
82
106
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
mod_root = Regexp.quote("#{ENV['MU_LIBDIR']}/modules/mu/")
|
|
87
|
-
bin_root = Regexp.quote("#{ENV['MU_INSTALLDIR']}/bin/")
|
|
88
|
-
caller_name = caller[1]
|
|
107
|
+
if verbosity == MU::Logger::SILENT or (verbosity < MU::Logger::LOUD and level == DEBUG) or (verbosity < MU::Logger::NORMAL and level == INFO)
|
|
108
|
+
return
|
|
109
|
+
end
|
|
89
110
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
caller_name
|
|
96
|
-
caller_name.sub!(/^modules\//, "")
|
|
111
|
+
if level == SUMMARY
|
|
112
|
+
@summary << msg
|
|
113
|
+
return
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
caller_name = extract_caller_name(caller[1])
|
|
97
117
|
|
|
98
118
|
time = Time.now.strftime("%b %d %H:%M:%S").to_s
|
|
99
119
|
|
|
100
120
|
Syslog.open("Mu/"+caller_name, Syslog::LOG_PID, Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3) if !Syslog.opened?
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
details = details[:details]
|
|
104
|
-
end
|
|
105
|
-
details = PP.pp(details, '') if !details.is_a?(String)
|
|
106
|
-
end
|
|
107
|
-
details = "<pre>"+details+"</pre>" if html
|
|
108
|
-
# We get passed literal quoted newlines sometimes, fix 'em. Get Windows'
|
|
109
|
-
# ugly line feeds too.
|
|
110
|
-
if !details.nil?
|
|
111
|
-
details = details.dup # in case it's frozen or something
|
|
112
|
-
details.gsub!(/\\n/, "\n")
|
|
113
|
-
details.gsub!(/(\\r|\r)/, "")
|
|
114
|
-
end
|
|
121
|
+
|
|
122
|
+
details = format_details(details, html)
|
|
115
123
|
|
|
116
124
|
msg = msg.first if msg.is_a?(Array)
|
|
117
125
|
msg = "" if msg == nil
|
|
118
126
|
msg = msg.to_s if !msg.is_a?(String) and msg.respond_to?(:to_s)
|
|
119
127
|
|
|
120
|
-
# wrapper for writing a log entry to multiple filehandles
|
|
121
|
-
# @param handles [Array<IO>]
|
|
122
|
-
# @param msgs [Array<String>]
|
|
123
|
-
def write(handles = [], msgs = [])
|
|
124
|
-
return if handles.nil? or msgs.nil?
|
|
125
|
-
handles.each { |h|
|
|
126
|
-
msgs.each { |m|
|
|
127
|
-
h.puts m
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
end
|
|
131
|
-
|
|
132
128
|
@@log_semaphere.synchronize {
|
|
133
129
|
handles = [handle]
|
|
134
130
|
extra_logfile = if deploy and deploy.deploy_dir and Dir.exist?(deploy.deploy_dir)
|
|
@@ -137,110 +133,41 @@ module MU
|
|
|
137
133
|
handles << extra_logfile if extra_logfile
|
|
138
134
|
msgs = []
|
|
139
135
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
end
|
|
155
|
-
Syslog.log(Syslog::LOG_DEBUG, msg.gsub(/%/, ''))
|
|
156
|
-
Syslog.log(Syslog::LOG_DEBUG, details.gsub(/%/, '')) if details
|
|
157
|
-
end
|
|
158
|
-
when INFO
|
|
159
|
-
if verbosity >= MU::Logger::NORMAL
|
|
160
|
-
if html
|
|
161
|
-
html_out "#{time} - #{caller_name} - #{msg}", "green"
|
|
162
|
-
elsif color
|
|
163
|
-
msgs << "#{time} - #{caller_name} - #{msg}".green.on_black
|
|
164
|
-
else
|
|
165
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
166
|
-
end
|
|
167
|
-
if verbosity >= MU::Logger::LOUD
|
|
168
|
-
if html
|
|
169
|
-
html_out " #{details}"
|
|
170
|
-
elsif color
|
|
171
|
-
msgs << "#{details}".white.on_black if details
|
|
172
|
-
else
|
|
173
|
-
msgs << "#{details}" if details
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
|
177
|
-
Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
|
178
|
-
end
|
|
179
|
-
when NOTICE
|
|
180
|
-
if html
|
|
181
|
-
html_out "#{time} - #{caller_name} - #{msg}", "yellow"
|
|
182
|
-
elsif color
|
|
183
|
-
msgs << "#{time} - #{caller_name} - #{msg}".yellow.on_black
|
|
184
|
-
else
|
|
185
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
186
|
-
end
|
|
187
|
-
if verbosity >= MU::Logger::QUIET
|
|
188
|
-
if html
|
|
189
|
-
html_out "#{caller_name} - #{msg}"
|
|
190
|
-
elsif color
|
|
191
|
-
msgs << "#{details}".white.on_black if details
|
|
192
|
-
else
|
|
193
|
-
msgs << "#{details}" if details
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
|
197
|
-
Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
|
198
|
-
when WARN
|
|
199
|
-
if html
|
|
200
|
-
html_out "#{time} - #{caller_name} - #{msg}", "orange"
|
|
201
|
-
elsif color
|
|
202
|
-
msgs << "#{time} - #{caller_name} - #{msg}".light_red.on_black
|
|
203
|
-
else
|
|
204
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
205
|
-
end
|
|
206
|
-
if verbosity >= MU::Logger::SILENT
|
|
207
|
-
if html
|
|
208
|
-
html_out "#{caller_name} - #{msg}"
|
|
209
|
-
elsif color
|
|
210
|
-
msgs << "#{details}".white.on_black if details
|
|
211
|
-
else
|
|
212
|
-
msgs << "#{details}" if details
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
Syslog.log(Syslog::LOG_WARNING, msg.gsub(/%/, ''))
|
|
216
|
-
Syslog.log(Syslog::LOG_WARNING, details.gsub(/%/, '')) if details
|
|
217
|
-
when ERR
|
|
218
|
-
if html
|
|
219
|
-
html_out "#{time} - #{caller_name} - #{msg}", "red"
|
|
220
|
-
html_out " #{details}" if details
|
|
221
|
-
elsif color
|
|
222
|
-
msgs << "#{time} - #{caller_name} - #{msg}".red.on_black
|
|
223
|
-
msgs << "#{details}".white.on_black if details
|
|
224
|
-
else
|
|
225
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
226
|
-
msgs << "#{details}" if details
|
|
227
|
-
end
|
|
228
|
-
Syslog.log(Syslog::LOG_ERR, msg.gsub(/%/, ''))
|
|
229
|
-
Syslog.log(Syslog::LOG_ERR, details.gsub(/%/, '')) if details
|
|
136
|
+
if !PRINT_MSG_IF[level][:msg] or level >= PRINT_MSG_IF[level][:msg]
|
|
137
|
+
if html
|
|
138
|
+
html_out "#{time} - #{caller_name} - #{msg}", COLORMAP[level][:html]
|
|
139
|
+
else
|
|
140
|
+
str = "#{time} - #{caller_name} - #{msg}"
|
|
141
|
+
str = str.send(COLORMAP[level][:ansi]).on_black if color
|
|
142
|
+
msgs << str
|
|
143
|
+
end
|
|
144
|
+
Syslog.log(SYSLOG_MAP[level], msg.gsub(/%/, ''))
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
if details and (!PRINT_MSG_IF[level][:details] or level >= PRINT_MSG_IF[level][:details])
|
|
148
|
+
if html
|
|
149
|
+
html_out " #{details}"
|
|
230
150
|
else
|
|
231
|
-
if
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
msgs << "#{time} - #{caller_name} - #{msg}".white.on_black
|
|
236
|
-
msgs << "#{details}".white.on_black if details
|
|
237
|
-
else
|
|
238
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
|
239
|
-
msgs << "#{details}" if details
|
|
240
|
-
end
|
|
241
|
-
Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
|
242
|
-
Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
|
151
|
+
details = details.white.on_black if color
|
|
152
|
+
msgs << details
|
|
153
|
+
end
|
|
154
|
+
Syslog.log(SYSLOG_MAP[level], details.gsub(/%/, ''))
|
|
243
155
|
end
|
|
156
|
+
|
|
157
|
+
# else
|
|
158
|
+
# if html
|
|
159
|
+
# html_out "#{time} - #{caller_name} - #{msg}"
|
|
160
|
+
# html_out " #{details}" if details
|
|
161
|
+
# elsif color
|
|
162
|
+
# msgs << "#{time} - #{caller_name} - #{msg}".white.on_black
|
|
163
|
+
# msgs << "#{details}".white.on_black if details
|
|
164
|
+
# else
|
|
165
|
+
# msgs << "#{time} - #{caller_name} - #{msg}"
|
|
166
|
+
# msgs << "#{details}" if details
|
|
167
|
+
# end
|
|
168
|
+
# Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
|
169
|
+
# Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
|
170
|
+
|
|
244
171
|
write(handles, msgs)
|
|
245
172
|
|
|
246
173
|
extra_logfile.close if extra_logfile
|
|
@@ -250,6 +177,43 @@ module MU
|
|
|
250
177
|
|
|
251
178
|
private
|
|
252
179
|
|
|
180
|
+
def format_details(details, html = false)
|
|
181
|
+
return if details.nil?
|
|
182
|
+
|
|
183
|
+
if details.is_a?(Hash) and details.has_key?(:details)
|
|
184
|
+
details = details[:details]
|
|
185
|
+
end
|
|
186
|
+
details = PP.pp(details, '') if !details.is_a?(String)
|
|
187
|
+
|
|
188
|
+
details = "<pre>"+details+"</pre>" if html
|
|
189
|
+
# We get passed literal quoted newlines sometimes, fix 'em. Get Windows'
|
|
190
|
+
# ugly line feeds too.
|
|
191
|
+
|
|
192
|
+
details = details.dup # in case it's frozen or something
|
|
193
|
+
details.gsub!(/\\n/, "\n")
|
|
194
|
+
details.gsub!(/(\\r|\r)/, "")
|
|
195
|
+
|
|
196
|
+
details
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# By which we mean, "get the filename (with the .rb stripped off) which
|
|
200
|
+
# originated the call to this method. Which, for our purposes, is the
|
|
201
|
+
# MU subclass that called us. Useful information. And it looks like Perl.
|
|
202
|
+
def extract_caller_name(caller_name)
|
|
203
|
+
return nil if !caller_name or !caller_name.is_a?(String)
|
|
204
|
+
mod_root = Regexp.quote("#{ENV['MU_LIBDIR']}/modules/mu/")
|
|
205
|
+
bin_root = Regexp.quote("#{ENV['MU_INSTALLDIR']}/bin/")
|
|
206
|
+
|
|
207
|
+
caller_name.sub!(/:.*/, "")
|
|
208
|
+
caller_name.sub!(/^\.\//, "")
|
|
209
|
+
caller_name.sub!(/^#{mod_root}/, "")
|
|
210
|
+
caller_name.sub!(/^#{bin_root}/, "")
|
|
211
|
+
caller_name.sub!(/\.r[ub]$/, "")
|
|
212
|
+
caller_name.sub!(/#{Regexp.quote(MU.myRoot)}\//, "")
|
|
213
|
+
caller_name.sub!(/^modules\//, "")
|
|
214
|
+
caller_name
|
|
215
|
+
end
|
|
216
|
+
|
|
253
217
|
# Output a log message as HTML.
|
|
254
218
|
#
|
|
255
219
|
# @param msg [String]: The log message to print
|
|
@@ -259,5 +223,17 @@ module MU
|
|
|
259
223
|
@handle.puts "<span style='color:#{rgb.css_rgb};'>#{msg}</span>"
|
|
260
224
|
end
|
|
261
225
|
|
|
226
|
+
# wrapper for writing a log entry to multiple filehandles
|
|
227
|
+
# @param handles [Array<IO>]
|
|
228
|
+
# @param msgs [Array<String>]
|
|
229
|
+
def write(handles = [], msgs = [])
|
|
230
|
+
return if handles.nil? or msgs.nil?
|
|
231
|
+
handles.each { |h|
|
|
232
|
+
msgs.each { |m|
|
|
233
|
+
h.puts m
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
end
|
|
237
|
+
|
|
262
238
|
end #class
|
|
263
239
|
end #module
|