kafo 0.6.12 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,14 +3,17 @@
3
3
  # note current configuration is written to kafo.yaml every time kafo is run
4
4
 
5
5
  ## Installer configuration
6
- # Your project name
7
- # :name: Kafo
6
+ # Human readable scenario name
7
+ # :name: default
8
+ # Description of the installer scenario and its purpose
9
+ # :description:
8
10
  # Path to answer file, if the file does not exist a $pwd/config/answers.yaml is used as a fallback
9
11
  # :answer_file: /etc/kafo/answers.yaml
10
12
  # Custom installer path
11
13
  # :installer_dir: /usr/share/kafo/
12
- # Uncomment if you want to load puppet modules from a specific path, $pwd/modules is used by default
13
- # :modules_dir: /usr/share/kafo/modules
14
+ # Uncomment if you want to load puppet modules from a specific path, $pwd/modules is used by default,
15
+ # multiple dirs are allowed
16
+ # :module_dirs: /usr/share/kafo/modules
14
17
  # Similar as modules_dir but for kafo internal modules, leave nil if you don't need to change it
15
18
  # :kafo_modules_dir:
16
19
  # Enable colors? If you don't touch this, we'll autodetect terminal capabilities
@@ -44,6 +47,11 @@
44
47
  # :hook_dirs:
45
48
  # - /opt/hooks
46
49
 
50
+ ## Checks - system checks in these extra directories will be loaded
51
+ # by default $installer_dir/checks is used
52
+ # :check_dirs:
53
+ # - /opt/checks
54
+
47
55
  # custom storage is handy if you use hooks and you must store some configuration
48
56
  # which should persist among installer runs. It can be also used for passing
49
57
  # value from one hook to another.
@@ -2,12 +2,18 @@ require 'highline/import'
2
2
 
3
3
  module Kafo
4
4
  class ColorScheme
5
- def initialize(config)
6
- @config = config
5
+
6
+ def self.colors_possible?
7
+ ::ENV['TERM'] && !`which tput 2> /dev/null`.empty? && `tput colors`.to_i > 0
8
+ end
9
+
10
+ def initialize(options={})
11
+ @background = options[:background].nil? ? :dark : options[:background]
12
+ @colors = options[:colors].nil? ? self.class.colors_possible? : options[:colors]
7
13
  end
8
14
 
9
15
  def setup
10
- if @config.app[:colors]
16
+ if @colors
11
17
  HighLine.color_scheme = build_color_scheme
12
18
  HighLine.use_color = true
13
19
  else
@@ -28,6 +34,7 @@ module Kafo
28
34
  def color_hash
