leap_cli 1.8.1 → 1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|