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
@@ -1,209 +0,0 @@
|
|
1
|
-
require 'tsort'
|
2
|
-
|
3
|
-
module LeapCli
|
4
|
-
module Config
|
5
|
-
#
|
6
|
-
# A list of Config::Object instances (internally stored as a hash)
|
7
|
-
#
|
8
|
-
class ObjectList < Hash
|
9
|
-
include TSort
|
10
|
-
|
11
|
-
def initialize(config=nil)
|
12
|
-
if config
|
13
|
-
self.add(config['name'], config)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
#
|
18
|
-
# If the key is a string, the Config::Object it references is returned.
|
19
|
-
#
|
20
|
-
# If the key is a hash, we treat it as a condition and filter all the Config::Objects using the condition.
|
21
|
-
# A new ObjectList is returned.
|
22
|
-
#
|
23
|
-
# Examples:
|
24
|
-
#
|
25
|
-
# nodes['vpn1']
|
26
|
-
# node named 'vpn1'
|
27
|
-
#
|
28
|
-
# nodes[:public_dns => true]
|
29
|
-
# all nodes with public dns
|
30
|
-
#
|
31
|
-
# nodes[:services => 'openvpn', 'location.country_code' => 'US']
|
32
|
-
# all nodes with services containing 'openvpn' OR country code of US
|
33
|
-
#
|
34
|
-
# Sometimes, you want to do an OR condition with multiple conditions
|
35
|
-
# for the same field. Since hash keys must be unique, you can use
|
36
|
-
# an array representation instead:
|
37
|
-
#
|
38
|
-
# nodes[[:services, 'openvpn'], [:services, 'tor']]
|
39
|
-
# nodes with openvpn OR tor service
|
40
|
-
#
|
41
|
-
# nodes[:services => 'openvpn'][:tags => 'production']
|
42
|
-
# nodes with openvpn AND are production
|
43
|
-
#
|
44
|
-
def [](key)
|
45
|
-
if key.is_a?(Hash) || key.is_a?(Array)
|
46
|
-
filter(key)
|
47
|
-
else
|
48
|
-
super key.to_s
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def exclude(node)
|
53
|
-
list = self.dup
|
54
|
-
list.delete(node.name)
|
55
|
-
return list
|
56
|
-
end
|
57
|
-
|
58
|
-
def each_node(&block)
|
59
|
-
self.keys.sort.each do |node_name|
|
60
|
-
yield self[node_name]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
#
|
65
|
-
# filters this object list, producing a new list.
|
66
|
-
# filter is an array or a hash. see []
|
67
|
-
#
|
68
|
-
def filter(filter)
|
69
|
-
results = Config::ObjectList.new
|
70
|
-
filter.each do |field, match_value|
|
71
|
-
field = field.is_a?(Symbol) ? field.to_s : field
|
72
|
-
match_value = match_value.is_a?(Symbol) ? match_value.to_s : match_value
|
73
|
-
if match_value.is_a?(String) && match_value =~ /^!/
|
74
|
-
operator = :not_equal
|
75
|
-
match_value = match_value.sub(/^!/, '')
|
76
|
-
else
|
77
|
-
operator = :equal
|
78
|
-
end
|
79
|
-
each do |name, config|
|
80
|
-
value = config[field]
|
81
|
-
if value.is_a? Array
|
82
|
-
if operator == :equal && value.include?(match_value)
|
83
|
-
results[name] = config
|
84
|
-
elsif operator == :not_equal && !value.include?(match_value)
|
85
|
-
results[name] = config
|
86
|
-
end
|
87
|
-
else
|
88
|
-
if operator == :equal && value == match_value
|
89
|
-
results[name] = config
|
90
|
-
elsif operator == :not_equal && value != match_value
|
91
|
-
results[name] = config
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
results
|
97
|
-
end
|
98
|
-
|
99
|
-
def add(name, object)
|
100
|
-
self[name] = object
|
101
|
-
end
|
102
|
-
|
103
|
-
#
|
104
|
-
# converts the hash of configs into an array of hashes, with ONLY the specified fields
|
105
|
-
#
|
106
|
-
def fields(*fields)
|
107
|
-
result = []
|
108
|
-
keys.sort.each do |name|
|
109
|
-
result << self[name].pick(*fields)
|
110
|
-
end
|
111
|
-
result
|
112
|
-
end
|
113
|
-
|
114
|
-
#
|
115
|
-
# like fields(), but returns an array of values instead of an array of hashes.
|
116
|
-
#
|
117
|
-
def field(field)
|
118
|
-
field = field.to_s
|
119
|
-
result = []
|
120
|
-
keys.sort.each do |name|
|
121
|
-
result << self[name].get(field)
|
122
|
-
end
|
123
|
-
result
|
124
|
-
end
|
125
|
-
|
126
|
-
#
|
127
|
-
# pick_fields(field1, field2, ...)
|
128
|
-
#
|
129
|
-
# generates a Hash from the object list, but with only the fields that are picked.
|
130
|
-
#
|
131
|
-
# If there are more than one field, then the result is a Hash of Hashes.
|
132
|
-
# If there is just one field, it is a simple map to the value.
|
133
|
-
#
|
134
|
-
# For example:
|
135
|
-
#
|
136
|
-
# "neighbors" = "= nodes_like_me[:services => :couchdb].pick_fields('domain.full', 'ip_address')"
|
137
|
-
#
|
138
|
-
# generates this:
|
139
|
-
#
|
140
|
-
# neighbors:
|
141
|
-
# couch1:
|
142
|
-
# domain_full: couch1.bitmask.net
|
143
|
-
# ip_address: "10.5.5.44"
|
144
|
-
# couch2:
|
145
|
-
# domain_full: couch2.bitmask.net
|
146
|
-
# ip_address: "10.5.5.52"
|
147
|
-
#
|
148
|
-
# But this:
|
149
|
-
#
|
150
|
-
# "neighbors": "= nodes_like_me[:services => :couchdb].pick_fields('domain.full')"
|
151
|
-
#
|
152
|
-
# will generate this:
|
153
|
-
#
|
154
|
-
# neighbors:
|
155
|
-
# couch1: couch1.bitmask.net
|
156
|
-
# couch2: couch2.bitmask.net
|
157
|
-
#
|
158
|
-
def pick_fields(*fields)
|
159
|
-
self.values.inject({}) do |hsh, node|
|
160
|
-
value = self[node.name].pick(*fields)
|
161
|
-
if fields.size == 1
|
162
|
-
value = value.values.first
|
163
|
-
end
|
164
|
-
hsh[node.name] = value
|
165
|
-
hsh
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
#
|
170
|
-
# Applies inherit_from! to all objects.
|
171
|
-
#
|
172
|
-
# 'env' specifies what environment should be for
|
173
|
-
# each object in the list.
|
174
|
-
#
|
175
|
-
def inherit_from!(object_list, env)
|
176
|
-
object_list.each do |name, object|
|
177
|
-
if self[name]
|
178
|
-
self[name].inherit_from!(object)
|
179
|
-
else
|
180
|
-
self[name] = object.duplicate(env)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
#
|
186
|
-
# topographical sort based on test dependency
|
187
|
-
#
|
188
|
-
def tsort_each_node(&block)
|
189
|
-
self.each_key(&block)
|
190
|
-
end
|
191
|
-
|
192
|
-
def tsort_each_child(node_name, &block)
|
193
|
-
if self[node_name]
|
194
|
-
self[node_name].test_dependencies.each do |test_me_first|
|
195
|
-
if self[test_me_first] # TODO: in the future, allow for ability to optionally pull in all dependencies.
|
196
|
-
# not just the ones that pass the node filter.
|
197
|
-
yield(test_me_first)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def names_in_test_dependency_order
|
204
|
-
self.tsort
|
205
|
-
end
|
206
|
-
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Configuration class for provider.json
|
3
|
-
#
|
4
|
-
|
5
|
-
module LeapCli; module Config
|
6
|
-
class Provider < Object
|
7
|
-
attr_reader :environment
|
8
|
-
def set_env(e)
|
9
|
-
if e == 'default'
|
10
|
-
@environment = nil
|
11
|
-
else
|
12
|
-
@environment = e
|
13
|
-
end
|
14
|
-
end
|
15
|
-
def provider
|
16
|
-
self
|
17
|
-
end
|
18
|
-
def validate!
|
19
|
-
# nothing here yet :(
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end; end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
#
|
3
|
-
# A class for the secrets.json file
|
4
|
-
#
|
5
|
-
|
6
|
-
module LeapCli; module Config
|
7
|
-
|
8
|
-
class Secrets < Object
|
9
|
-
attr_reader :node_list
|
10
|
-
|
11
|
-
def initialize(manager=nil)
|
12
|
-
super(manager)
|
13
|
-
@discovered_keys = {}
|
14
|
-
end
|
15
|
-
|
16
|
-
# we can't use fetch() or get(), since those already have special meanings
|
17
|
-
def retrieve(key, environment)
|
18
|
-
environment ||= 'default'
|
19
|
-
self.fetch(environment, {})[key.to_s]
|
20
|
-
end
|
21
|
-
|
22
|
-
def set(*args, &block)
|
23
|
-
if block_given?
|
24
|
-
set_with_block(*args, &block)
|
25
|
-
else
|
26
|
-
set_without_block(*args)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# searches over all keys matching the regexp, checking to see if the value
|
31
|
-
# has been already used by any of them.
|
32
|
-
def taken?(regexp, value, environment)
|
33
|
-
self.keys.grep(regexp).each do |key|
|
34
|
-
return true if self.retrieve(key, environment) == value
|
35
|
-
end
|
36
|
-
return false
|
37
|
-
end
|
38
|
-
|
39
|
-
def set_without_block(key, value, environment)
|
40
|
-
set_with_block(key, environment) {value}
|
41
|
-
end
|
42
|
-
|
43
|
-
def set_with_block(key, environment, &block)
|
44
|
-
environment ||= 'default'
|
45
|
-
key = key.to_s
|
46
|
-
@discovered_keys[environment] ||= {}
|
47
|
-
@discovered_keys[environment][key] = true
|
48
|
-
self[environment] ||= {}
|
49
|
-
self[environment][key] ||= yield
|
50
|
-
end
|
51
|
-
|
52
|
-
#
|
53
|
-
# if clean is true, then only secrets that have been discovered
|
54
|
-
# during this run will be exported.
|
55
|
-
#
|
56
|
-
# if environment is also pinned, then we will clean those secrets
|
57
|
-
# just for that environment.
|
58
|
-
#
|
59
|
-
# the clean argument should only be used when all nodes have
|
60
|
-
# been processed, otherwise secrets that are actually in use will
|
61
|
-
# get mistakenly removed.
|
62
|
-
#
|
63
|
-
def dump_json(clean=false)
|
64
|
-
pinned_env = LeapCli.leapfile.environment
|
65
|
-
if clean
|
66
|
-
self.each_key do |environment|
|
67
|
-
if pinned_env.nil? || pinned_env == environment
|
68
|
-
env = self[environment]
|
69
|
-
if env.nil?
|
70
|
-
raise StandardError.new("secrets.json file seems corrupted. No such environment '#{environment}'")
|
71
|
-
end
|
72
|
-
env.each_key do |key|
|
73
|
-
unless @discovered_keys[environment] && @discovered_keys[environment][key]
|
74
|
-
self[environment].delete(key)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
if self[environment].empty?
|
78
|
-
self.delete(environment)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
super()
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
end; end
|
data/lib/leap_cli/config/tag.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# A class for node services or node tags.
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
7
|
-
module LeapCli; module Config
|
8
|
-
|
9
|
-
class Tag < Object
|
10
|
-
attr_reader :node_list
|
11
|
-
|
12
|
-
def initialize(environment=nil)
|
13
|
-
super(environment)
|
14
|
-
@node_list = Config::ObjectList.new
|
15
|
-
end
|
16
|
-
|
17
|
-
# don't copy the node list pointer when this object is dup'ed.
|
18
|
-
def initialize_copy(orig)
|
19
|
-
super
|
20
|
-
@node_list = Config::ObjectList.new
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
end; end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Capistrano
|
2
|
-
class Configuration
|
3
|
-
module Connections
|
4
|
-
def failed!(server)
|
5
|
-
@failure_callback.call(server) if @failure_callback
|
6
|
-
Thread.current[:failed_sessions] << server
|
7
|
-
end
|
8
|
-
|
9
|
-
def call_on_failure(&block)
|
10
|
-
@failure_callback = block
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
|
data/lib/leap_cli/logger.rb
DELETED
@@ -1,237 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# A drop in replacement for Capistrano::Logger that integrates better with LEAP CLI.
|
3
|
-
#
|
4
|
-
|
5
|
-
require 'capistrano/logger'
|
6
|
-
|
7
|
-
#
|
8
|
-
# from Capistrano::Logger
|
9
|
-
# =========================
|
10
|
-
#
|
11
|
-
# IMPORTANT = 0
|
12
|
-
# INFO = 1
|
13
|
-
# DEBUG = 2
|
14
|
-
# TRACE = 3
|
15
|
-
# MAX_LEVEL = 3
|
16
|
-
# COLORS = {
|
17
|
-
# :none => "0",
|
18
|
-
# :black => "30",
|
19
|
-
# :red => "31",
|
20
|
-
# :green => "32",
|
21
|
-
# :yellow => "33",
|
22
|
-
# :blue => "34",
|
23
|
-
# :magenta => "35",
|
24
|
-
# :cyan => "36",
|
25
|
-
# :white => "37"
|
26
|
-
# }
|
27
|
-
# STYLES = {
|
28
|
-
# :bright => 1,
|
29
|
-
# :dim => 2,
|
30
|
-
# :underscore => 4,
|
31
|
-
# :blink => 5,
|
32
|
-
# :reverse => 7,
|
33
|
-
# :hidden => 8
|
34
|
-
# }
|
35
|
-
#
|
36
|
-
|
37
|
-
module LeapCli
|
38
|
-
class Logger < Capistrano::Logger
|
39
|
-
|
40
|
-
def initialize(options={})
|
41
|
-
@options = options
|
42
|
-
@level = options[:level] || 0
|
43
|
-
@message_buffer = nil
|
44
|
-
end
|
45
|
-
|
46
|
-
def log(level, message, line_prefix=nil, options={})
|
47
|
-
if message !~ /\n$/ && level <= 2 && line_prefix.is_a?(String)
|
48
|
-
# in some cases, when the message doesn't end with a return, we buffer it and
|
49
|
-
# wait until we encounter the return before we log the message out.
|
50
|
-
@message_buffer ||= ""
|
51
|
-
@message_buffer += message
|
52
|
-
return
|
53
|
-
elsif @message_buffer
|
54
|
-
message = @message_buffer + message
|
55
|
-
@message_buffer = nil
|
56
|
-
end
|
57
|
-
|
58
|
-
options[:level] ||= level
|
59
|
-
[:stdout, :log].each do |mode|
|
60
|
-
LeapCli::log_raw(mode) do
|
61
|
-
message_lines(mode, message, line_prefix, options)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def message_lines(mode, message, line_prefix, options)
|
69
|
-
formatted_message, formatted_prefix, message_options = apply_formatting(mode, message, line_prefix, options)
|
70
|
-
if message_options[:level] <= self.level && formatted_message && formatted_message.chars.any?
|
71
|
-
if formatted_prefix
|
72
|
-
formatted_message.lines.collect { |line|
|
73
|
-
"[#{formatted_prefix}] #{line.sub(/\s+$/, '')}"
|
74
|
-
}
|
75
|
-
else
|
76
|
-
formatted_message.lines.collect {|line| line.sub(/\s+$/, '')}
|
77
|
-
end
|
78
|
-
else
|
79
|
-
nil
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
##
|
84
|
-
## FORMATTING
|
85
|
-
##
|
86
|
-
|
87
|
-
#
|
88
|
-
# options for formatters:
|
89
|
-
#
|
90
|
-
# :match => regexp for matching a log line
|
91
|
-
# :color => what color the line should be
|
92
|
-
# :style => what style the line should be
|
93
|
-
# :priority => what order the formatters are applied in. higher numbers first.
|
94
|
-
# :match_level => only apply filter at the specified log level
|
95
|
-
# :level => make this line visible at this log level or higher
|
96
|
-
# :replace => replace the matched text
|
97
|
-
# :exit => force the exit code to be this (does not interrupt program, just
|
98
|
-
# ensures a specific exit code when the program eventually exits)
|
99
|
-
#
|
100
|
-
@formatters = [
|
101
|
-
# TRACE
|
102
|
-
{ :match => /command finished/, :color => :white, :style => :dim, :match_level => 3, :priority => -10 },
|
103
|
-
{ :match => /executing locally/, :color => :yellow, :match_level => 3, :priority => -20 },
|
104
|
-
|
105
|
-
# DEBUG
|
106
|
-
#{ :match => /executing .*/, :color => :green, :match_level => 2, :priority => -10, :timestamp => true },
|
107
|
-
#{ :match => /.*/, :color => :yellow, :match_level => 2, :priority => -30 },
|
108
|
-
{ :match => /^transaction:/, :level => 3 },
|
109
|
-
|
110
|
-
# INFO
|
111
|
-
{ :match => /.*out\] (fatal:|ERROR:).*/, :color => :red, :match_level => 1, :priority => -10 },
|
112
|
-
{ :match => /Permission denied/, :color => :red, :match_level => 1, :priority => -20 },
|
113
|
-
{ :match => /sh: .+: command not found/, :color => :magenta, :match_level => 1, :priority => -30 },
|
114
|
-
|
115
|
-
# IMPORTANT
|
116
|
-
{ :match => /^(E|e)rr ::/, :color => :red, :match_level => 0, :priority => -10, :exit => 1},
|
117
|
-
{ :match => /^ERROR:/, :color => :red, :priority => -10, :exit => 1},
|
118
|
-
{ :match => /.*/, :color => :blue, :match_level => 0, :priority => -20 },
|
119
|
-
|
120
|
-
# CLEANUP
|
121
|
-
{ :match => /\s+$/, :replace => '', :priority => 0},
|
122
|
-
|
123
|
-
# DEBIAN PACKAGES
|
124
|
-
{ :match => /^(Hit|Ign) /, :color => :green, :priority => -20},
|
125
|
-
{ :match => /^Err /, :color => :red, :priority => -20},
|
126
|
-
{ :match => /^W(ARNING)?: /, :color => :yellow, :priority => -20},
|
127
|
-
{ :match => /^E: /, :color => :red, :priority => -20},
|
128
|
-
{ :match => /already the newest version/, :color => :green, :priority => -20},
|
129
|
-
{ :match => /WARNING: The following packages cannot be authenticated!/, :color => :red, :level => 0, :priority => -10},
|
130
|
-
|
131
|
-
# PUPPET
|
132
|
-
{ :match => /^(W|w)arning: Not collecting exported resources without storeconfigs/, :level => 2, :color => :yellow, :priority => -10},
|
133
|
-
{ :match => /^(W|w)arning: Found multiple default providers for vcsrepo:/, :level => 2, :color => :yellow, :priority => -10},
|
134
|
-
{ :match => /^(W|w)arning: .*is deprecated.*$/, :level => 2, :color => :yellow, :priority => -10},
|
135
|
-
{ :match => /^(W|w)arning: Scope.*$/, :level => 2, :color => :yellow, :priority => -10},
|
136
|
-
{ :match => /^(N|n)otice:/, :level => 1, :color => :cyan, :priority => -20},
|
137
|
-
{ :match => /^(N|n)otice:.*executed successfully$/, :level => 2, :color => :cyan, :priority => -15},
|
138
|
-
{ :match => /^(W|w)arning:/, :level => 0, :color => :yellow, :priority => -20},
|
139
|
-
{ :match => /^Duplicate declaration:/, :level => 0, :color => :red, :priority => -20},
|
140
|
-
{ :match => /Finished catalog run/, :level => 0, :color => :green, :priority => -10},
|
141
|
-
{ :match => /^APPLY COMPLETE \(changes made\)/, :level => 0, :color => :green, :priority => -10},
|
142
|
-
{ :match => /^APPLY COMPLETE \(no changes\)/, :level => 0, :color => :green, :priority => -10},
|
143
|
-
|
144
|
-
# PUPPET FATAL ERRORS
|
145
|
-
{ :match => /^(E|e)rr(or|):/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
146
|
-
{ :match => /^Wrapped exception:/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
147
|
-
{ :match => /^Failed to parse template/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
148
|
-
{ :match => /^Execution of.*returned/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
149
|
-
{ :match => /^Parameter matches failed:/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
150
|
-
{ :match => /^Syntax error/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
151
|
-
{ :match => /^Cannot reassign variable/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
152
|
-
{ :match => /^Could not find template/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
153
|
-
{ :match => /^APPLY COMPLETE.*fail/, :level => 0, :color => :red, :priority => -1, :exit => 1},
|
154
|
-
|
155
|
-
# TESTS
|
156
|
-
{ :match => /^PASS: /, :color => :green, :priority => -20},
|
157
|
-
{ :match => /^(FAIL|ERROR): /, :color => :red, :priority => -20},
|
158
|
-
{ :match => /^(SKIP|WARN): /, :color => :yellow, :priority => -20},
|
159
|
-
{ :match => /\d+ tests: \d+ passes, \d+ skips, 0 warnings, 0 failures, 0 errors/, :color => :blue, :priority => -20},
|
160
|
-
|
161
|
-
# LOG SUPPRESSION
|
162
|
-
{ :match => /^(W|w)arning: You cannot collect without storeconfigs being set/, :level => 2, :priority => 10},
|
163
|
-
{ :match => /^(W|w)arning: You cannot collect exported resources without storeconfigs being set/, :level => 2, :priority => 10}
|
164
|
-
]
|
165
|
-
|
166
|
-
def self.sorted_formatters
|
167
|
-
# Sort matchers in reverse order so we can break if we found a match.
|
168
|
-
@sorted_formatters ||= @formatters.sort_by { |i| -(i[:priority] || i[:prio] || 0) }
|
169
|
-
end
|
170
|
-
|
171
|
-
@prefix_formatters = [
|
172
|
-
{ :match => /(err|out) :: /, :replace => '', :priority => 0},
|
173
|
-
{ :match => /\s+$/, :replace => '', :priority => 0}
|
174
|
-
]
|
175
|
-
def self.prefix_formatters; @prefix_formatters; end
|
176
|
-
|
177
|
-
def apply_formatting(mode, message, line_prefix = nil, options={})
|
178
|
-
message = message.dup
|
179
|
-
options = options.dup
|
180
|
-
if !line_prefix.nil?
|
181
|
-
if !line_prefix.is_a?(String)
|
182
|
-
line_prefix = line_prefix.to_s.dup
|
183
|
-
else
|
184
|
-
line_prefix = line_prefix.dup
|
185
|
-
end
|
186
|
-
end
|
187
|
-
color = options[:color] || :none
|
188
|
-
style = options[:style]
|
189
|
-
|
190
|
-
if line_prefix
|
191
|
-
self.class.prefix_formatters.each do |formatter|
|
192
|
-
if line_prefix =~ formatter[:match] && formatter[:replace]
|
193
|
-
line_prefix.gsub!(formatter[:match], formatter[:replace])
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
self.class.sorted_formatters.each do |formatter|
|
199
|
-
if (formatter[:match_level] == level || formatter[:match_level].nil?)
|
200
|
-
if message =~ formatter[:match]
|
201
|
-
options[:level] = formatter[:level] if formatter[:level]
|
202
|
-
color = formatter[:color] if formatter[:color]
|
203
|
-
style = formatter[:style] || formatter[:attribute] # (support original cap colors)
|
204
|
-
|
205
|
-
message.gsub!(formatter[:match], formatter[:replace]) if formatter[:replace]
|
206
|
-
message.replace(formatter[:prepend] + message) unless formatter[:prepend].nil?
|
207
|
-
message.replace(message + formatter[:append]) unless formatter[:append].nil?
|
208
|
-
message.replace(Time.now.strftime('%Y-%m-%d %T') + ' ' + message) if formatter[:timestamp]
|
209
|
-
|
210
|
-
if formatter[:exit]
|
211
|
-
LeapCli::Util.exit_status(formatter[:exit])
|
212
|
-
end
|
213
|
-
|
214
|
-
# stop formatting, unless formatter was just for string replacement
|
215
|
-
break unless formatter[:replace]
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
if color == :hide
|
221
|
-
return nil
|
222
|
-
elsif mode == :log || (color == :none && style.nil?) || !LeapCli.log_in_color
|
223
|
-
return [message, line_prefix, options]
|
224
|
-
else
|
225
|
-
term_color = COLORS[color]
|
226
|
-
term_style = STYLES[style]
|
227
|
-
if line_prefix.nil?
|
228
|
-
message.replace format(message, term_color, term_style)
|
229
|
-
else
|
230
|
-
line_prefix.replace format(line_prefix, term_color, term_style).strip # format() appends a \n
|
231
|
-
end
|
232
|
-
return [message, line_prefix, options]
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|
237
|
-
end
|