29
35
  @color_hash ||= {
30
36
  :headline => build_color(:yellow),
37
+ :title => build_color(:yellow),
31
38
  :horizontal_line => build_color(:white),
32
39
  :important => build_color(:white),
33
40
  :question => build_color(:green),
@@ -41,7 +48,7 @@ module Kafo
41
48
  end
42
49
 
43
50
  def build_color(color)
44
- bright = @config.app[:color_of_background].to_s == 'bright'
51
+ bright = @background.to_s == 'bright'
45
52
  color = convert_bright_to_dark(color) if bright
46
53
 
47
54
  attributes = [ color ]
@@ -3,16 +3,15 @@ require 'yaml'
3
3
  require 'tmpdir'
4
4
  require 'kafo/puppet_module'
5
5
  require 'kafo/password_manager'
6
+ require 'kafo/color_scheme'
6
7
 
7
8
  module Kafo
8
9
  class Configuration
9
10
  attr_reader :config_file, :answer_file
10
11
 
11
- def self.colors_possible?
12
- !`which tput 2> /dev/null`.empty? && `tput colors`.to_i > 0
13
- end
14
-
15
12
  DEFAULT = {
13
+ :name => '',
14
+ :description => '',
16
15
  :log_dir => '/var/log/kafo',
17
16
  :log_name => 'configuration.log',
18
17
  :log_level => 'info',
@@ -20,13 +19,14 @@ module Kafo
20
19
  :mapping => {},
21
20
  :answer_file => './config/answers.yaml',
22
21
  :installer_dir => '.',
23
- :modules_dir => './modules',
22
+ :module_dirs => ['./modules'],
24
23
  :default_values_dir => '/tmp',
25
- :colors => Configuration.colors_possible?,
24
+ :colors => Kafo::ColorScheme.colors_possible?,
26
25
  :color_of_background => :dark,
27
26
  :hook_dirs => [],
28
27
  :custom => {},
29
28
  :low_priority_modules => [],
29
+ :verbose_log_level => 'info'
30
30
  }
31
31
 
32
32
  def initialize(file, persist = true)
@@ -37,7 +37,7 @@ module Kafo
37
37
 
38
38
  @answer_file = app[:answer_file]
39
39
  begin
40
- @data = YAML.load_file(@answer_file)
40
+ @data = load_yaml_file(@answer_file)
41
41
  rescue Errno::ENOENT => e
42
42
  puts "No answer file at #{@answer_file} found, can not continue"
43
43
  KafoConfigure.exit(:no_answer_file)
@@ -62,13 +62,15 @@ module Kafo
62
62
  def app
63
63
  @app ||= begin
64
64
  begin
65
- configuration = YAML.load_file(@config_file)
65
+ configuration = load_yaml_file(@config_file)
66
66
  rescue => e
67
67
  configuration = {}
68
68
  end
69
69
 
70
70
  result = DEFAULT.merge(configuration || {})
71
71
  result[:password] ||= PasswordManager.new.password
72
+ result[:module_dirs] = result[:modules_dir] || result[:module_dirs]
73
+ result.delete(:modules_dir)
72
74
  result
73
75
  end
74
76
  end
@@ -82,11 +84,31 @@ module Kafo
82
84
  end
83
85
 
84
86
  def modules
85
- @modules ||= @data.keys.map { |mod| PuppetModule.new(mod).parse }.sort
87
+ @modules ||= @data.keys.map { |mod| PuppetModule.new(mod, KafoParsers::PuppetModuleParser, self).parse }.sort
88
+ end
89
+
90
+ def root_dir
91
+ File.expand_path(app[:installer_dir])
92
+ end
93
+
94
+ def check_dirs
95
+ [app[:check_dirs] || File.join(root_dir, 'checks')].flatten
96
+ end
97
+
98
+ def module_dirs
99
+ [app[:module_dirs] || (app[:installer_dir] + '/modules')].flatten.map { |dir| File.expand_path(dir) }
100
+ end
101
+
102
+ def gem_root
103
+ File.join(File.dirname(__FILE__), '../../')
104
+ end
105
+
106
+ def kafo_modules_dir
107
+ app[:kafo_modules_dir] || (gem_root + '/modules')
86
108
  end
87
109
 
88
110
  def add_module(name)
89
- mod = PuppetModule.new(name).parse
111
+ mod = PuppetModule.new(name, KafoParsers::PuppetModuleParser, self).parse
90
112
  unless modules.map(&:name).include?(mod.name)
91
113
  mod.enable
92
114
  @modules << mod
@@ -98,13 +120,25 @@ module Kafo
98
120
  save_configuration(app)
99
121
  end
100
122
 
123
+ def migrate_configuration(from_config, options={})
124
+ keys_to_skip = options.fetch(:skip, [])
125
+ keys = [:log_dir, :log_name, :log_level, :no_prefix, :default_values_dir,
126
+ :colors, :color_of_background, :custom, :password, :verbose_log_level]
127
+ keys += options.fetch(:with, [])
128
+ keys.each do |key|
129
+ next if keys_to_skip.include?(key)
130
+ app[key] = from_config.app[key]
131
+ end
132
+ save_configuration(app)
133
+ end
134
+
101
135
  def params_default_values
102
136
  @params_default_values ||= begin
103
137
  @logger.debug "Creating tmp dir within #{app[:default_values_dir]}..."
104
138
  temp_dir = Dir.mktmpdir(nil, app[:default_values_dir])
105
139
  KafoConfigure.exit_handler.register_cleanup_path temp_dir
106
140
  @logger.info 'Loading default values from puppet modules...'
107
- command = PuppetCommand.new("$temp_dir=\"#{temp_dir}\" #{includes} dump_values(#{params})").append('2>&1').command
141
+ command = PuppetCommand.new("$temp_dir=\"#{temp_dir}\" #{includes} dump_values(#{params_to_dump})", ['--noop'], self).append('2>&1').command
108
142
  result = `#{command}`
109
143
  @logger.debug result
110
144
  unless $?.exitstatus == 0
@@ -116,7 +150,7 @@ module Kafo
116
150
  KafoConfigure.exit(:defaults_error)
117
151
  end
118
152
  @logger.info "... finished"
119
- YAML.load_file(File.join(temp_dir, 'default_values.yaml'))
153
+ load_yaml_file(File.join(temp_dir, 'default_values.yaml'))
120
154
  end
121
155
  end
122
156
 
@@ -133,7 +167,7 @@ module Kafo
133
167
  end
134
168
 
135
169
  def config_header
136
- files = [app[:config_header_file], File.join(KafoConfigure.gem_root, '/config/config_header.txt')].compact
170
+ files = [app[:config_header_file], File.join(gem_root, '/config/config_header.txt')].compact
137
171
  file = files.select { |f| File.exists?(f) }.first
138
172
  @config_header ||= file.nil? ? '' : File.read(file)
139
173
  end
@@ -145,6 +179,83 @@ module Kafo
145
179
  File.open(filename, 'w') { |file| file.write(config_header + format(YAML.dump(data))) }
146
180
  end
147
181
 
182
+ def params
183
+ @params ||= modules.map(&:params).flatten
184
+ end
185
+
186
+ def param(mod, name)
187
+ params.detect { |p| p.name == name && p.module.name == mod }
188
+ end
189
+
190
+ def preset_defaults_from_puppet
191
+ # set values based on default_values
192
+ params.each do |param|
193
+ param.set_default(params_default_values)
194
+ end
195
+ end
196
+
197
+ def preset_defaults_from_yaml
198
+ # set values based on YAML
199
+ params.each do |param|
200
+ param.set_value_by_config(self)
201
+ end
202
+ end
203
+
204
+ def preset_defaults_from_other_config(other_config)
205
+ params_changed(other_config).each do |par|
206
+ param(par.module.class_name, par.name).value = other_config.param(par.module.class_name, par.name).value
207
+ end
208
+ end
209
+
210
+ def params_changed(old_config)
211
+ # finds params that had different value in the old config
212
+ params.select do |par|
213
+ next unless par.module.enabled?
214
+ old_param = old_config.param(par.module.class_name, par.name)
215
+ old_param && old_param.value != par.value
216
+ end
217
+ end
218
+
219
+ def params_missing(old_config)
220
+ # finds params that are present but will be missing in the new config
221
+ old_config.params.select do |par|
222
+ next if !par.module.enabled? || !module_enabled?(par.module.name)
223
+ param(par.module.class_name, par.name).nil?
224
+ end
225
+ end
226
+
227
+ def temp_config_file
228
+ @temp_config_file ||= "/tmp/kafo_answers_#{rand(1_000_000)}.yaml"
229
+ end
230
+
231
+ def log_file
232
+ File.join(app[:log_dir], app[:log_name])
233
+ end
234
+
235
+ def log_exists?
236
+ File.exists?(log_file) && File.size(log_file) > 0
237
+ end
238
+
239
+ def answers
240
+ @data
241
+ end
242
+
243
+ def run_migrations
244
+ migrations = Kafo::Migrations.new(migrations_dir)
245
+ @app, @data = migrations.run(app, answers)
246
+ if migrations.migrations.count > 0
247
+ @modules = nil # force the lazy loaded modules to reload next time they are used
248
+ save_configuration(app)
249
+ store(answers)
250
+ migrations.store_applied
251
+ @logger.info("#{migrations.migrations.count} migration/s were applied. Updated configuration was saved.")
252
+ end
253
+ end
254
+
255
+ def migrations_dir
256
+ @config_file.gsub(/\.yaml$/, '.migrations')
257
+ end
258
+
148
259
  private
149
260
 
150
261
  def custom_storage
@@ -153,20 +264,26 @@ module Kafo
153
264
 
154
265
  def includes
155
266
  modules.map do |mod|
156
- params_file = File.join(KafoConfigure.modules_dir, mod.params_path)
157
- @logger.debug "checking presence of #{params_file}"
158
- File.exist?(params_file) ? "include #{mod.dir_name}::#{mod.params_class_name}" : nil
267
+ module_dir = module_dirs.find do |dir|
268
+ params_file = File.join(dir, mod.params_path)
269
+ @logger.debug "checking presence of #{params_file}"
270
+ File.exist?(params_file)
271
+ end
272
+ module_dir ? "include #{mod.dir_name}::#{mod.params_class_name}" : nil
159
273
  end.uniq.compact.join(' ')
160
274
  end
161
275
 
162
- def params
163
- params = modules.map(&:params).flatten
164
- params = params.select { |p| p.default != 'UNSET' }
165
- params.map { |param| "#{param.dump_default}" }.join(',')
276
+ def params_to_dump
277
+ parameters = params.select { |p| p.default != 'UNSET' }
278
+ parameters.map { |param| "#{param.dump_default}" }.join(',')
166
279
  end
167
280
 
168
281
  def format(data)
169
282
  data.gsub('!ruby/sym ', ':')
170
283
  end
284
+
285
+ def load_yaml_file(filename)
286
+ YAML.load_file(filename)
287
+ end
171
288
  end
172
289
  end
@@ -15,7 +15,9 @@ module Kafo
15
15
  :manifest_error => 22,
16
16
  :no_answer_file => 23,
17
17
  :unknown_module => 24,
18
- :defaults_error => 25
18
+ :defaults_error => 25,
19
+ :unknown_scenario => 26,
20
+ :scenario_error => 27
19
21
  }
