cloud-mu 3.1.6 → 3.4.0
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 +1 -1
- data/bin/mu-adopt +15 -12
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +37 -1
- 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-run-tests +37 -12
- data/cloud-mu.gemspec +4 -4
- data/cookbooks/mu-tools/attributes/default.rb +7 -0
- data/cookbooks/mu-tools/libraries/helper.rb +87 -3
- data/cookbooks/mu-tools/recipes/apply_security.rb +39 -23
- data/cookbooks/mu-tools/recipes/aws_api.rb +13 -0
- data/cookbooks/mu-tools/recipes/google_api.rb +4 -0
- data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
- data/cookbooks/mu-tools/resources/disk.rb +33 -12
- data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
- data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
- data/extras/clean-stock-amis +10 -2
- data/extras/generate-stock-images +7 -3
- data/extras/image-generators/AWS/centos7.yaml +19 -16
- data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
- data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
- data/modules/mommacat.ru +2 -2
- data/modules/mu.rb +84 -97
- data/modules/mu/adoption.rb +359 -59
- data/modules/mu/cleanup.rb +67 -44
- data/modules/mu/cloud.rb +108 -1754
- 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 +178 -0
- data/modules/mu/config.rb +122 -80
- 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 +2 -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 +4 -5
- 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 +81 -9
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +30 -34
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +5 -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 +10 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +13 -17
- data/modules/mu/defaults/AWS.yaml +106 -106
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +33 -19
- data/modules/mu/groomer.rb +15 -0
- data/modules/mu/groomers/chef.rb +3 -0
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +22 -1
- data/modules/mu/mommacat.rb +71 -26
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +82 -3
- data/modules/mu/mommacat/search.rb +59 -16
- data/modules/mu/mommacat/storage.rb +119 -48
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +248 -62
- 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 +65 -63
- data/modules/mu/providers/aws/database.rb +1747 -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 +291 -133
- 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 +469 -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 +112 -78
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +172 -41
- data/modules/mu/{clouds → providers}/aws/server.rb +120 -145
- 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 +141 -73
- data/modules/mu/{clouds → providers}/aws/vpc_subnet.rb +0 -0
- data/modules/mu/{clouds → providers}/azure.rb +4 -1
- 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 +1 -1
- 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 +15 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +2 -2
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +29 -14
- data/modules/mu/{clouds → providers}/google/database.rb +2 -9
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +4 -4
- 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 +2 -2
- data/modules/mu/{clouds → providers}/google/role.rb +46 -35
- data/modules/mu/{clouds → providers}/google/server.rb +26 -11
- data/modules/mu/{clouds → providers}/google/server_pool.rb +11 -11
- data/modules/mu/{clouds → providers}/google/user.rb +32 -22
- 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 +38 -3
- 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 +2 -2
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +126 -98
- 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]
|
data/modules/mu/groomers/chef.rb
CHANGED
|
@@ -805,6 +805,9 @@ retry
|
|
|
805
805
|
end
|
|
806
806
|
end
|
|
807
807
|
|
|
808
|
+
# Purge Chef resources matching a particular deploy
|
|
809
|
+
# @param deploy_id [String]
|
|
810
|
+
# @param noop [Boolean]
|
|
808
811
|
def self.cleanup(deploy_id, noop = false)
|
|
809
812
|
return nil if deploy_id.nil? or deploy_id.empty?
|
|
810
813
|
begin
|
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
|
data/modules/mu/master.rb
CHANGED
|
@@ -602,7 +602,7 @@ module MU
|
|
|
602
602
|
return
|
|
603
603
|
end
|
|
604
604
|
if ssh_key_name.nil? or ssh_key_name.empty?
|
|
605
|
-
MU.log "Failed to extract ssh_key_name for #{
|
|
605
|
+
MU.log "Failed to extract ssh_key_name for #{server.mu_name} in addHostToSSHConfig", MU::ERR
|
|
606
606
|
return
|
|
607
607
|
end
|
|
608
608
|
|
|
@@ -880,5 +880,26 @@ module MU
|
|
|
880
880
|
end
|
|
881
881
|
end
|
|
882
882
|
|
|
883
|
+
# Recursively zip a directory
|
|
884
|
+
# @param srcdir [String]
|
|
885
|
+
# @param outfile [String]
|
|
886
|
+
def self.zipDir(srcdir, outfile)
|
|
887
|
+
require 'zip'
|
|
888
|
+
::Zip::File.open(outfile, ::Zip::File::CREATE) { |zipfile|
|
|
889
|
+
addpath = Proc.new { |zip_path, parent_path|
|
|
890
|
+
Dir.entries(parent_path).reject{ |d| [".", ".."].include?(d) }.each { |entry|
|
|
891
|
+
src = File.join(parent_path, entry)
|
|
892
|
+
dst = File.join(zip_path, entry).sub(/^\//, '')
|
|
893
|
+
if File.directory?(src)
|
|
894
|
+
addpath.call(dst, src)
|
|
895
|
+
else
|
|
896
|
+
zipfile.add(dst, src)
|
|
897
|
+
end
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
addpath.call("", srcdir)
|
|
901
|
+
}
|
|
902
|
+
end
|
|
903
|
+
|
|
883
904
|
end
|
|
884
905
|
end
|
data/modules/mu/mommacat.rb
CHANGED
|
@@ -167,6 +167,7 @@ module MU
|
|
|
167
167
|
@need_deploy_flush = false
|
|
168
168
|
@node_cert_semaphore = Mutex.new
|
|
169
169
|
@deployment = deployment_data
|
|
170
|
+
|
|
170
171
|
@deployment['mu_public_ip'] = MU.mu_public_ip
|
|
171
172
|
@private_key = nil
|
|
172
173
|
@public_key = nil
|
|
@@ -182,6 +183,7 @@ module MU
|
|
|
182
183
|
@appname ||= @original_config['name'] if @original_config
|
|
183
184
|
@timestamp = timestamp
|
|
184
185
|
@environment = environment
|
|
186
|
+
@original_config['environment'] ||= @environment if @original_config
|
|
185
187
|
|
|
186
188
|
if set_context_to_me
|
|
187
189
|
MU::MommaCat.setThreadContext(self)
|
|
@@ -253,8 +255,7 @@ module MU
|
|
|
253
255
|
seen << resource['credentials']
|
|
254
256
|
else
|
|
255
257
|
cloudconst = @original_config['cloud'] ? @original_config['cloud'] : MU::Config.defaultCloud
|
|
256
|
-
|
|
257
|
-
seen << cloudclass.credConfig(name_only: true)
|
|
258
|
+
seen << MU::Cloud.cloudClass(cloudconst).credConfig(name_only: true)
|
|
258
259
|
end
|
|
259
260
|
}
|
|
260
261
|
end
|
|
@@ -289,11 +290,10 @@ module MU
|
|
|
289
290
|
habitats << hab_ref.id
|
|
290
291
|
end
|
|
291
292
|
elsif resource['cloud']
|
|
292
|
-
cloudclass = Object.const_get("MU").const_get("Cloud").const_get(resource['cloud'])
|
|
293
293
|
# XXX this should be a general method implemented by each cloud
|
|
294
294
|
# provider
|
|
295
295
|
if resource['cloud'] == "Google"
|
|
296
|
-
habitats <<
|
|
296
|
+
habitats << MU::Cloud.cloudClass(resource['cloud']).defaultProject(resource['credentials'])
|
|
297
297
|
end
|
|
298
298
|
end
|
|
299
299
|
}
|
|
@@ -317,13 +317,11 @@ module MU
|
|
|
317
317
|
if @original_config[type]
|
|
318
318
|
@original_config[type].each { |resource|
|
|
319
319
|
if resource['cloud']
|
|
320
|
-
|
|
321
|
-
resclass = Object.const_get("MU").const_get("Cloud").const_get(resource['cloud']).const_get(res_type.to_s)
|
|
322
|
-
if resclass.isGlobal?
|
|
320
|
+
if MU::Cloud.resourceClass(resource['cloud'], res_type).isGlobal?
|
|
323
321
|
# XXX why was I doing this, urgh
|
|
324
322
|
next
|
|
325
323
|
elsif !resource['region']
|
|
326
|
-
regions <<
|
|
324
|
+
regions << MU::Cloud.cloudClass(resource['cloud']).myRegion(resource['credentials'])
|
|
327
325
|
end
|
|
328
326
|
end
|
|
329
327
|
if resource['region']
|
|
@@ -401,7 +399,7 @@ module MU
|
|
|
401
399
|
# @param type [String]:
|
|
402
400
|
# @param name [String]:
|
|
403
401
|
# @param object [MU::Cloud]:
|
|
404
|
-
def addKitten(type, name, object)
|
|
402
|
+
def addKitten(type, name, object, do_notify: false)
|
|
405
403
|
if !type or !name or !object or !object.mu_name
|
|
406
404
|
raise MuError, "Nil arguments to addKitten are not allowed (got type: #{type}, name: #{name}, and '#{object}' to add)"
|
|
407
405
|
end
|
|
@@ -409,7 +407,7 @@ module MU
|
|
|
409
407
|
_shortclass, _cfg_name, type, _classname, attrs = MU::Cloud.getResourceNames(type)
|
|
410
408
|
object.intoDeploy(self)
|
|
411
409
|
|
|
412
|
-
|
|
410
|
+
add_block = Proc.new {
|
|
413
411
|
@kittens[type] ||= {}
|
|
414
412
|
@kittens[type][object.habitat] ||= {}
|
|
415
413
|
if attrs[:has_multiples]
|
|
@@ -418,7 +416,20 @@ module MU
|
|
|
418
416
|
else
|
|
419
417
|
@kittens[type][object.habitat][name] = object
|
|
420
418
|
end
|
|
419
|
+
if do_notify
|
|
420
|
+
notify(type, name, object.notify, triggering_node: object, delayed_save: true)
|
|
421
|
+
end
|
|
421
422
|
}
|
|
423
|
+
|
|
424
|
+
begin
|
|
425
|
+
@kitten_semaphore.synchronize {
|
|
426
|
+
add_block.call()
|
|
427
|
+
}
|
|
428
|
+
rescue ThreadError => e
|
|
429
|
+
# already locked by a parent call to this method, so this should be safe
|
|
430
|
+
raise e if !e.message.match(/recursive locking/)
|
|
431
|
+
add_block.call()
|
|
432
|
+
end
|
|
422
433
|
end
|
|
423
434
|
|
|
424
435
|
# Encrypt a string with the deployment's public key.
|
|
@@ -536,16 +547,26 @@ module MU
|
|
|
536
547
|
# @param remove [Boolean]: Remove this resource from the deploy structure, instead of adding it.
|
|
537
548
|
# @return [void]
|
|
538
549
|
def notify(type, key, data, mu_name: nil, remove: false, triggering_node: nil, delayed_save: false)
|
|
539
|
-
|
|
550
|
+
no_write = (@no_artifacts or !caller.grep(/\/mommacat\.rb:\d+:in `notify'/).empty?)
|
|
540
551
|
|
|
541
552
|
begin
|
|
542
|
-
|
|
553
|
+
if !no_write
|
|
554
|
+
if !MU::MommaCat.lock("deployment-notification", deploy_id: @deploy_id, retries: 10)
|
|
555
|
+
raise MuError, "Failed to get deployment-notifcation lock for #{@deploy_id}"
|
|
556
|
+
end
|
|
557
|
+
end
|
|
543
558
|
|
|
544
559
|
if !@need_deploy_flush or @deployment.nil? or @deployment.empty?
|
|
545
560
|
loadDeploy(true) # make sure we're saving the latest and greatest
|
|
546
561
|
end
|
|
547
562
|
|
|
548
|
-
|
|
563
|
+
@timestamp ||= @deployment['timestamp']
|
|
564
|
+
@seed ||= @deployment['seed']
|
|
565
|
+
@appname ||= @deployment['appname']
|
|
566
|
+
@handle ||= @deployment['handle']
|
|
567
|
+
|
|
568
|
+
_shortclass, _cfg_name, mu_type, _classname, attrs = MU::Cloud.getResourceNames(type, false)
|
|
569
|
+
type = mu_type if mu_type
|
|
549
570
|
has_multiples = attrs[:has_multiples] ? true : false
|
|
550
571
|
|
|
551
572
|
mu_name ||= if !data.nil? and !data["mu_name"].nil?
|
|
@@ -559,6 +580,7 @@ module MU
|
|
|
559
580
|
end
|
|
560
581
|
|
|
561
582
|
@need_deploy_flush = true
|
|
583
|
+
@last_modified = Time.now
|
|
562
584
|
|
|
563
585
|
if !remove
|
|
564
586
|
if data.nil?
|
|
@@ -578,7 +600,9 @@ module MU
|
|
|
578
600
|
@deployment[type][key] = data
|
|
579
601
|
MU.log "Adding to @deployment[#{type}][#{key}]", MU::DEBUG, details: data
|
|
580
602
|
end
|
|
581
|
-
|
|
603
|
+
if !delayed_save and !no_write
|
|
604
|
+
save!(key)
|
|
605
|
+
end
|
|
582
606
|
else
|
|
583
607
|
have_deploy = true
|
|
584
608
|
if @deployment[type].nil? or @deployment[type][key].nil?
|
|
@@ -603,10 +627,10 @@ module MU
|
|
|
603
627
|
end
|
|
604
628
|
}
|
|
605
629
|
end
|
|
606
|
-
save! if !delayed_save
|
|
630
|
+
save! if !delayed_save and !no_write
|
|
607
631
|
end
|
|
608
632
|
ensure
|
|
609
|
-
MU::MommaCat.unlock("deployment-notification")
|
|
633
|
+
MU::MommaCat.unlock("deployment-notification", deploy_id: @deploy_id) if !no_write
|
|
610
634
|
end
|
|
611
635
|
end
|
|
612
636
|
|
|
@@ -614,18 +638,37 @@ module MU
|
|
|
614
638
|
# @param subject [String]: The subject line of the message.
|
|
615
639
|
# @param msg [String]: The message body.
|
|
616
640
|
# @return [void]
|
|
617
|
-
def sendAdminSlack(subject, msg: "")
|
|
618
|
-
if
|
|
619
|
-
(
|
|
641
|
+
def sendAdminSlack(subject, msg: "", scrub_mu_isms: true, snippets: [], noop: false)
|
|
642
|
+
if MU.muCfg['slack'] and MU.muCfg['slack']['webhook'] and
|
|
643
|
+
(!MU.muCfg['slack']['skip_environments'] or !MU.muCfg['slack']['skip_environments'].any?{ |s| s.casecmp(MU.environment)==0 })
|
|
620
644
|
require 'slack-notifier'
|
|
621
|
-
|
|
645
|
+
slackargs = nil
|
|
646
|
+
keyword_args = { channel: MU.muCfg['slack']['channel'] }
|
|
647
|
+
begin
|
|
648
|
+
slack = Slack::Notifier.new MU.muCfg['slack']['webhook']
|
|
649
|
+
prefix = scrub_mu_isms ? subject : "#{MU.appname} \*\"#{MU.handle}\"\* (`#{MU.deploy_id}`) - #{subject}"
|
|
650
|
+
|
|
651
|
+
text = if msg and !msg.empty?
|
|
652
|
+
"#{prefix}:\n\n```#{msg}```"
|
|
653
|
+
else
|
|
654
|
+
prefix
|
|
655
|
+
end
|
|
622
656
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
657
|
+
if snippets and snippets.size > 0
|
|
658
|
+
keyword_args[:attachments] = snippets
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
if !noop
|
|
662
|
+
slack.ping(text, **keyword_args)
|
|
663
|
+
else
|
|
664
|
+
MU.log "Would send to #{MU.muCfg['slack']['channel']}", MU::NOTICE, details: [ text, keyword_args ]
|
|
665
|
+
end
|
|
666
|
+
rescue Slack::Notifier::APIError => e
|
|
667
|
+
MU.log "Failed to send message to slack: #{e.message}", MU::ERR, details: keyword_args
|
|
668
|
+
return false
|
|
627
669
|
end
|
|
628
670
|
end
|
|
671
|
+
true
|
|
629
672
|
end
|
|
630
673
|
|
|
631
674
|
# Send an email notification to a deployment's administrators.
|
|
@@ -754,7 +797,7 @@ MAIL_HEAD_END
|
|
|
754
797
|
end
|
|
755
798
|
|
|
756
799
|
siblings = findLitterMate(type: "server", return_all: true)
|
|
757
|
-
return if siblings.nil? or siblings.empty?
|
|
800
|
+
return if siblings.nil? or (siblings.respond_to?(:empty?) and siblings.empty?)
|
|
758
801
|
|
|
759
802
|
update_servers = []
|
|
760
803
|
siblings.each_pair { |mu_name, node|
|
|
@@ -782,6 +825,7 @@ MAIL_HEAD_END
|
|
|
782
825
|
|
|
783
826
|
threads = []
|
|
784
827
|
update_servers.each { |sibling|
|
|
828
|
+
next if sibling.config.has_key?("groom") and !sibling.config["groom"]
|
|
785
829
|
threads << Thread.new {
|
|
786
830
|
Thread.abort_on_exception = true
|
|
787
831
|
Thread.current.thread_variable_set("name", "sync-"+sibling.mu_name.downcase)
|
|
@@ -838,7 +882,7 @@ MAIL_HEAD_END
|
|
|
838
882
|
end
|
|
839
883
|
|
|
840
884
|
if resource and resource.config and resource.config['cloud']
|
|
841
|
-
cloudclass =
|
|
885
|
+
cloudclass = MU::Cloud.cloudClass(resource.config['cloud'])
|
|
842
886
|
|
|
843
887
|
cloudclass.writeDeploySecret(@deploy_id, cert.to_pem, cert_cn+".crt", credentials: resource.config['credentials'])
|
|
844
888
|
cloudclass.writeDeploySecret(@deploy_id, key.to_pem, cert_cn+".key", credentials: resource.config['credentials'])
|
|
@@ -866,6 +910,7 @@ MAIL_HEAD_END
|
|
|
866
910
|
###########################################################################
|
|
867
911
|
###########################################################################
|
|
868
912
|
def setThreadContextToMe
|
|
913
|
+
|
|
869
914
|
["appname", "environment", "timestamp", "seed", "handle"].each { |var|
|
|
870
915
|
@deployment[var] ||= instance_variable_get("@#{var}".to_sym)
|
|
871
916
|
if @deployment[var]
|