d13n 0.5.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 +7 -0
- data/.gitignore +35 -0
- data/.rspec +6 -0
- data/.rubocop.yml +5 -0
- data/.ruby-version +1 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +151 -0
- data/Guardfile +63 -0
- data/README.md +200 -0
- data/bin/d13n +11 -0
- data/d13n.gemspec +34 -0
- data/lib/d13n/application/class_methods.rb +56 -0
- data/lib/d13n/application.rb +3 -0
- data/lib/d13n/cli/command.rb +76 -0
- data/lib/d13n/cli/commands/scaffold.rb +345 -0
- data/lib/d13n/configuration/default_source.rb +200 -0
- data/lib/d13n/configuration/dotted_hash.rb +39 -0
- data/lib/d13n/configuration/environment_source.rb +89 -0
- data/lib/d13n/configuration/manager.rb +239 -0
- data/lib/d13n/configuration/manual_source.rb +4 -0
- data/lib/d13n/configuration/mask_defaults.rb +6 -0
- data/lib/d13n/configuration/server_source.rb +83 -0
- data/lib/d13n/configuration/yaml_source.rb +66 -0
- data/lib/d13n/configuration.rb +6 -0
- data/lib/d13n/ext/string.rb +17 -0
- data/lib/d13n/logger/log_once.rb +24 -0
- data/lib/d13n/logger/memory_logger.rb +48 -0
- data/lib/d13n/logger/null_logger.rb +16 -0
- data/lib/d13n/logger.rb +213 -0
- data/lib/d13n/metric/conductor.rb +123 -0
- data/lib/d13n/metric/helper.rb +62 -0
- data/lib/d13n/metric/http_clients/http_helper.rb +15 -0
- data/lib/d13n/metric/http_clients/net_http_wrappers.rb +54 -0
- data/lib/d13n/metric/http_clients.rb +4 -0
- data/lib/d13n/metric/instrumentation/app_exception.rb +70 -0
- data/lib/d13n/metric/instrumentation/controller_instrumentation.rb +91 -0
- data/lib/d13n/metric/instrumentation/em-websocket.rb +71 -0
- data/lib/d13n/metric/instrumentation/exception.rb +65 -0
- data/lib/d13n/metric/instrumentation/middleware_tracing.rb +82 -0
- data/lib/d13n/metric/instrumentation/net.rb +36 -0
- data/lib/d13n/metric/instrumentation/sinatra/stream_namer.rb +35 -0
- data/lib/d13n/metric/instrumentation/sinatra.rb +165 -0
- data/lib/d13n/metric/instrumentation/websocket_instrumentation.rb +42 -0
- data/lib/d13n/metric/instrumentation.rb +41 -0
- data/lib/d13n/metric/manager.rb +106 -0
- data/lib/d13n/metric/metrics/app_database_metric.rb +4 -0
- data/lib/d13n/metric/metrics/app_http_metric.rb +229 -0
- data/lib/d13n/metric/metrics/app_state_metric.rb +103 -0
- data/lib/d13n/metric/metrics/base.rb +14 -0
- data/lib/d13n/metric/metrics/biz_state_metric.rb +4 -0
- data/lib/d13n/metric/metrics.rb +6 -0
- data/lib/d13n/metric/stream/span_tracer_helpers.rb +72 -0
- data/lib/d13n/metric/stream/stream_tracer_helpers.rb +141 -0
- data/lib/d13n/metric/stream/traced_span_stack.rb +73 -0
- data/lib/d13n/metric/stream.rb +322 -0
- data/lib/d13n/metric/stream_state.rb +68 -0
- data/lib/d13n/metric.rb +11 -0
- data/lib/d13n/rack/d13n_middleware.rb +21 -0
- data/lib/d13n/rack/metric_middleware.rb +18 -0
- data/lib/d13n/service/background_job/sinatra.rb +24 -0
- data/lib/d13n/service/background_job.rb +1 -0
- data/lib/d13n/service/start.rb +75 -0
- data/lib/d13n/service.rb +91 -0
- data/lib/d13n/support/request_id.rb +29 -0
- data/lib/d13n/version.rb +14 -0
- data/lib/d13n.rb +92 -0
- data/templates/.rspec.template +6 -0
- data/templates/.ruby-version.template +1 -0
- data/templates/Gemfile.template +16 -0
- data/templates/Guardfile.template +64 -0
- data/templates/Jenkinsfile.template +85 -0
- data/templates/Makefile.template +178 -0
- data/templates/README.md.template +1 -0
- data/templates/Rakefile.template +6 -0
- data/templates/application.yml.template +14 -0
- data/templates/config.ru.template +4 -0
- data/templates/docker/.dockerignore.template +5 -0
- data/templates/docker/Dockerfile.application.development +15 -0
- data/templates/docker/Dockerfile.cache.development +18 -0
- data/templates/docker/Dockerfile.development +27 -0
- data/templates/docker/Dockerfile.release +16 -0
- data/templates/docker/docker-compose.yml.development +53 -0
- data/templates/docker/docker-compose.yml.release +37 -0
- data/templates/lib/api/service.rb.template +10 -0
- data/templates/lib/api/support.rb.template +38 -0
- data/templates/lib/api/version.rb.template +3 -0
- data/templates/lib/api.rb.template +4 -0
- data/templates/lib/application.rb.template +49 -0
- data/templates/lib/service.rb.template +4 -0
- data/templates/lib/version.rb.template +3 -0
- data/templates/scripts/test.sh.template +7 -0
- data/templates/spec/spec_helper.rb.template +56 -0
- data/templates/tasks/migration.rake.template +11 -0
- data/templates/tasks/spec.rake.template +21 -0
- metadata +199 -0
@@ -0,0 +1,345 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
require 'd13n/version'
|
4
|
+
module D13n::Cli
|
5
|
+
class Scaffold < Command
|
6
|
+
def self.command; "scaffold"; end
|
7
|
+
|
8
|
+
attr_accessor :application, :project, :ruby_version, :application_base
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@bare = false
|
12
|
+
@application = nil
|
13
|
+
@ruby_version = '2.3.3'
|
14
|
+
super(args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
check_options
|
19
|
+
generate_scaffold
|
20
|
+
end
|
21
|
+
|
22
|
+
def check_options
|
23
|
+
if @application.nil?
|
24
|
+
puts 'application name required'
|
25
|
+
exit 1
|
26
|
+
elsif @project.nil?
|
27
|
+
puts 'project name required'
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_scaffold
|
33
|
+
@template_home = File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', '..', 'templates')
|
34
|
+
|
35
|
+
unless @bare
|
36
|
+
puts "Setting up application [#{application_base}] directories..."
|
37
|
+
Dir.mkdir(@application) unless File.directory?(@application)
|
38
|
+
Dir.chdir(@application)
|
39
|
+
end
|
40
|
+
|
41
|
+
@current_home = Dir.pwd
|
42
|
+
|
43
|
+
unless @bare
|
44
|
+
application_scaffold
|
45
|
+
end
|
46
|
+
|
47
|
+
rake_scaffold
|
48
|
+
|
49
|
+
migration_scaffold
|
50
|
+
|
51
|
+
gem_scaffold
|
52
|
+
|
53
|
+
makefile_scaffold
|
54
|
+
|
55
|
+
application_yml_scaffold
|
56
|
+
|
57
|
+
docker_scaffold
|
58
|
+
|
59
|
+
docker_script_scaffold
|
60
|
+
|
61
|
+
jekinsfile_scaffold
|
62
|
+
|
63
|
+
ruby_version_scaffold
|
64
|
+
|
65
|
+
spec_scaffold
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def application_base
|
72
|
+
@application_base = @application.split('_').map {|w| w.capitalize}.join
|
73
|
+
end
|
74
|
+
|
75
|
+
def application_const
|
76
|
+
@application_const ||= "#{application_base}::Service"
|
77
|
+
end
|
78
|
+
|
79
|
+
def template_erb(src, dst, src_sub_path=nil, dst_sub_path=nil)
|
80
|
+
src_file = if src_sub_path.nil?
|
81
|
+
File.join(@template_home,src)
|
82
|
+
else
|
83
|
+
File.join(@template_home, src_sub_path, src)
|
84
|
+
end
|
85
|
+
dst_file = if dst_sub_path.nil?
|
86
|
+
File.join(@current_home,dst)
|
87
|
+
else
|
88
|
+
File.join(@current_home, dst_sub_path, dst)
|
89
|
+
end
|
90
|
+
File.open(src_file) do |tfh|
|
91
|
+
erb = ERB.new(tfh.read)
|
92
|
+
File.open(dst_file, 'w') do |ofh|
|
93
|
+
ofh.print erb.result(binding)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def application_scaffold
|
99
|
+
puts "Generating application[#{application_base}] lib folder ..."
|
100
|
+
Dir.mkdir('lib')
|
101
|
+
application_source_path = File.join("lib","#{application}")
|
102
|
+
Dir.mkdir(application_source_path)
|
103
|
+
|
104
|
+
puts "Generating #{application_base} namespace file ..."
|
105
|
+
template_erb('application.rb.template', "#{application}.rb", 'lib', 'lib')
|
106
|
+
|
107
|
+
puts "Generating #{application_base} service file ..."
|
108
|
+
template_erb('service.rb.template','service.rb','lib',application_source_path)
|
109
|
+
template_erb('version.rb.template','version.rb','lib',application_source_path)
|
110
|
+
|
111
|
+
application_api
|
112
|
+
|
113
|
+
application_rack
|
114
|
+
|
115
|
+
application_readme
|
116
|
+
|
117
|
+
application_guard
|
118
|
+
end
|
119
|
+
|
120
|
+
def application_api
|
121
|
+
puts "Generating application[#{application_base}] api folder ..."
|
122
|
+
api_root = File.join('lib',application,'api')
|
123
|
+
Dir.mkdir(api_root)
|
124
|
+
|
125
|
+
application_source_path = File.join("lib","#{application}")
|
126
|
+
template_erb('api.rb.template','api.rb','lib', application_source_path)
|
127
|
+
|
128
|
+
api_template_root = File.join('lib', 'api')
|
129
|
+
puts api_template_root
|
130
|
+
puts "Generating #{application_base} api files ..."
|
131
|
+
template_erb('service.rb.template','service.rb',api_template_root, api_root)
|
132
|
+
template_erb('support.rb.template','support.rb',api_template_root, api_root)
|
133
|
+
template_erb('version.rb.template','version.rb',api_template_root, api_root)
|
134
|
+
end
|
135
|
+
|
136
|
+
def application_rack
|
137
|
+
puts "Generating application[#{application_base}] rack file ..."
|
138
|
+
template_erb('config.ru.template','config.ru')
|
139
|
+
end
|
140
|
+
|
141
|
+
def application_readme
|
142
|
+
puts "Generating application[#{application_base}] README.md file ..."
|
143
|
+
template_erb('README.md.template','README.md')
|
144
|
+
end
|
145
|
+
|
146
|
+
def application_guard
|
147
|
+
puts "Generating application[#{application_base}] README.md file ..."
|
148
|
+
template_erb('Guardfile.template','Guardfile')
|
149
|
+
end
|
150
|
+
|
151
|
+
def migration_scaffold
|
152
|
+
puts "Generating database migration folders ..."
|
153
|
+
@migration_root = 'db'
|
154
|
+
Dir.mkdir(@migration_root) unless File.directory?(@migration_root)
|
155
|
+
|
156
|
+
@migration_sub_dir = ['migrations', 'seeds']
|
157
|
+
@migration_sub_dir.each do |dir|
|
158
|
+
root_dir = "#{@migration_root}/#{dir}"
|
159
|
+
Dir.mkdir(root_dir) unless File.directory?(root_dir)
|
160
|
+
end
|
161
|
+
|
162
|
+
puts "Generating Rake migration file ..."
|
163
|
+
|
164
|
+
File.open(File.join(@template_home, @rake_task_root, 'migration.rake.template')) do |tfh|
|
165
|
+
erb = ERB.new(tfh.read)
|
166
|
+
File.open(File.join(@current_home, @rake_task_root, "migration.rake"), 'w') do |ofh|
|
167
|
+
ofh.print erb.result(binding)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def gem_scaffold
|
173
|
+
puts "Generating Gemfile ..."
|
174
|
+
|
175
|
+
File.open(File.join(@template_home, 'Gemfile.template')) do |tfh|
|
176
|
+
erb = ERB.new(tfh.read)
|
177
|
+
File.open(File.join(@current_home, "Gemfile"), 'w') do |ofh|
|
178
|
+
ofh.print erb.result(binding)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def makefile_scaffold
|
184
|
+
puts "Generating Makefile ..."
|
185
|
+
File.open(File.join(@template_home, 'Makefile.template')) do |tfh|
|
186
|
+
erb = ERB.new(tfh.read)
|
187
|
+
File.open(File.join(@current_home, "Makefile"), 'w') do |ofh|
|
188
|
+
ofh.print erb.result(binding)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def application_yml_scaffold
|
194
|
+
puts "Generating #{application}.yml ..."
|
195
|
+
File.open(File.join(@template_home, 'application.yml.template')) do |tfh|
|
196
|
+
erb = ERB.new(tfh.read)
|
197
|
+
File.open(File.join(@current_home, "#{application}.yml"), 'w') do |ofh|
|
198
|
+
ofh.print erb.result(binding)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def docker_scaffold
|
204
|
+
puts "Generating docker folder ..."
|
205
|
+
@docker_root = 'docker'
|
206
|
+
Dir.mkdir(@docker_root) unless File.directory?(@docker_root)
|
207
|
+
|
208
|
+
@docker_development_files = ['docker-compose.yml','Dockerfile.cache','Dockerfile']
|
209
|
+
@docker_release_files = ['docker-compose.yml', 'Dockerfile']
|
210
|
+
|
211
|
+
docker_stage(@docker_root, 'development', @docker_development_files)
|
212
|
+
docker_stage(@docker_root, 'release', @docker_release_files)
|
213
|
+
end
|
214
|
+
|
215
|
+
def docker_stage(root, stage, files)
|
216
|
+
puts "Generating docker #{stage} folder ..."
|
217
|
+
root_dir = "#{root}/#{stage}"
|
218
|
+
Dir.mkdir(root_dir) unless File.directory?(root_dir)
|
219
|
+
|
220
|
+
puts "Generating #{stage} docker files ..."
|
221
|
+
stage_dir = "#{root}/#{stage}"
|
222
|
+
files.each do |file|
|
223
|
+
File.open(File.join(@template_home, "docker", "#{file}.#{stage}")) do |tfh|
|
224
|
+
erb = ERB.new(tfh.read)
|
225
|
+
File.open(File.join(@current_home, stage_dir, file), 'w') do |ofh|
|
226
|
+
ofh.print erb.result(binding)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def docker_script_scaffold
|
233
|
+
@docker_script_root = 'scripts'
|
234
|
+
Dir.mkdir(@docker_script_root) unless File.directory?(@docker_script_root)
|
235
|
+
|
236
|
+
puts "Generating docker scripts ..."
|
237
|
+
File.open(File.join(@template_home, "#{@docker_script_root}/", "test.sh.template")) do |tfh|
|
238
|
+
erb = ERB.new(tfh.read)
|
239
|
+
File.open(File.join(@current_home, "#{@docker_script_root}/", "test.sh"), 'w') do |ofh|
|
240
|
+
ofh.print erb.result(binding)
|
241
|
+
end
|
242
|
+
|
243
|
+
FileUtils.chmod 0755,File.join(@current_home, "#{@docker_script_root}/", "test.sh")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def jekinsfile_scaffold
|
248
|
+
puts "Generating Jekinsfile ..."
|
249
|
+
|
250
|
+
File.open(File.join(@template_home, "Jenkinsfile.template")) do |tfh|
|
251
|
+
erb = ERB.new(tfh.read)
|
252
|
+
File.open(File.join(@current_home, "Jenkinsfile"), 'w') do |ofh|
|
253
|
+
ofh.print erb.result(binding)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def ruby_version_scaffold
|
259
|
+
puts "Generating Ruby Version file ..."
|
260
|
+
|
261
|
+
File.open(File.join(@template_home, ".ruby-version.template")) do |tfh|
|
262
|
+
erb = ERB.new(tfh.read)
|
263
|
+
File.open(File.join(@current_home, ".ruby-version"), 'w') do |ofh|
|
264
|
+
ofh.print erb.result(binding)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def spec_scaffold
|
270
|
+
puts "Generating RSpec configuraion file ..."
|
271
|
+
|
272
|
+
File.open(File.join(@template_home, ".rspec.template")) do |tfh|
|
273
|
+
erb = ERB.new(tfh.read)
|
274
|
+
File.open(File.join(@current_home, ".rspec"), 'w') do |ofh|
|
275
|
+
ofh.print erb.result(binding)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
puts "Generating Spec folders ..."
|
280
|
+
|
281
|
+
@spec_root = 'spec'
|
282
|
+
|
283
|
+
Dir.mkdir(@spec_root) unless File.directory?(@spec_root)
|
284
|
+
|
285
|
+
['unit', 'functional', 'factories'].each do |folder|
|
286
|
+
spec_sub_dir = File.join(@spec_root, folder)
|
287
|
+
Dir.mkdir(spec_sub_dir) unless File.directory?(spec_sub_dir)
|
288
|
+
end
|
289
|
+
|
290
|
+
puts "Generating Rspec Helper file ..."
|
291
|
+
|
292
|
+
File.open(File.join(@template_home, "spec", "spec_helper.rb.template")) do |tfh|
|
293
|
+
erb = ERB.new(tfh.read)
|
294
|
+
File.open(File.join(@current_home, "spec", "spec_helper.rb"), 'w') do |ofh|
|
295
|
+
ofh.print erb.result(binding)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
puts 'Generating Rspec rake task file ...'
|
300
|
+
|
301
|
+
File.open(File.join(@template_home, @rake_task_root, "spec.rake.template")) do |tfh|
|
302
|
+
erb = ERB.new(tfh.read)
|
303
|
+
File.open(File.join(@current_home, @rake_task_root, "spec.rake"), 'w') do |ofh|
|
304
|
+
ofh.print erb.result(binding)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def rake_scaffold
|
310
|
+
puts "Generating Rake file ..."
|
311
|
+
|
312
|
+
File.open(File.join(@template_home, "Rakefile.template")) do |tfh|
|
313
|
+
erb = ERB.new(tfh.read)
|
314
|
+
File.open(File.join(@current_home, "Rakefile"), 'w') do |ofh|
|
315
|
+
ofh.print erb.result(binding)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
puts "Generating Rake Task folder ..."
|
320
|
+
|
321
|
+
@rake_task_root = 'tasks'
|
322
|
+
|
323
|
+
Dir.mkdir(@rake_task_root) unless File.directory?(@rake_task_root)
|
324
|
+
end
|
325
|
+
|
326
|
+
def options
|
327
|
+
OptionParser.new %Q{Usage: #{$0} #{self.class.command} [OPTIONS] ["description"] }, 40 do |opts|
|
328
|
+
opts.separator ''
|
329
|
+
opts.separator 'Specific options:'
|
330
|
+
|
331
|
+
opts.on('-a APP', '--app','Specify an application to scaffold') do |app|
|
332
|
+
@application = app.downcase
|
333
|
+
end
|
334
|
+
|
335
|
+
opts.on('-p PROJECT', '--project','Specify project of application to scaffold') do |project|
|
336
|
+
@project = project.downcase
|
337
|
+
end
|
338
|
+
|
339
|
+
opts.on('-b', '--bare', 'Scaffold a bare folder') do |bare|
|
340
|
+
@bare = true
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module D13n::Configuration
|
4
|
+
def self.value_of(key)
|
5
|
+
Proc.new {
|
6
|
+
D13n.config[key]
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
class Boolean
|
11
|
+
def self.===(o)
|
12
|
+
TrueClass === o or FalseClass === o
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class DefaultSource
|
17
|
+
attr_reader :defaults, :alias
|
18
|
+
|
19
|
+
extend Forwardable
|
20
|
+
def_delegators :@defaults, :has_key?, :each, :merge, :delete, :keys, :[], :to_hash
|
21
|
+
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
frozen_default
|
25
|
+
@defaults = default_values
|
26
|
+
@alias = default_alias
|
27
|
+
end
|
28
|
+
|
29
|
+
def frozen_default
|
30
|
+
D13n::Configuration::DEFAULTS.freeze
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_values
|
34
|
+
result = {}
|
35
|
+
D13n::Configuration::DEFAULTS.each do |key, value|
|
36
|
+
result[key] = value[:default]
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_alias
|
42
|
+
result = {}
|
43
|
+
D13n::Configuration::DEFAULTS.each do |key,value|
|
44
|
+
result[key] = (value[:alias] || key).to_s
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.defaults
|
50
|
+
D13n::Configuration::DEFAULTS
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.defaults=(default_config)
|
54
|
+
D13n::Configuration::DEFAULTS.merge!(default_config)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.config_search_paths
|
58
|
+
Proc.new {
|
59
|
+
paths = [
|
60
|
+
File.join("config", "#{D13n.app_name}.yml"),
|
61
|
+
File.join("#{D13n.app_name}.yml")
|
62
|
+
]
|
63
|
+
|
64
|
+
if D13n.service.instance.root
|
65
|
+
paths << File.join(D13n.service.instance.root, "config", "#{D13n.app_name}.yml")
|
66
|
+
paths << File.join(D13n.service.instance.root, "#{D13n.app_name}.yml")
|
67
|
+
end
|
68
|
+
|
69
|
+
if ENV["HOME"]
|
70
|
+
paths << File.join(ENV["HOME"], ".#{D13n.app_name}", "#{D13n.app_name}.yml")
|
71
|
+
paths << File.join(ENV["HOME"], "#{D13n.app_name}.yml")
|
72
|
+
end
|
73
|
+
paths
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.config_path
|
78
|
+
Proc.new {
|
79
|
+
found_path = D13n.config[:config_search_paths].detect do |file|
|
80
|
+
File.expand_path(file) if File.exist? file
|
81
|
+
end
|
82
|
+
found_path || ""
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.transform_for(key)
|
87
|
+
default_settings = D13n::Configuration::DEFAULTS[key]
|
88
|
+
default_settings[:transform] if default_settings
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.convert_to_list(value)
|
92
|
+
case value
|
93
|
+
when String
|
94
|
+
value.split(/\s*,\s*/)
|
95
|
+
when Array
|
96
|
+
value
|
97
|
+
else
|
98
|
+
raise ArgumentError.new("Config value '#{value}' couldn't be turned into a list.")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
DEFAULTS = {
|
104
|
+
:app_name => {
|
105
|
+
:default => Proc.new{"#{D13n.app_name}"},
|
106
|
+
:public => true,
|
107
|
+
:type => String,
|
108
|
+
:allowed_from_server => false,
|
109
|
+
:description => 'Define Application Name'
|
110
|
+
},
|
111
|
+
:port => {
|
112
|
+
:default => 3000,
|
113
|
+
:public => true,
|
114
|
+
:type => Integer,
|
115
|
+
:description => 'Define service port'
|
116
|
+
},
|
117
|
+
:host => {
|
118
|
+
:default => '0.0.0.0',
|
119
|
+
:public => true,
|
120
|
+
:type => String,
|
121
|
+
:description => 'Define service host'
|
122
|
+
},
|
123
|
+
#
|
124
|
+
# Log config
|
125
|
+
#
|
126
|
+
:log_level => {
|
127
|
+
:default => 'info',
|
128
|
+
:public => true,
|
129
|
+
:type => String,
|
130
|
+
:description => 'Sets the level of detail of log messages. Possible log levels, in increasing verbosity, are: <code>error</code>, <code>warn</code>, <code>info</code> or <code>debug</code>.'
|
131
|
+
},
|
132
|
+
:log_file_path => {
|
133
|
+
:default => 'stdout',
|
134
|
+
:public => true,
|
135
|
+
:type => String,
|
136
|
+
:description => 'Defines a path to the log file, excluding the filename.'
|
137
|
+
},
|
138
|
+
:log_file_name => {
|
139
|
+
:default => Proc.new{"#{D13n.app_name}.log"},
|
140
|
+
:public => true,
|
141
|
+
:type => String,
|
142
|
+
:description => 'Defines a name for the log file.'
|
143
|
+
},
|
144
|
+
#
|
145
|
+
# YAML file Config
|
146
|
+
#
|
147
|
+
:config_path => {
|
148
|
+
:default => DefaultSource.config_path,
|
149
|
+
:public => true,
|
150
|
+
:type => String,
|
151
|
+
:description => 'Path to <b>application.yml</b>. If undefined, the agent checks the following directories (in order): <b>config/application.yml</b>, <b>application.yml</b>, <b>$HOME/.d13n/application.yml</b> and <b>$HOME/application.yml</b>.'
|
152
|
+
},
|
153
|
+
:config_search_paths => {
|
154
|
+
:default => DefaultSource.config_search_paths,
|
155
|
+
:public => false,
|
156
|
+
:type => Array,
|
157
|
+
:allowed_from_server => false,
|
158
|
+
:description => "An array of candidate locations for the service\'s configuration file."
|
159
|
+
},
|
160
|
+
:'metric.channel.type' => {
|
161
|
+
:default => 'logger',
|
162
|
+
:public => true,
|
163
|
+
:type => String,
|
164
|
+
:allowed_from_server => true,
|
165
|
+
:description => 'Metric Channel Type.'
|
166
|
+
},
|
167
|
+
:'metric.app.http.in.apdex_t' => {
|
168
|
+
:default => 300,
|
169
|
+
:public => true,
|
170
|
+
:type => Integer,
|
171
|
+
:allowed_from_server => true,
|
172
|
+
:description => 'Metric HTTP IN Apdex Config Value.'
|
173
|
+
},
|
174
|
+
:'metric.app.http.in.tracable' => {
|
175
|
+
:default => true,
|
176
|
+
:public => true,
|
177
|
+
:type => D13n::Configuration::Boolean,
|
178
|
+
:description => 'Metric HTTP IN trace enable switch'
|
179
|
+
},
|
180
|
+
:'metric.app.http.in.sinatra.enable' => {
|
181
|
+
:default => true,
|
182
|
+
:public => true,
|
183
|
+
:type => D13n::Configuration::Boolean,
|
184
|
+
:description => 'enable http in trace for sinatra'
|
185
|
+
},
|
186
|
+
:'metric.app.http.in.sinatra.auto_middleware.enable' => {
|
187
|
+
:default => true,
|
188
|
+
:public => true,
|
189
|
+
:type => D13n::Configuration::Boolean,
|
190
|
+
:description => 'enable sinatra auto load middleware'
|
191
|
+
},
|
192
|
+
:'metric.app.http.out.tracable' => {
|
193
|
+
:default => true,
|
194
|
+
:public => true,
|
195
|
+
:type => D13n::Configuration::Boolean,
|
196
|
+
:allowed_from_server => true,
|
197
|
+
:description => "Metric HTTP OUT trace enable switch"
|
198
|
+
}
|
199
|
+
}
|
200
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module D13n::Configuration
|
2
|
+
class DottedHash < ::Hash
|
3
|
+
def initialize(hash, keep_nesting=false)
|
4
|
+
self.merge!(hash) if keep_nesting
|
5
|
+
|
6
|
+
self.merge!(dot_flattened(hash))
|
7
|
+
DottedHash.symbolize(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def inspect
|
11
|
+
"#<#{self.class.name}:#{object_id} #{super}>"
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
{}.replace(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.symbolize(hash)
|
19
|
+
hash.keys.each do |key|
|
20
|
+
hash[key.to_sym] = hash.delete(key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
# turns {'a' => {'b' => 'c'}} into {'a.b' => 'c'}
|
26
|
+
def dot_flattened(nested_hash, names=[], result={})
|
27
|
+
nested_hash.each do |key, val|
|
28
|
+
next if val == nil
|
29
|
+
if val.respond_to?(:has_key?)
|
30
|
+
dot_flattened(val, names + [key], result)
|
31
|
+
else
|
32
|
+
result[(names + [key]).join('.')] = val
|
33
|
+
end
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module D13n::Configuration
|
2
|
+
class EnvironmentSource < DottedHash
|
3
|
+
SUPPORTED_PREFIXES = Proc.new {/^#{D13n.app_name}_/i}
|
4
|
+
SPECIAL_CASE_KEYS = [
|
5
|
+
"#{D13n.app_prefix}_LOG" # read by set_log_file
|
6
|
+
]
|
7
|
+
|
8
|
+
attr_accessor :type_map
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
set_log_file
|
12
|
+
set_config_file
|
13
|
+
|
14
|
+
@type_map = {}
|
15
|
+
|
16
|
+
DEFAULTS.each do |config_setting, value|
|
17
|
+
self.type_map[config_setting] = value[:type]
|
18
|
+
end
|
19
|
+
|
20
|
+
set_values_from_app_environment_variables
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_log_file
|
24
|
+
env_log = "#{D13n.app_prefix}_LOG"
|
25
|
+
if ENV[env_log]
|
26
|
+
if ENV[env_log].upcase == 'STDOUT'
|
27
|
+
self[:log_file_path] = self[:log_file_name] = 'STDOUT'
|
28
|
+
else
|
29
|
+
self[:log_file_path] = File.dirname(ENV[env_log])
|
30
|
+
self[:log_file_name] = File.basename(ENV[env_log])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_config_file
|
36
|
+
env_config = "#{D13n.app_prefix}_CONFIG"
|
37
|
+
self[:config_path] = ENV[env_config] if ENV[env_config]
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_values_from_app_environment_variables
|
41
|
+
app_env_var_keys = collect_app_environment_variable_keys
|
42
|
+
|
43
|
+
app_env_var_keys.each do |key|
|
44
|
+
next if SPECIAL_CASE_KEYS.include?(key.upcase)
|
45
|
+
set_value_from_app_environment_variable(key)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_value_from_app_environment_variable(key)
|
50
|
+
config_key = convert_environment_key_to_config_key(key)
|
51
|
+
set_key_by_type(config_key, key)
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_key_by_type(config_key, environment_key)
|
55
|
+
value = ENV[environment_key]
|
56
|
+
type = self.type_map[config_key]
|
57
|
+
|
58
|
+
if type == String
|
59
|
+
self[config_key] = value
|
60
|
+
elsif type == Integer
|
61
|
+
self[config_key] = value.to_i
|
62
|
+
elsif type == Float
|
63
|
+
self[config_key] = value.to_f
|
64
|
+
elsif type == Symbol
|
65
|
+
self[config_key] = value.to_sym
|
66
|
+
elsif type == Array
|
67
|
+
self[config_key] = value.split(/\s*,\s*/)
|
68
|
+
elsif type == D13n::Configuration::Boolean
|
69
|
+
if value =~ /false|off|no/i
|
70
|
+
self[config_key] = false
|
71
|
+
elsif value != nil
|
72
|
+
self[config_key] = true
|
73
|
+
end
|
74
|
+
else
|
75
|
+
D13n.logger.info("#{environment_key} does not have a corresponding configuration setting (#{config_key} does not exist).")
|
76
|
+
self[config_key] = value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def convert_environment_key_to_config_key(key)
|
81
|
+
stripped_key = key.gsub(SUPPORTED_PREFIXES.call, '').downcase.to_sym
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def collect_app_environment_variable_keys
|
86
|
+
ENV.keys.select { |key| key.match(SUPPORTED_PREFIXES.call) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|