20
22
  end
21
23
 
@@ -23,7 +25,7 @@ module Kafo
23
25
  @exit_code = translate_exit_code(code)
24
26
  block.call if block
25
27
  KafoConfigure.logger.debug "Exit with status code: #{@exit_code} (signal was #{code})"
26
- KafoConfigure.logger.dump_errors
28
+ KafoConfigure.logger.dump_errors unless KafoConfigure.verbose
27
29
  cleanup
28
30
  Kernel.exit(@exit_code)
29
31
  end
@@ -2,6 +2,7 @@ require 'kafo/hook_context'
2
2
 
3
3
  module Kafo
4
4
  class Hooking
5
+ # pre_migrations - just after kafo reads its configuration - useful for config file updates. Only in this stage it is posible to request config reload (`Kafo.request_config_reload`) to get in our changes
5
6
  # boot - before kafo is ready to work, useful for adding new app arguments, logger won't work yet
6
7
  # init - just after hooking is initialized and kafo is configured, parameters have no values yet
7
8
  # pre_values - just before value from CLI is set to parameters (they already have default values)
@@ -9,7 +10,7 @@ module Kafo
9
10
  # pre_commit - after validations or interactive wizard have completed, all parameter values are set but not yet stored in the answer file
10
11
  # pre - just before puppet is executed to converge system
