cloud-mu 3.1.2 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- 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/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +10 -13
- 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 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- 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 +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- 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/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -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 +920 -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 +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- 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 +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- 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 +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- 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 +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
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
|
@@ -184,13 +190,13 @@ module MU
|
|
184
190
|
if !item.nil?
|
185
191
|
begin
|
186
192
|
loaded = ::ChefVault::Item.load(vault, item)
|
187
|
-
rescue ::ChefVault::Exceptions::KeysNotFound
|
193
|
+
rescue ::ChefVault::Exceptions::KeysNotFound
|
188
194
|
raise MuNoSuchSecret, "Can't load the Chef Vault #{vault}:#{item}. Does it exist? Chef user: #{MU.chef_user}"
|
189
195
|
end
|
190
196
|
else
|
191
197
|
# If we didn't ask for a particular item, list what we have.
|
192
198
|
begin
|
193
|
-
loaded = ::Chef::DataBag.load(vault).keys.select { |k
|
199
|
+
loaded = ::Chef::DataBag.load(vault).keys.select { |k| !k.match(/_keys$/) }
|
194
200
|
rescue Net::HTTPServerException
|
195
201
|
raise MuNoSuchSecret, "Failed to retrieve Vault #{vault}"
|
196
202
|
end
|
@@ -258,7 +264,6 @@ module MU
|
|
258
264
|
knifeAddToRunList(multiple: @config['run_list'])
|
259
265
|
end
|
260
266
|
|
261
|
-
pending_reboot_count = 0
|
262
267
|
chef_node = ::Chef::Node.load(@server.mu_name)
|
263
268
|
if !@config['application_attributes'].nil?
|
264
269
|
MU.log "Setting node:#{@server.mu_name} application_attributes", MU::DEBUG, details: @config['application_attributes']
|
@@ -300,7 +305,7 @@ module MU
|
|
300
305
|
cmd = "#{upgrade_cmd} chef-client --color || echo #{error_signal}"
|
301
306
|
end
|
302
307
|
Timeout::timeout(timeout) {
|
303
|
-
|
308
|
+
ssh.exec!(cmd) { |_ch, _stream, data|
|
304
309
|
extra_logfile = if Dir.exist?(@server.deploy.deploy_dir)
|
305
310
|
File.open(@server.deploy.deploy_dir+"/log", "a")
|
306
311
|
end
|
@@ -330,7 +335,7 @@ module MU
|
|
330
335
|
}
|
331
336
|
else
|
332
337
|
MU.log "Invoking Chef over WinRM on #{@server.mu_name}: #{purpose}"
|
333
|
-
winrm = @server.getWinRMSession(haveBootstrapped? ?
|
338
|
+
winrm = @server.getWinRMSession(haveBootstrapped? ? 2 : max_retries)
|
334
339
|
if @server.windows? and @server.windowsRebootPending?(winrm)
|
335
340
|
# Windows frequently gets stuck here
|
336
341
|
if retries > 5
|
@@ -363,7 +368,7 @@ module MU
|
|
363
368
|
}
|
364
369
|
|
365
370
|
if resp.exitcode == 1 and output_lines.join("\n").match(/Chef Client finished/)
|
366
|
-
MU.log
|
371
|
+
MU.log output_lines.last
|
367
372
|
elsif resp.exitcode != 0
|
368
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/)
|
369
374
|
raise MU::Groomer::RunError, output_lines.slice(output_lines.length-50, output_lines.length).join("")
|
@@ -380,7 +385,7 @@ module MU
|
|
380
385
|
sleep 30
|
381
386
|
end
|
382
387
|
retry
|
383
|
-
rescue
|
388
|
+
rescue SystemExit, Timeout::Error, MU::Cloud::BootstrapTempFail, Net::HTTPServerException, HTTPClient::ConnectTimeoutError, WinRM::WinRMError, Net::SSH::AuthenticationFailed, Net::SSH::Disconnect, Net::SSH::ConnectionTimeout, Net::SSH::Proxy::ConnectError, Net::SSH::Exception, Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::EPIPE, SocketError, IOError => e
|
384
389
|
begin
|
385
390
|
ssh.close if !ssh.nil?
|
386
391
|
rescue Net::SSH::Exception, IOError => e
|
@@ -390,6 +395,8 @@ module MU
|
|
390
395
|
MU.log "ssh session to #{@server.mu_name} was closed unexpectedly, waiting before trying again", MU::NOTICE
|
391
396
|
end
|
392
397
|
sleep 10
|
398
|
+
rescue StandardError => e
|
399
|
+
MU.log "Error I don't recognize closing ssh tunnel", MU::WARN, details: e.inspect
|
393
400
|
end
|
394
401
|
if e.instance_of?(MU::Groomer::RunError) and retries == 0 and max_retries > 1 and purpose != "Base Windows configuration"
|
395
402
|
MU.log "Got a run error, will attempt to install/update Chef Client on next attempt", MU::NOTICE
|
@@ -404,7 +411,7 @@ module MU
|
|
404
411
|
begin
|
405
412
|
preClean(true) # drop any Chef install that's not ours
|
406
413
|
@server.reboot # try gently rebooting the thing
|
407
|
-
rescue
|
414
|
+
rescue StandardError => e # it's ok to fail here (and to ignore failure)
|
408
415
|
MU.log "preclean err #{e.inspect}", MU::ERR
|
409
416
|
end
|
410
417
|
reboot_first_fail = false
|
@@ -414,9 +421,9 @@ module MU
|
|
414
421
|
if retries < max_retries
|
415
422
|
retries += 1
|
416
423
|
MU.log "#{@server.mu_name}: Chef run '#{purpose}' failed after #{Time.new - runstart} seconds, retrying (#{retries}/#{max_retries})", MU::WARN, details: e.message.dup
|
417
|
-
if purpose != "Base Windows configuration"
|
418
|
-
windows_try_ssh = !windows_try_ssh
|
419
|
-
end
|
424
|
+
# if purpose != "Base Windows configuration"
|
425
|
+
# windows_try_ssh = !windows_try_ssh
|
426
|
+
# end
|
420
427
|
if e.is_a?(WinRM::WinRMError)
|
421
428
|
if @server.windows? and retries >= 3 and retries % 3 == 0
|
422
429
|
# Mix in a hard reboot if WinRM isn't answering
|
@@ -429,7 +436,7 @@ module MU
|
|
429
436
|
@server.deploy.sendAdminSlack("Chef run '#{purpose}' failed on `#{@server.mu_name}` :crying_cat_face:", msg: e.message)
|
430
437
|
raise MU::Groomer::RunError, "#{@server.mu_name}: Chef run '#{purpose}' failed #{max_retries} times, last error was: #{e.message}"
|
431
438
|
end
|
432
|
-
rescue
|
439
|
+
rescue StandardError => e
|
433
440
|
@server.deploy.sendAdminSlack("Chef run '#{purpose}' failed on `#{@server.mu_name}` :crying_cat_face:", msg: e.inspect)
|
434
441
|
raise MU::Groomer::RunError, "Caught unexpected #{e.inspect} on #{@server.mu_name} in @groomer.run at #{e.backtrace[0]}"
|
435
442
|
|
@@ -443,8 +450,8 @@ module MU
|
|
443
450
|
def splunkVaultInit
|
444
451
|
self.class.loadChefLib
|
445
452
|
begin
|
446
|
-
|
447
|
-
rescue ::ChefVault::Exceptions::KeysNotFound
|
453
|
+
::ChefVault::Item.load("splunk", "admin_user")
|
454
|
+
rescue ::ChefVault::Exceptions::KeysNotFound
|
448
455
|
pw = Password.pronounceable(12..14)
|
449
456
|
creds = {
|
450
457
|
"username" => "admin",
|
@@ -550,7 +557,7 @@ module MU
|
|
550
557
|
winrm = @server.getWinRMSession(1, 30, winrm_retries: 2)
|
551
558
|
pp winrm.run(cmd)
|
552
559
|
return
|
553
|
-
rescue
|
560
|
+
rescue SystemExit, Timeout::Error, MU::Cloud::BootstrapTempFail, MU::MuError, Net::HTTPServerException, HTTPClient::ConnectTimeoutError, WinRM::WinRMError, Net::SSH::AuthenticationFailed, Net::SSH::Disconnect, Net::SSH::ConnectionTimeout, Net::SSH::Proxy::ConnectError, Net::SSH::Exception, Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::EPIPE, SocketError, IOError
|
554
561
|
MU.log "WinRM failure attempting Chef upgrade on #{@server.mu_name}, will fall back to ssh", MU::WARN
|
555
562
|
cmd = %Q{powershell.exe -inputformat none -noprofile "#{cmd}"}
|
556
563
|
end
|
@@ -558,7 +565,7 @@ module MU
|
|
558
565
|
|
559
566
|
MU.log "Attempting Chef upgrade via ssh on #{@server.mu_name}", MU::NOTICE, details: cmd
|
560
567
|
ssh = @server.getSSHSession(1)
|
561
|
-
|
568
|
+
ssh.exec!(cmd) { |_ch, _stream, data|
|
562
569
|
puts data
|
563
570
|
}
|
564
571
|
end
|
@@ -580,7 +587,7 @@ module MU
|
|
580
587
|
@config['cleaned_chef'] = true
|
581
588
|
end
|
582
589
|
|
583
|
-
|
590
|
+
_nat_ssh_key, _nat_ssh_user, _nat_ssh_host, canonical_addr, ssh_user, ssh_key_name = @server.getSSHConfig
|
584
591
|
|
585
592
|
MU.log "Bootstrapping #{@server.mu_name} (#{canonical_addr}) with knife"
|
586
593
|
|
@@ -593,11 +600,12 @@ module MU
|
|
593
600
|
json_attribs['skipinitialupdates'] = @config['skipinitialupdates']
|
594
601
|
end
|
595
602
|
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
603
|
+
# XXX this seems to break Knife Bootstrap
|
604
|
+
# vault_access = if !@config['vault_access'].nil?
|
605
|
+
# @config['vault_access']
|
606
|
+
# else
|
607
|
+
# []
|
608
|
+
# end
|
601
609
|
|
602
610
|
@server.windows? ? max_retries = 25 : max_retries = 10
|
603
611
|
@server.windows? ? timeout = 1800 : timeout = 300
|
@@ -617,13 +625,20 @@ module MU
|
|
617
625
|
kb.name_args = [@server.mu_name]
|
618
626
|
kb.config[:manual] = true
|
619
627
|
kb.config[:winrm_transport] = :ssl
|
620
|
-
kb.config[:host] = @server.mu_name
|
621
628
|
kb.config[:winrm_port] = 5986
|
622
629
|
kb.config[:session_timeout] = timeout
|
623
630
|
kb.config[:operation_timeout] = timeout
|
624
|
-
|
625
|
-
|
626
|
-
|
631
|
+
if retries % 2 == 0
|
632
|
+
kb.config[:host] = canonical_addr
|
633
|
+
kb.config[:winrm_authentication_protocol] = :basic
|
634
|
+
kb.config[:winrm_user] = @server.config['windows_admin_username']
|
635
|
+
kb.config[:winrm_password] = @server.getWindowsAdminPassword
|
636
|
+
else
|
637
|
+
kb.config[:host] = @server.mu_name
|
638
|
+
kb.config[:winrm_authentication_protocol] = :cert
|
639
|
+
kb.config[:winrm_client_cert] = "#{MU.mySSLDir}/#{@server.mu_name}-winrm.crt"
|
640
|
+
kb.config[:winrm_client_key] = "#{MU.mySSLDir}/#{@server.mu_name}-winrm.key"
|
641
|
+
end
|
627
642
|
# kb.config[:ca_trust_file] = "#{MU.mySSLDir}/Mu_CA.pem"
|
628
643
|
# XXX ca_trust_file doesn't work for some reason, so we have to set the below for now
|
629
644
|
kb.config[:winrm_ssl_verify_mode] = :verify_none
|
@@ -658,7 +673,7 @@ module MU
|
|
658
673
|
}
|
659
674
|
# throws Net::HTTPServerException if we haven't really bootstrapped
|
660
675
|
::Chef::Node.load(@server.mu_name)
|
661
|
-
rescue
|
676
|
+
rescue SystemExit, Timeout::Error, MU::Cloud::BootstrapTempFail, Net::HTTPServerException, HTTPClient::ConnectTimeoutError, WinRM::WinRMError, Net::SSH::AuthenticationFailed, Net::SSH::Disconnect, Net::SSH::ConnectionTimeout, Net::SSH::Proxy::ConnectError, Net::SSH::Exception, Errno::ECONNRESET, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::EPIPE, SocketError, IOError => e
|
662
677
|
if retries < max_retries
|
663
678
|
retries += 1
|
664
679
|
# Bad Chef installs are possible culprits of bootstrap failures, so
|
@@ -671,9 +686,9 @@ module MU
|
|
671
686
|
!@config['forced_preclean']
|
672
687
|
begin
|
673
688
|
preClean(false) # it's ok for this to fail
|
674
|
-
rescue
|
689
|
+
rescue StandardError => e
|
675
690
|
end
|
676
|
-
MU::Groomer::Chef.
|
691
|
+
MU::Groomer::Chef.purge(@server.mu_name, nodeonly: true)
|
677
692
|
@config['forced_preclean'] = true
|
678
693
|
@server.reboot if @server.windows? # *sigh*
|
679
694
|
end
|
@@ -683,7 +698,7 @@ module MU
|
|
683
698
|
else
|
684
699
|
raise MuError, "#{@server.mu_name}: Knife Bootstrap failed too many times with #{e.inspect}"
|
685
700
|
end
|
686
|
-
rescue
|
701
|
+
rescue StandardError => e
|
687
702
|
MU.log e.inspect, MU::ERR, details: e.backtrace
|
688
703
|
sleep 10*retries
|
689
704
|
retry
|
@@ -700,7 +715,7 @@ retry
|
|
700
715
|
end
|
701
716
|
}
|
702
717
|
knifeAddToRunList("role[mu-node]")
|
703
|
-
knifeAddToRunList("mu-tools::selinux")
|
718
|
+
knifeAddToRunList("recipe[mu-tools::selinux]")
|
704
719
|
|
705
720
|
grantSecretAccess(@server.mu_name, "windows_credentials") if @server.windows?
|
706
721
|
grantSecretAccess(@server.mu_name, "ssl_cert")
|
@@ -748,7 +763,7 @@ retry
|
|
748
763
|
return
|
749
764
|
end
|
750
765
|
|
751
|
-
@server.describe
|
766
|
+
@server.describe
|
752
767
|
saveChefMetadata
|
753
768
|
begin
|
754
769
|
chef_node = ::Chef::Node.load(@server.mu_name)
|
@@ -785,17 +800,57 @@ retry
|
|
785
800
|
chef_node.save
|
786
801
|
end
|
787
802
|
return chef_node['deployment']
|
788
|
-
rescue Net::HTTPServerException
|
803
|
+
rescue Net::HTTPServerException
|
789
804
|
MU.log "Attempted to save deployment to Chef node #{@server.mu_name} before it was bootstrapped.", MU::DEBUG
|
790
805
|
end
|
791
806
|
end
|
792
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
|
+
|
793
848
|
# Expunge Chef resources associated with a node.
|
794
849
|
# @param node [String]: The Mu name of the node in question.
|
795
850
|
# @param vaults_to_clean [Array<Hash>]: Some vaults to expunge
|
796
851
|
# @param noop [Boolean]: Skip actual deletion, just state what we'd do
|
797
852
|
# @param nodeonly [Boolean]: Just delete the node and its keys, but leave other artifacts
|
798
|
-
def self.
|
853
|
+
def self.purge(node, vaults_to_clean = [], noop = false, nodeonly: false)
|
799
854
|
loadChefLib
|
800
855
|
MU.log "Deleting Chef resources associated with #{node}"
|
801
856
|
if !nodeonly
|
@@ -804,7 +859,7 @@ retry
|
|
804
859
|
MU.log "knife vault remove #{vault['vault']} #{vault['item']} --search name:#{node}", MU::NOTICE
|
805
860
|
begin
|
806
861
|
::Chef::Knife.run(['vault', 'remove', vault['vault'], vault['item'], "--search", "name:#{node}"]) if !noop
|
807
|
-
rescue
|
862
|
+
rescue StandardError => e
|
808
863
|
MU.log "Error removing vault access for #{node} from #{vault['vault']} #{vault['item']}", MU::ERR, details: e.inspect
|
809
864
|
end
|
810
865
|
MU::MommaCat.unlock("vault-#{vault['vault']}")
|
@@ -858,7 +913,7 @@ retry
|
|
858
913
|
::Chef::Knife.run(['vault', 'refresh', vault['vault'], vault['item']])
|
859
914
|
end
|
860
915
|
end
|
861
|
-
rescue JSON::ParserError
|
916
|
+
rescue JSON::ParserError
|
862
917
|
MU.log "Error parsing JSON from data bag #{vault['vault']} #{vault['item']}_keys, skipping vault client cleanse", MU::WARN
|
863
918
|
end
|
864
919
|
end
|
@@ -887,18 +942,34 @@ retry
|
|
887
942
|
MU.log "Granting #{host} access to #{vault} #{item}"
|
888
943
|
begin
|
889
944
|
::Chef::Knife.run(['vault', 'update', vault, item, "--search", "name:#{host}"])
|
890
|
-
rescue
|
945
|
+
rescue StandardError => e
|
891
946
|
MU.log e.inspect, MU::ERR, details: caller
|
892
947
|
end
|
893
948
|
MU::MommaCat.unlock("vault-#{vault}", true)
|
894
949
|
end
|
895
950
|
|
951
|
+
# Execute a +knife+ command, and return its exit status and output
|
952
|
+
# @param cmd [String]: The knife subcommand to run, such as +vault list+
|
953
|
+
# @param showoutput [String]: Print the results to stdout
|
954
|
+
# @return [Array<Integer,String>]
|
955
|
+
def self.knifeCmd(cmd, showoutput = false)
|
956
|
+
MU.log "knife #{cmd}", MU::NOTICE if showoutput
|
957
|
+
output = `#{MU::Groomer::Chef.knife} #{cmd}`
|
958
|
+
exitstatus = $?.exitstatus
|
959
|
+
|
960
|
+
if showoutput
|
961
|
+
puts output
|
962
|
+
puts "Exit status: #{exitstatus}"
|
963
|
+
end
|
964
|
+
return [exitstatus, output]
|
965
|
+
end
|
966
|
+
|
896
967
|
private
|
897
968
|
|
898
969
|
# Save common Mu attributes to this node's Chef node structure.
|
899
970
|
def saveChefMetadata
|
900
971
|
self.class.loadChefLib
|
901
|
-
|
972
|
+
@server.getSSHConfig # why though
|
902
973
|
MU.log "Saving #{@server.mu_name} Chef artifacts"
|
903
974
|
|
904
975
|
begin
|
@@ -998,7 +1069,7 @@ retry
|
|
998
1069
|
deploy = MU::MommaCat.getLitter(MU.deploy_id, use_cache: false)
|
999
1070
|
@config['dependencies'].each{ |dep|
|
1000
1071
|
if dep['type'] == "database" && deploy.deployment.has_key?("databases") && deploy.deployment["databases"].has_key?(dep['name'])
|
1001
|
-
deploy.deployment["databases"][dep['name']].each { |
|
1072
|
+
deploy.deployment["databases"][dep['name']].values.each { |database|
|
1002
1073
|
grantSecretAccess(database['vault_name'], database['vault_item']) if database.has_key?("vault_name") && database.has_key?("vault_item")
|
1003
1074
|
}
|
1004
1075
|
end
|
@@ -1019,18 +1090,6 @@ retry
|
|
1019
1090
|
@secrets_granted["#{vault}:#{item}"] = item
|
1020
1091
|
end
|
1021
1092
|
|
1022
|
-
def self.knifeCmd(cmd, showoutput = false)
|
1023
|
-
MU.log "knife #{cmd}", MU::NOTICE if showoutput
|
1024
|
-
output = `#{MU::Groomer::Chef.knife} #{cmd}`
|
1025
|
-
exitstatus = $?.exitstatus
|
1026
|
-
|
1027
|
-
if showoutput
|
1028
|
-
puts output
|
1029
|
-
puts "Exit status: #{exitstatus}"
|
1030
|
-
end
|
1031
|
-
return [exitstatus, output]
|
1032
|
-
end
|
1033
|
-
|
1034
1093
|
def knifeCmd(cmd, showoutput = false)
|
1035
1094
|
self.class.knifeCmd(cmd, showoutput)
|
1036
1095
|
end
|
@@ -1063,9 +1122,11 @@ retry
|
|
1063
1122
|
if multiple.size == 0
|
1064
1123
|
multiple = [rl_entry]
|
1065
1124
|
end
|
1066
|
-
multiple.
|
1125
|
+
multiple.map! { |entry|
|
1067
1126
|
if !entry.match(/^role|recipe\[/)
|
1068
|
-
|
1127
|
+
"#{type}[#{entry}]"
|
1128
|
+
else
|
1129
|
+
entry
|
1069
1130
|
end
|
1070
1131
|
}
|
1071
1132
|
|
@@ -1110,8 +1171,8 @@ retry
|
|
1110
1171
|
MU.log("Adding #{rl_string} to Chef run_list of #{@server.mu_name}")
|
1111
1172
|
MU.log("Running #{query}", MU::DEBUG)
|
1112
1173
|
output=%x{#{query}}
|
1113
|
-
# XXX rescue
|
1114
|
-
rescue
|
1174
|
+
# XXX rescue StandardError is bad style
|
1175
|
+
rescue StandardError => e
|
1115
1176
|
raise MuError, "FAIL: #{MU::Groomer::Chef.knife} node run_list add #{@server.mu_name} \"#{rl_string}\": #{e.message} (output was #{output})"
|
1116
1177
|
end
|
1117
1178
|
end
|
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
|
@@ -66,66 +93,38 @@ module MU
|
|
66
93
|
def log(msg,
|
67
94
|
level=INFO,
|
68
95
|
details: nil,
|
69
|
-
html:
|
70
|
-
verbosity:
|
71
|
-
handle:
|
72
|
-
color:
|
96
|
+
html: nil,
|
97
|
+
verbosity: nil,
|
98
|
+
handle: nil,
|
99
|
+
color: nil,
|
73
100
|
deploy: MU.mommacat
|
74
101
|
)
|
75
102
|
verbosity ||= @verbosity
|
76
|
-
|
77
|
-
|
78
|
-
|
103
|
+
html ||= @html
|
104
|
+
handle ||= @handle
|
105
|
+
color ||= @color
|
79
106
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
mod_root = Regexp.quote("#{ENV['MU_LIBDIR']}/modules/mu/")
|
84
|
-
bin_root = Regexp.quote("#{ENV['MU_INSTALLDIR']}/bin/")
|
85
|
-
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
|
86
110
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
caller_name
|
93
|
-
caller_name.sub!(/^modules\//, "")
|
111
|
+
if level == SUMMARY
|
112
|
+
@summary << msg
|
113
|
+
return
|
114
|
+
end
|
115
|
+
|
116
|
+
caller_name = extract_caller_name(caller[1])
|
94
117
|
|
95
118
|
time = Time.now.strftime("%b %d %H:%M:%S").to_s
|
96
119
|
|
97
120
|
Syslog.open("Mu/"+caller_name, Syslog::LOG_PID, Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3) if !Syslog.opened?
|
98
|
-
|
99
|
-
|
100
|
-
details = details[:details]
|
101
|
-
end
|
102
|
-
details = PP.pp(details, '') if !details.is_a?(String)
|
103
|
-
end
|
104
|
-
details = "<pre>"+details+"</pre>" if @html
|
105
|
-
# We get passed literal quoted newlines sometimes, fix 'em. Get Windows'
|
106
|
-
# ugly line feeds too.
|
107
|
-
if !details.nil?
|
108
|
-
details = details.dup # in case it's frozen or something
|
109
|
-
details.gsub!(/\\n/, "\n")
|
110
|
-
details.gsub!(/(\\r|\r)/, "")
|
111
|
-
end
|
121
|
+
|
122
|
+
details = format_details(details, html)
|
112
123
|
|
113
124
|
msg = msg.first if msg.is_a?(Array)
|
114
125
|
msg = "" if msg == nil
|
115
126
|
msg = msg.to_s if !msg.is_a?(String) and msg.respond_to?(:to_s)
|
116
127
|
|
117
|
-
# wrapper for writing a log entry to multiple filehandles
|
118
|
-
# @param handles [Array<IO>]
|
119
|
-
# @param msgs [Array<String>]
|
120
|
-
def write(handles = [], msgs = [])
|
121
|
-
return if handles.nil? or msgs.nil?
|
122
|
-
handles.each { |h|
|
123
|
-
msgs.each { |m|
|
124
|
-
h.puts m
|
125
|
-
}
|
126
|
-
}
|
127
|
-
end
|
128
|
-
|
129
128
|
@@log_semaphere.synchronize {
|
130
129
|
handles = [handle]
|
131
130
|
extra_logfile = if deploy and deploy.deploy_dir and Dir.exist?(deploy.deploy_dir)
|
@@ -134,110 +133,41 @@ module MU
|
|
134
133
|
handles << extra_logfile if extra_logfile
|
135
134
|
msgs = []
|
136
135
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
Syslog.log(Syslog::LOG_DEBUG, msg.gsub(/%/, ''))
|
153
|
-
Syslog.log(Syslog::LOG_DEBUG, details.gsub(/%/, '')) if details
|
154
|
-
end
|
155
|
-
when INFO
|
156
|
-
if verbosity >= MU::Logger::NORMAL
|
157
|
-
if @html
|
158
|
-
html_out "#{time} - #{caller_name} - #{msg}", "green"
|
159
|
-
elsif color
|
160
|
-
msgs << "#{time} - #{caller_name} - #{msg}".green.on_black
|
161
|
-
else
|
162
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
163
|
-
end
|
164
|
-
if verbosity >= MU::Logger::LOUD
|
165
|
-
if @html
|
166
|
-
html_out " #{details}"
|
167
|
-
elsif color
|
168
|
-
msgs << "#{details}".white.on_black if details
|
169
|
-
else
|
170
|
-
msgs << "#{details}" if details
|
171
|
-
end
|
172
|
-
end
|
173
|
-
Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
174
|
-
Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
175
|
-
end
|
176
|
-
when NOTICE
|
177
|
-
if @html
|
178
|
-
html_out "#{time} - #{caller_name} - #{msg}", "yellow"
|
179
|
-
elsif color
|
180
|
-
msgs << "#{time} - #{caller_name} - #{msg}".yellow.on_black
|
181
|
-
else
|
182
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
183
|
-
end
|
184
|
-
if verbosity >= MU::Logger::QUIET
|
185
|
-
if @html
|
186
|
-
html_out "#{caller_name} - #{msg}"
|
187
|
-
elsif color
|
188
|
-
msgs << "#{details}".white.on_black if details
|
189
|
-
else
|
190
|
-
msgs << "#{details}" if details
|
191
|
-
end
|
192
|
-
end
|
193
|
-
Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
194
|
-
Syslog.log(Syslog::LOG_NOTICE, details.gsub(/%/, '')) if details
|
195
|
-
when WARN
|
196
|
-
if @html
|
197
|
-
html_out "#{time} - #{caller_name} - #{msg}", "orange"
|
198
|
-
elsif color
|
199
|
-
msgs << "#{time} - #{caller_name} - #{msg}".light_red.on_black
|
200
|
-
else
|
201
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
202
|
-
end
|
203
|
-
if verbosity >= MU::Logger::SILENT
|
204
|
-
if @html
|
205
|
-
html_out "#{caller_name} - #{msg}"
|
206
|
-
elsif color
|
207
|
-
msgs << "#{details}".white.on_black if details
|
208
|
-
else
|
209
|
-
msgs << "#{details}" if details
|
210
|
-
end
|
211
|
-
end
|
212
|
-
Syslog.log(Syslog::LOG_WARNING, msg.gsub(/%/, ''))
|
213
|
-
Syslog.log(Syslog::LOG_WARNING, details.gsub(/%/, '')) if details
|
214
|
-
when ERR
|
215
|
-
if @html
|
216
|
-
html_out "#{time} - #{caller_name} - #{msg}", "red"
|
217
|
-
html_out " #{details}" if details
|
218
|
-
elsif color
|
219
|
-
msgs << "#{time} - #{caller_name} - #{msg}".red.on_black
|
220
|
-
msgs << "#{details}".white.on_black if details
|
221
|
-
else
|
222
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
223
|
-
msgs << "#{details}" if details
|
224
|
-
end
|
225
|
-
Syslog.log(Syslog::LOG_ERR, msg.gsub(/%/, ''))
|
226
|
-
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}"
|
227
150
|
else
|
228
|
-
if
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
msgs << "#{time} - #{caller_name} - #{msg}".white.on_black
|
233
|
-
msgs << "#{details}".white.on_black if details
|
234
|
-
else
|
235
|
-
msgs << "#{time} - #{caller_name} - #{msg}"
|
236
|
-
msgs << "#{details}" if details
|
237
|
-
end
|
238
|
-
Syslog.log(Syslog::LOG_NOTICE, msg.gsub(/%/, ''))
|
239
|
-
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(/%/, ''))
|
240
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
|
+
|
241
171
|
write(handles, msgs)
|
242
172
|
|
243
173
|
extra_logfile.close if extra_logfile
|
@@ -247,6 +177,43 @@ module MU
|
|
247
177
|
|
248
178
|
private
|
249
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
|
+
|
250
217
|
# Output a log message as HTML.
|
251
218
|
#
|
252
219
|
# @param msg [String]: The log message to print
|
@@ -256,5 +223,17 @@ module MU
|
|
256
223
|
@handle.puts "<span style='color:#{rgb.css_rgb};'>#{msg}</span>"
|
257
224
|
end
|
258
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
|
+
|
259
238
|
end #class
|
260
239
|
end #module
|