leap_cli 1.8.1 → 1.9
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/bin/leap +6 -12
- data/lib/leap_cli.rb +3 -23
- data/lib/leap_cli/bootstrap.rb +36 -12
- data/lib/leap_cli/commands/common.rb +88 -46
- data/lib/leap_cli/commands/new.rb +24 -17
- data/lib/leap_cli/commands/pre.rb +3 -1
- data/lib/leap_cli/core_ext/hash.rb +19 -0
- data/lib/leap_cli/leapfile.rb +47 -32
- data/lib/leap_cli/log.rb +196 -88
- data/lib/leap_cli/path.rb +5 -5
- data/lib/leap_cli/util.rb +28 -18
- data/lib/leap_cli/version.rb +8 -3
- data/vendor/acme-client/lib/acme-client.rb +1 -0
- data/vendor/acme-client/lib/acme/client.rb +122 -0
- data/vendor/acme-client/lib/acme/client/certificate.rb +30 -0
- data/vendor/acme-client/lib/acme/client/certificate_request.rb +111 -0
- data/vendor/acme-client/lib/acme/client/crypto.rb +98 -0
- data/vendor/acme-client/lib/acme/client/error.rb +16 -0
- data/vendor/acme-client/lib/acme/client/faraday_middleware.rb +123 -0
- data/vendor/acme-client/lib/acme/client/resources.rb +5 -0
- data/vendor/acme-client/lib/acme/client/resources/authorization.rb +44 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges.rb +6 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/base.rb +43 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb +19 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb +18 -0
- data/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb +24 -0
- data/vendor/acme-client/lib/acme/client/resources/registration.rb +37 -0
- data/vendor/acme-client/lib/acme/client/self_sign_certificate.rb +60 -0
- data/vendor/acme-client/lib/acme/client/version.rb +7 -0
- data/vendor/base32/lib/base32.rb +67 -0
- data/vendor/certificate_authority/lib/certificate_authority.rb +2 -1
- data/vendor/certificate_authority/lib/certificate_authority/certificate.rb +4 -4
- data/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb +7 -5
- data/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb +46 -0
- data/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb +6 -2
- data/vendor/certificate_authority/lib/certificate_authority/extensions.rb +10 -3
- data/vendor/certificate_authority/lib/certificate_authority/key_material.rb +11 -9
- data/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb +3 -3
- data/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb +0 -2
- data/vendor/certificate_authority/lib/certificate_authority/serial_number.rb +8 -2
- data/vendor/certificate_authority/lib/certificate_authority/validations.rb +31 -0
- data/vendor/rsync_command/lib/rsync_command.rb +49 -12
- metadata +50 -91
- data/lib/leap/platform.rb +0 -90
- data/lib/leap_cli/config/environment.rb +0 -180
- data/lib/leap_cli/config/filter.rb +0 -178
- data/lib/leap_cli/config/manager.rb +0 -419
- data/lib/leap_cli/config/node.rb +0 -77
- data/lib/leap_cli/config/object.rb +0 -428
- data/lib/leap_cli/config/object_list.rb +0 -209
- data/lib/leap_cli/config/provider.rb +0 -22
- data/lib/leap_cli/config/secrets.rb +0 -87
- data/lib/leap_cli/config/sources.rb +0 -11
- data/lib/leap_cli/config/tag.rb +0 -25
- data/lib/leap_cli/lib_ext/capistrano_connections.rb +0 -16
- data/lib/leap_cli/logger.rb +0 -237
- data/lib/leap_cli/remote/leap_plugin.rb +0 -192
- data/lib/leap_cli/remote/puppet_plugin.rb +0 -26
- data/lib/leap_cli/remote/rsync_plugin.rb +0 -35
- data/lib/leap_cli/remote/tasks.rb +0 -51
- data/lib/leap_cli/ssh_key.rb +0 -195
- data/lib/leap_cli/util/remote_command.rb +0 -158
- data/lib/leap_cli/util/secret.rb +0 -55
- data/lib/leap_cli/util/x509.rb +0 -33
@@ -32,4 +32,23 @@ class Hash
|
|
32
32
|
replace(deep_merge(other_hash))
|
33
33
|
end
|
34
34
|
|
35
|
+
#
|
36
|
+
# A recursive symbolize_keys
|
37
|
+
#
|
38
|
+
unless Hash.method_defined?(:symbolize_keys)
|
39
|
+
def symbolize_keys
|
40
|
+
self.inject({}) {|result, (key, value)|
|
41
|
+
new_key = case key
|
42
|
+
when String then key.to_sym
|
43
|
+
else key
|
44
|
+
end
|
45
|
+
new_value = case value
|
46
|
+
when Hash then symbolize_keys(value)
|
47
|
+
else value
|
48
|
+
end
|
49
|
+
result[new_key] = new_value
|
50
|
+
result
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
35
54
|
end
|
data/lib/leap_cli/leapfile.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
#
|
4
4
|
# It is akin to a Gemfile, Rakefile, or Capfile (e.g. it is a ruby file that gets eval'ed)
|
5
5
|
#
|
6
|
+
# Additional configuration options are defined in platform's leapfile_extensions.rb
|
7
|
+
#
|
6
8
|
|
7
9
|
module LeapCli
|
8
10
|
def self.leapfile
|
@@ -10,17 +12,12 @@ module LeapCli
|
|
10
12
|
end
|
11
13
|
|
12
14
|
class Leapfile
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
attr_accessor :log
|
18
|
-
attr_accessor :vagrant_network
|
19
|
-
attr_accessor :vagrant_basebox
|
20
|
-
attr_accessor :environment
|
15
|
+
attr_reader :platform_directory_path
|
16
|
+
attr_reader :provider_directory_path
|
17
|
+
attr_reader :environment
|
18
|
+
attr_reader :valid
|
21
19
|
|
22
20
|
def initialize
|
23
|
-
@vagrant_network = '10.5.5.0/24'
|
24
21
|
end
|
25
22
|
|
26
23
|
#
|
@@ -61,25 +58,44 @@ module LeapCli
|
|
61
58
|
#
|
62
59
|
# load the platform
|
63
60
|
#
|
64
|
-
|
65
|
-
|
61
|
+
platform_class = "#{@platform_directory_path}/lib/leap/platform"
|
62
|
+
platform_definition = "#{@platform_directory_path}/platform.rb"
|
63
|
+
unless File.exist?(platform_definition)
|
66
64
|
Util.bail! "ERROR: The file `#{platform_file}` does not exist. Please check the value of `@platform_directory_path` in `Leapfile` or `~/.leaprc`."
|
67
65
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
begin
|
67
|
+
require platform_class
|
68
|
+
require platform_definition
|
69
|
+
rescue LoadError
|
70
|
+
Util.log "The leap_platform at #{platform_directory_path} is not compatible with this version of leap_cli"
|
71
|
+
Util.log "You can either:" do
|
72
|
+
Util.log "Upgrade leap_platform to version " + LeapCli::COMPATIBLE_PLATFORM_VERSION.first
|
73
|
+
Util.log "Or, downgrade leap_cli to version 1.8"
|
74
|
+
end
|
75
|
+
Util.bail!
|
76
|
+
rescue StandardError => exc
|
77
|
+
Util.bail! exc.to_s
|
75
78
|
end
|
76
|
-
|
77
|
-
|
79
|
+
begin
|
80
|
+
Leap::Platform.validate!(LeapCli::VERSION, LeapCli::COMPATIBLE_PLATFORM_VERSION, self)
|
81
|
+
rescue StandardError => exc
|
82
|
+
Util.bail! exc.to_s
|
78
83
|
end
|
79
|
-
|
80
|
-
|
84
|
+
leapfile_extensions = "#{@platform_directory_path}/lib/leap_cli/leapfile_extensions.rb"
|
85
|
+
if File.exist?(leapfile_extensions)
|
86
|
+
require leapfile_extensions
|
81
87
|
end
|
82
|
-
|
88
|
+
|
89
|
+
#
|
90
|
+
# validate
|
91
|
+
#
|
92
|
+
instance_variables.each do |var|
|
93
|
+
var = var.to_s.sub('@', '')
|
94
|
+
if !self.respond_to?(var)
|
95
|
+
LeapCli.log :warning, "the variable `#{var}` is set in .leaprc or Leapfile, but it is not supported."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
@valid = validate
|
83
99
|
return @valid
|
84
100
|
end
|
85
101
|
end
|
@@ -105,7 +121,7 @@ module LeapCli
|
|
105
121
|
def edit_leaprc(property, value=nil)
|
106
122
|
file_path = leaprc_path
|
107
123
|
lines = []
|
108
|
-
if File.
|
124
|
+
if File.exist?(file_path)
|
109
125
|
regexp = /self\.#{Regexp.escape(property)} = .*? if @provider_directory_path == '#{Regexp.escape(@provider_directory_path)}'/
|
110
126
|
File.readlines(file_path).each do |line|
|
111
127
|
unless line =~ regexp
|
@@ -128,10 +144,9 @@ module LeapCli
|
|
128
144
|
end
|
129
145
|
|
130
146
|
def read_settings(file)
|
131
|
-
if File.
|
132
|
-
|
147
|
+
if File.exist? file
|
148
|
+
LeapCli.log 2, :read, file
|
133
149
|
instance_eval(File.read(file), file)
|
134
|
-
validate(file)
|
135
150
|
end
|
136
151
|
end
|
137
152
|
|
@@ -146,11 +161,11 @@ module LeapCli
|
|
146
161
|
return search_dir
|
147
162
|
end
|
148
163
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
164
|
+
def method_missing(method, *args)
|
165
|
+
if method =~ /=$/
|
166
|
+
self.instance_variable_set('@' + method.to_s.sub('=',''), args.first)
|
167
|
+
else
|
168
|
+
self.instance_variable_get('@' + method.to_s)
|
154
169
|
end
|
155
170
|
end
|
156
171
|
|
data/lib/leap_cli/log.rb
CHANGED
@@ -1,58 +1,84 @@
|
|
1
|
-
require 'paint'
|
2
|
-
|
3
1
|
##
|
4
2
|
## LOGGING
|
5
3
|
##
|
6
|
-
## Ugh. This class does not work well with multiple threads!
|
7
|
-
##
|
8
4
|
|
9
5
|
module LeapCli
|
10
|
-
|
6
|
+
module LogCommand
|
7
|
+
@@logger = nil
|
11
8
|
|
12
|
-
|
9
|
+
def log(*args, &block)
|
10
|
+
logger.log(*args, &block)
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
def set_log_level(value)
|
19
|
-
@log_level = value
|
20
|
-
end
|
13
|
+
def log_raw(*args, &block)
|
14
|
+
logger.log_raw(*args, &block)
|
15
|
+
end
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@indent_level = value
|
27
|
-
end
|
17
|
+
# global shared logger
|
18
|
+
def logger
|
19
|
+
@@logger ||= LeapCli::LeapLogger.new
|
20
|
+
end
|
28
21
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def log_file=(value)
|
33
|
-
@log_file = value
|
34
|
-
if @log_file
|
35
|
-
if !File.directory?(File.dirname(@log_file))
|
36
|
-
Util.bail!('Invalid log file "%s", directory "%s" does not exist' % [@log_file, File.dirname(@log_file)])
|
37
|
-
end
|
38
|
-
@log_output_stream = File.open(@log_file, 'a')
|
22
|
+
# thread safe logger
|
23
|
+
def new_logger
|
24
|
+
logger.dup
|
39
25
|
end
|
40
|
-
end
|
41
26
|
|
42
|
-
|
43
|
-
|
44
|
-
|
27
|
+
# deprecated
|
28
|
+
def log_level
|
29
|
+
logger.log_level
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# These probably should have been part of the logger originally,
|
34
|
+
# but they are made available here for convenience:
|
35
|
+
#
|
36
|
+
|
37
|
+
def bail!(*args, &block)
|
38
|
+
Util.bail!(*args, &block)
|
39
|
+
end
|
45
40
|
|
41
|
+
def assert!(*args, &block)
|
42
|
+
Util.assert!(*args, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
46
|
end
|
47
47
|
|
48
48
|
|
49
49
|
module LeapCli
|
50
|
-
|
50
|
+
class LeapLogger
|
51
51
|
#
|
52
52
|
# these are log titles typically associated with files
|
53
53
|
#
|
54
|
-
FILE_TITLES =
|
54
|
+
FILE_TITLES = %w(updated created removed missing nochange loading)
|
55
|
+
|
56
|
+
# TODO: use these
|
57
|
+
IMPORTANT = 0
|
58
|
+
INFO = 1
|
59
|
+
DEBUG = 2
|
60
|
+
TRACE = 3
|
55
61
|
|
62
|
+
attr_reader :log_output_stream, :log_file
|
63
|
+
attr_accessor :indent_level, :log_level, :log_in_color
|
64
|
+
|
65
|
+
def initialize()
|
66
|
+
@log_level = 1
|
67
|
+
@indent_level = 0
|
68
|
+
@log_file = nil
|
69
|
+
@log_output_stream = nil
|
70
|
+
@log_in_color = true
|
71
|
+
end
|
72
|
+
|
73
|
+
def log_file=(value)
|
74
|
+
@log_file = value
|
75
|
+
if @log_file
|
76
|
+
if !File.directory?(File.dirname(@log_file))
|
77
|
+
Util.bail!('Invalid log file "%s", directory "%s" does not exist' % [@log_file, File.dirname(@log_file)])
|
78
|
+
end
|
79
|
+
@log_output_stream = File.open(@log_file, 'a')
|
80
|
+
end
|
81
|
+
end
|
56
82
|
|
57
83
|
#
|
58
84
|
# master logging function.
|
@@ -63,74 +89,95 @@ module LeapCli
|
|
63
89
|
# * Integer: the log level (0, 1, 2)
|
64
90
|
# * Symbol: the prefix title to colorize. may be one of
|
65
91
|
# [:error, :warning, :info, :updated, :created, :removed, :no_change, :missing]
|
66
|
-
# * Hash: a hash of options.
|
92
|
+
# * Hash: a hash of options.
|
93
|
+
# :wrap -- if true, appy intend to each line in message.
|
94
|
+
# :color -- apply color to message or prefix
|
95
|
+
# :style -- apply style to message or prefix
|
67
96
|
#
|
68
|
-
|
69
97
|
def log(*args)
|
70
98
|
level = args.grep(Integer).first || 1
|
71
99
|
title = args.grep(Symbol).first
|
72
100
|
message = args.grep(String).first
|
73
101
|
options = args.grep(Hash).first || {}
|
74
|
-
|
102
|
+
host = options[:host]
|
103
|
+
if title
|
104
|
+
title = title.to_s
|
105
|
+
end
|
106
|
+
if @log_level < level || (title.nil? && message.nil?)
|
75
107
|
return
|
76
108
|
end
|
77
109
|
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
when :loading then ['loading', :magenta]
|
93
|
-
when :missing then ['missing', :yellow, :bold]
|
94
|
-
when :skipping then ['skipping', :yellow, :bold]
|
95
|
-
when :run then ['run', :magenta]
|
96
|
-
when :failed then ['FAILED', :red, :bold]
|
97
|
-
when :completed then ['completed', :green, :bold]
|
98
|
-
when :ran then ['ran', :green, :bold]
|
99
|
-
when :bail then ['bailing out', :red, :bold]
|
100
|
-
when :invalid then ['invalid', :red, :bold]
|
101
|
-
else [title.to_s, :cyan, :bold]
|
102
|
-
end
|
103
|
-
if options[:host]
|
104
|
-
clear_prefix = "[%s] %s " % [options[:host], prefix_options[0]]
|
105
|
-
colored_prefix = "[%s] %s " % [Paint[options[:host], prefix_options[1], prefix_options[2]], prefix_options[0]]
|
110
|
+
#
|
111
|
+
# transform absolute path names
|
112
|
+
#
|
113
|
+
if title && FILE_TITLES.include?(title) && message =~ /^\//
|
114
|
+
message = LeapCli::Path.relative_path(message)
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# apply filters
|
119
|
+
# LogFilter will not be defined if no platform was loaded.
|
120
|
+
#
|
121
|
+
if defined?(LeapCli::LogFilter)
|
122
|
+
if title
|
123
|
+
title, filter_flags = LogFilter.apply_title_filters(title)
|
106
124
|
else
|
107
|
-
|
108
|
-
|
125
|
+
message, filter_flags = LogFilter.apply_message_filters(message)
|
126
|
+
return if message.nil?
|
109
127
|
end
|
110
|
-
|
111
|
-
clear_prefix = colored_prefix = "[%s] " % options[:host]
|
128
|
+
options = options.merge(filter_flags)
|
112
129
|
end
|
113
130
|
|
114
|
-
#
|
115
|
-
|
116
|
-
|
131
|
+
#
|
132
|
+
# set line prefix
|
133
|
+
#
|
134
|
+
if (host)
|
135
|
+
host = host.split('.').first
|
117
136
|
end
|
137
|
+
prefix = prefix_str(host, title)
|
118
138
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
139
|
+
#
|
140
|
+
# write to the log file, always
|
141
|
+
#
|
142
|
+
log_raw(:log, nil, prefix) { message }
|
143
|
+
|
144
|
+
#
|
145
|
+
# log to stdout, maybe in color
|
146
|
+
#
|
147
|
+
if @log_in_color
|
148
|
+
if options[:wrap]
|
149
|
+
message = message.split("\n")
|
150
|
+
end
|
151
|
+
if options[:color]
|
152
|
+
if host
|
153
|
+
host = colorize(host, options[:color], options[:style])
|
154
|
+
elsif title
|
155
|
+
title = colorize(title, options[:color], options[:style])
|
156
|
+
else
|
157
|
+
message = colorize(message, options[:color], options[:style])
|
158
|
+
end
|
159
|
+
elsif title
|
160
|
+
title = colorize(title, :cyan, :bold)
|
161
|
+
end
|
162
|
+
# new colorized prefix:
|
163
|
+
prefix = prefix_str(host, title)
|
124
164
|
end
|
165
|
+
log_raw(:stdout, options[:indent], prefix) { message }
|
125
166
|
|
126
|
-
#
|
167
|
+
#
|
168
|
+
# run block indented, if given
|
169
|
+
#
|
127
170
|
if block_given?
|
128
|
-
|
171
|
+
@indent_level += 1
|
129
172
|
yield
|
130
|
-
|
173
|
+
@indent_level -= 1
|
131
174
|
end
|
132
175
|
end
|
133
176
|
|
177
|
+
def debug(*args)
|
178
|
+
self.log(3, *args)
|
179
|
+
end
|
180
|
+
|
134
181
|
#
|
135
182
|
# Add a raw log entry, without any modifications (other than indent).
|
136
183
|
# Content to be logged is yielded by the block.
|
@@ -139,23 +186,26 @@ module LeapCli
|
|
139
186
|
# if mode == :stdout, output is sent to STDOUT.
|
140
187
|
# if mode == :log, output is sent to log file, if present.
|
141
188
|
#
|
142
|
-
def log_raw(mode, indent=nil, &block)
|
143
|
-
# NOTE:
|
189
|
+
def log_raw(mode, indent=nil, prefix=nil, &block)
|
190
|
+
# NOTE: using 'print' produces better results than 'puts'
|
191
|
+
# when multiple threads are logging)
|
144
192
|
if mode == :log
|
145
|
-
if
|
193
|
+
if @log_output_stream
|
146
194
|
messages = [yield].compact.flatten
|
147
195
|
if messages.any?
|
148
196
|
timestamp = Time.now.strftime("%b %d %H:%M:%S")
|
149
197
|
messages.each do |message|
|
150
|
-
|
198
|
+
message = message.rstrip
|
199
|
+
next if message.empty?
|
200
|
+
@log_output_stream.print("#{timestamp} #{prefix} #{message}\n")
|
151
201
|
end
|
152
|
-
|
202
|
+
@log_output_stream.flush
|
153
203
|
end
|
154
204
|
end
|
155
205
|
elsif mode == :stdout
|
156
206
|
messages = [yield].compact.flatten
|
157
207
|
if messages.any?
|
158
|
-
indent ||=
|
208
|
+
indent ||= @indent_level
|
159
209
|
indent_str = ""
|
160
210
|
indent_str += " " * indent.to_i
|
161
211
|
if indent.to_i > 0
|
@@ -163,12 +213,70 @@ module LeapCli
|
|
163
213
|
else
|
164
214
|
indent_str += ' = '
|
165
215
|
end
|
216
|
+
indent_str += prefix if prefix
|
166
217
|
messages.each do |message|
|
218
|
+
message = message.rstrip
|
219
|
+
next if message.empty?
|
167
220
|
STDOUT.print("#{indent_str}#{message}\n")
|
168
221
|
end
|
169
222
|
end
|
170
223
|
end
|
171
224
|
end
|
172
225
|
|
226
|
+
def colorize(str, color, style=nil)
|
227
|
+
codes = [FG_COLORS[color] || FG_COLORS[:default]]
|
228
|
+
if style
|
229
|
+
codes << EFFECTS[style] || EFFECTS[:nothing]
|
230
|
+
end
|
231
|
+
if str.is_a?(String)
|
232
|
+
["\033[%sm" % codes.join(';'), str, NO_COLOR].join
|
233
|
+
elsif str.is_a?(Array)
|
234
|
+
str.map { |s|
|
235
|
+
["\033[%sm" % codes.join(';'), s, NO_COLOR].join
|
236
|
+
}
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
private
|
241
|
+
|
242
|
+
def prefix_str(host, title)
|
243
|
+
prefix = ""
|
244
|
+
prefix += "[" + host + "] " if host
|
245
|
+
prefix += title + " " if title
|
246
|
+
prefix += " " if !prefix.empty? && prefix !~ / $/
|
247
|
+
return prefix
|
248
|
+
end
|
249
|
+
|
250
|
+
EFFECTS = {
|
251
|
+
:reset => 0, :nothing => 0,
|
252
|
+
:bright => 1, :bold => 1,
|
253
|
+
:underline => 4,
|
254
|
+
:inverse => 7, :swap => 7,
|
255
|
+
}
|
256
|
+
NO_COLOR = "\033[0m"
|
257
|
+
FG_COLORS = {
|
258
|
+
:black => 30,
|
259
|
+
:red => 31,
|
260
|
+
:green => 32,
|
261
|
+
:yellow => 33,
|
262
|
+
:blue => 34,
|
263
|
+
:magenta => 35,
|
264
|
+
:cyan => 36,
|
265
|
+
:white => 37,
|
266
|
+
:default => 39,
|
267
|
+
}
|
268
|
+
BG_COLORS = {
|
269
|
+
:black => 40,
|
270
|
+
:red => 41,
|
271
|
+
:green => 42,
|
272
|
+
:yellow => 43,
|
273
|
+
:blue => 44,
|
274
|
+
:magenta => 45,
|
275
|
+
:cyan => 46,
|
276
|
+
:white => 47,
|
277
|
+
:default => 49,
|
278
|
+
}
|
279
|
+
|
173
280
|
end
|
174
|
-
end
|
281
|
+
end
|
282
|
+
|