11
12
  # post - just after puppet is executed to converge system
12
- TYPES = [:boot, :init, :pre, :post, :pre_values, :pre_validations, :pre_commit]
13
+ TYPES = [:pre_migrations, :boot, :init, :pre, :post, :pre_values, :pre_validations, :pre_commit]
13
14
 
14
15
  attr_accessor :hooks, :kafo
15
16
 
@@ -53,6 +54,10 @@ module Kafo
53
54
  logger.info "All hooks in group #{group} finished"
54
55
  end
55
56
 
57
+ def register_pre_migrations(name, &block)
58
+ register(:pre_migrations, name, &block)
59
+ end
60
+
56
61
  def register_boot(name, &block)
57
62
  register(:boot, name, &block)
58
63
  end
@@ -9,8 +9,10 @@ end
9
9
 
10
10
  require 'pty'
11
11
  require 'clamp'
12
+ require 'kafo/color_scheme'
12
13
  require 'kafo_parsers/exceptions'
13
14
  require 'kafo/exceptions'
15
+ require 'kafo/migrations'
14
16
  require 'kafo/configuration'
15
17
  require 'kafo/logger'
16
18
  require 'kafo/string_helper'
@@ -21,6 +23,7 @@ require 'kafo/puppet_command'
21
23
  require 'kafo/progress_bar'
22
24
  require 'kafo/hooking'
23
25
  require 'kafo/exit_handler'
26
+ require 'kafo/scenario_manager'
24
27
 
25
28
  module Kafo
26
29
  class KafoConfigure < Clamp::Command
@@ -28,8 +31,8 @@ module Kafo
28
31
 
29
32
  class << self
30
33
  attr_accessor :config, :root_dir, :config_file, :gem_root, :temp_config_file,
31
- :modules_dir, :kafo_modules_dir, :verbose, :app_options, :logger,
32
- :exit_handler
34
+ :module_dirs, :kafo_modules_dir, :verbose, :app_options, :logger,
35
+ :check_dirs, :exit_handler, :scenario_manager
33
36
  attr_writer :hooking
34
37
 
35
38
  def hooking
@@ -38,29 +41,53 @@ module Kafo
38
41
  end
39
42
 
40
43
  def initialize(*args)
44
+ self.class.preset_color_scheme
41
45
  self.class.logger = Logger.new
42
46
  self.class.exit_handler = ExitHandler.new
43
- self.class.config_file = config_file
44
- self.class.config = Configuration.new(self.class.config_file)
45
- self.class.root_dir = File.expand_path(self.class.config.app[:installer_dir])
46
- modules_dir = self.class.config.app[:modules_dir] || (self.class.config.app[:installer_dir] + '/modules')
47
- self.class.modules_dir = File.expand_path(modules_dir)
48
- self.class.gem_root = File.join(File.dirname(__FILE__), '../../')
49
- self.class.kafo_modules_dir = self.class.config.app[:kafo_modules_dir] || (self.class.gem_root + '/modules')
50
47
  @progress_bar = nil
51
- self.class.hooking.load
52
- self.class.hooking.kafo = self
48
+ @config_reload_requested = false
49
+
50
+ scenario_manager = setup_scenario_manager
51
+ self.class.scenario_manager = scenario_manager
52
+
53
+ # Handle --list-scenarios before we need them
54
+ scenario_manager.list_available_scenarios if ARGV.include?('--list-scenarios')
55
+ setup_config(config_file)
56
+
57
+ self.class.hooking.execute(:pre_migrations)
58
+
59
+ # run migrations
60
+ self.class.config.run_migrations
61
+
62
+ # reload config
63
+ if @config_reload_requested
64
+ scenario_manager = setup_scenario_manager
65
+ self.class.scenario_manager = scenario_manager
66
+ setup_config(self.class.config_file)
67
+ self.class.logger.info('Installer configuration was reloaded')
68
+ end
69
+
70
+ if scenario_manager.configured?
71
+ scenario_manager.check_scenario_change(self.class.config_file)
72
+ if scenario_manager.scenario_changed?(self.class.config_file)
73
+ prev_config = scenario_manager.load_configuration(scenario_manager.previous_scenario)
74
+ prev_config.run_migrations
75
+ self.class.config.migrate_configuration(prev_config, :skip => [:log_name])
76
+ setup_config(self.class.config_file)
77
+ self.class.logger.info("Due to scenario change the configuration (#{self.class.config_file}) was updated with #{scenario_manager.previous_scenario} and reloaded.")
78
+ end
79
+ end
53
80
 
54
81
  super
55
82
 
56
83
  self.class.hooking.execute(:boot)
57
- set_app_options
84
+ set_app_options # define args for installer
58
85
  # we need to parse app config params using clamp even before run method does it
59
86
  # so we limit parsing only to app config options (because of --help and later defined params)
60
87
  parse clamp_app_arguments
61
- parse_app_arguments
88
+ parse_app_arguments # set values from ARGS to config.app
62
89
  Logger.setup
63
- ColorScheme.new(config).setup
90
+ self.class.set_color_scheme
64
91
 
65
92
  self.class.hooking.execute(:init)
66
93
  set_parameters # here the params gets parsed and we need app config populated
@@ -104,10 +131,11 @@ module Kafo
104
131
 
105
132
  self.class.hooking.execute(:pre_commit)
106
133
  if dont_save_answers? || noop?
107
- self.class.temp_config_file = temp_config_file
108
- store_params(temp_config_file)
134
+ self.class.temp_config_file = self.class.config.temp_config_file
135
+ store_params(self.class.config.temp_config_file)
109
136
  else
110
137
  store_params
138
+ self.class.scenario_manager.link_last_scenario(self.class.config_file) if self.class.scenario_manager.configured?
111
139
  end
112
140
  run_installation
113
141
  return self
@@ -178,21 +206,39 @@ module Kafo
178
206
  end
179
207
 
180
208
  def param(mod, name)
181
- params.detect { |p| p.name == name && p.module.name == mod }
209
+ config.param(mod, name)
182
210
  end
183
211
 
212
+ def request_config_reload
213
+ @config_reload_requested = true
214
+ end
215
+
216
+
184
217
  private
185
218
 
186
- def set_parameters
187
- # set values based on default_values
188
- params.each do |param|
189
- param.set_default(config.params_default_values)
190
- end
219
+ def setup_config(conf_file)
220
+ self.class.config_file = conf_file
221
+ self.class.config = Configuration.new(self.class.config_file)
222
+ self.class.root_dir = self.class.config.root_dir
223
+ self.class.check_dirs = self.class.config.check_dirs
224
+ self.class.module_dirs = self.class.config.module_dirs
225
+ self.class.gem_root = self.class.config.gem_root
226
+ self.class.kafo_modules_dir = self.class.config.kafo_modules_dir
227
+ self.class.hooking.load
228
+ self.class.hooking.kafo = self
229
+ end
230
+
231
+ def setup_scenario_manager
232
+ ScenarioManager.new((defined?(CONFIG_DIR) && CONFIG_DIR) || (defined?(CONFIG_FILE) && CONFIG_FILE))
233
+ end
191
234
 
235
+ def set_parameters
236
+ config.preset_defaults_from_puppet
192
237
  self.class.hooking.execute(:pre_values)
193
- # set values based on YAML
194
- params.each do |param|
195
- param.set_value_by_config(config)
238
+ config.preset_defaults_from_yaml
239
+ if self.class.scenario_manager.scenario_changed?(config.config_file)
240
+ prev_scenario = self.class.scenario_manager.load_and_setup_configuration(self.class.scenario_manager.previous_scenario)
241
+ config.preset_defaults_from_other_config(prev_scenario)
196
242
  end
197
243
  end
198
244
 
@@ -216,6 +262,10 @@ module Kafo
216
262
  self.class.app_option ['-v', '--verbose'], :flag, 'Display log on STDOUT instead of progressbar'
217
263
  self.class.app_option ['-l', '--verbose-log-level'], 'LEVEL', 'Log level for verbose mode output',
218
264
  :default => 'info'
265
+ self.class.app_option ['-S', '--scenario'], 'SCENARIO', 'Use installation scenario'
266
+ self.class.app_option ['--list-scenarios'], :flag, 'List available installation scenaraios'
267
+ self.class.app_option ['--force'], :flag, 'Force change of installation scenaraio'
268
+ self.class.app_option ['--compare-scenarios'], :flag, 'Show changes between last used scenario and the scenario specified with -S or --scenario argument'
219
269
  end
220
270
 
221
271
  def set_options
@@ -341,7 +391,7 @@ module Kafo
341
391
  end
342
392
  @progress_bar.close if @progress_bar
343
393
  logger.info "Puppet has finished, bye!"
344
- FileUtils.rm(temp_config_file, :force => true)
394
+ FileUtils.rm(self.class.config.temp_config_file, :force => true)
345
395
  self.class.exit(exit_code) do
346
396
  self.class.hooking.execute(:post)
347
397
  end
@@ -375,13 +425,32 @@ module Kafo
375
425
 
376
426
  def config_file
377
427
  return CONFIG_FILE if defined?(CONFIG_FILE) && File.exists?(CONFIG_FILE)
428
+ return self.class.scenario_manager.select_scenario if self.class.scenario_manager.configured?
378
429
  return '/etc/kafo/kafo.yaml' if File.exists?('/etc/kafo/kafo.yaml')
379
430
  return "#{::RbConfig::CONFIG['sysconfdir']}/kafo/kafo.yaml" if File.exists?("#{::RbConfig::CONFIG['sysconfdir']}/kafo/kafo.yaml")
380
431
  File.join(Dir.pwd, 'config', 'kafo.yaml')
381
432
  end
382
433
 
383
- def temp_config_file
384
- @temp_config_file ||= "/tmp/kafo_answers_#{rand(1_000_000)}.yaml"
434
+ def self.use_colors?
435
+ if config
436
+ colors = config.app[:colors]
437
+ else
438
+ colors = ARGV.include?('--no-colors') ? false : nil
439
+ colors = ARGV.include?('--colors') ? true : nil if colors.nil?
440
+ end
441
+ colors
442
+ end
443
+
444
+ def self.preset_color_scheme
445
+ match = ARGV.join(' ').match /--color-of-background[ =](\w+)/
446
+ background = match && match[1]
447
+ ColorScheme.new(:background => background, :colors => use_colors?).setup
448
+ end
449
+
450
+ def self.set_color_scheme
451
+ ColorScheme.new(
452
+ :background => config.app[:color_of_background],
453
+ :colors => use_colors?).setup
385
454
  end
386
455
  end
387
456
  end