chef-core 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef_core/cliux/ui/error_printer.rb +14 -12
- data/lib/chef_core/cliux/ui/plain_text_element.rb +1 -2
- data/lib/chef_core/cliux/ui/plain_text_header.rb +1 -1
- data/lib/chef_core/cliux/ui/terminal.rb +4 -4
- data/lib/chef_core/error.rb +0 -1
- data/lib/chef_core/file_fetcher.rb +1 -1
- data/lib/chef_core/target_host.rb +16 -11
- data/lib/chef_core/target_host/linux.rb +1 -1
- data/lib/chef_core/target_resolver.rb +5 -3
- data/lib/chef_core/telemeter.rb +12 -7
- data/lib/chef_core/telemeter/patch.rb +0 -7
- data/lib/chef_core/telemeter/sender.rb +5 -5
- data/lib/chef_core/text.rb +1 -0
- data/lib/chef_core/text/error_translation.rb +7 -4
- data/lib/chef_core/text/text_wrapper.rb +2 -1
- data/lib/chef_core/version.rb +1 -1
- metadata +5 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3304fd223814fd03889847edc6b0b44bb20e0218d126d37c8c68e2df2bed3290
|
4
|
+
data.tar.gz: d818f9f5683018d5578d46244926fb8bd3cabafdbfe11521916c51b123674469
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b4b4a9ab4c31d096a57d3309663f3d5fb2800b3e2696314800fad001fe0c7b090192b7e8a4276068722037be53857f35cd8dcc89a7c53e7cad850a6b2a6eddb
|
7
|
+
data.tar.gz: 44ed3054f724b189822237081f1b717c8cc85ae32fb547f305cfcb4b9f395736f51d587269e7e1cd1cbe1263d891c662e1c55063bad225525dba3fc344f77c1d
|
@@ -59,7 +59,7 @@ module ChefCore
|
|
59
59
|
e.jobs.each do |j|
|
60
60
|
wrapped = ChefCore::Errors::StandardErrorResolver.wrap_exception(j.exception, j.target_host)
|
61
61
|
ep = ErrorPrinter.new(wrapper: wrapped, config: config)
|
62
|
-
msg = ep.format_body
|
62
|
+
msg = ep.format_body.tr("\n", " ").gsub(/ {2,}/, " ").chomp.strip
|
63
63
|
out.write("Host: #{j.target_host.hostname} ")
|
64
64
|
if ep.exception.respond_to? :id
|
65
65
|
out.write("Error: #{ep.exception.id}: ")
|
@@ -100,7 +100,7 @@ module ChefCore
|
|
100
100
|
@pastel = Pastel.new
|
101
101
|
@content = StringIO.new
|
102
102
|
@config = config
|
103
|
-
@id = if @exception.
|
103
|
+
@id = if @exception.is_a? ChefCore::Error
|
104
104
|
@exception.id
|
105
105
|
else
|
106
106
|
DEFAULT_ERROR_NO
|
@@ -122,7 +122,7 @@ module ChefCore
|
|
122
122
|
|
123
123
|
def format_undecorated
|
124
124
|
@content << "\n"
|
125
|
-
@content << format_body
|
125
|
+
@content << format_body
|
126
126
|
if @command
|
127
127
|
@content << "\n"
|
128
128
|
@content << @command.usage
|
@@ -131,11 +131,11 @@ module ChefCore
|
|
131
131
|
|
132
132
|
def format_decorated
|
133
133
|
@content << "\n"
|
134
|
-
@content << format_header
|
134
|
+
@content << format_header
|
135
135
|
@content << "\n\n"
|
136
|
-
@content << format_body
|
136
|
+
@content << format_body
|
137
137
|
@content << "\n"
|
138
|
-
@content << format_footer
|
138
|
+
@content << format_footer
|
139
139
|
@content << "\n"
|
140
140
|
end
|
141
141
|
|
@@ -144,9 +144,9 @@ module ChefCore
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def format_body
|
147
|
-
if exception.
|
147
|
+
if exception.is_a? ChefCore::Error
|
148
148
|
format_workstation_exception
|
149
|
-
elsif exception.
|
149
|
+
elsif exception.is_a? Train::Error
|
150
150
|
format_train_exception
|
151
151
|
else
|
152
152
|
format_other_exception
|
@@ -172,7 +172,7 @@ module ChefCore
|
|
172
172
|
def add_backtrace_header(out, args)
|
173
173
|
out.write("\n#{"-" * 80}\n")
|
174
174
|
out.print("#{Time.now}: Error encountered while running the following:\n")
|
175
|
-
out.print(" #{args.join(
|
175
|
+
out.print(" #{args.join(" ")}\n")
|
176
176
|
out.print("Backtrace:\n")
|
177
177
|
end
|
178
178
|
|
@@ -183,10 +183,10 @@ module ChefCore
|
|
183
183
|
end
|
184
184
|
|
185
185
|
def self.error_summary(e)
|
186
|
-
if e.
|
186
|
+
if e.is_a? ChefCore::Error
|
187
187
|
# By convention, all of our defined messages have a short summary on the first line.
|
188
188
|
ChefCore::Text.errors.send(e.id).text(*e.params).split("\n").first
|
189
|
-
elsif e.
|
189
|
+
elsif e.is_a? String
|
190
190
|
e
|
191
191
|
else
|
192
192
|
if e.respond_to? :message
|
@@ -205,7 +205,7 @@ module ChefCore
|
|
205
205
|
# TODO this gets moved to trainerrormapper or simply removed since
|
206
206
|
# many of these issues are now handled in the RemoteTarget::ConnectionFailure
|
207
207
|
def format_train_exception
|
208
|
-
backend, host = formatted_host
|
208
|
+
backend, host = formatted_host
|
209
209
|
if host.nil?
|
210
210
|
t.CHEFTRN002.text(exception.message)
|
211
211
|
else
|
@@ -219,6 +219,7 @@ module ChefCore
|
|
219
219
|
|
220
220
|
def formatted_host
|
221
221
|
return nil if target_host.nil?
|
222
|
+
|
222
223
|
cfg = target_host.config
|
223
224
|
port = cfg[:port].nil? ? "" : ":#{cfg[:port]}"
|
224
225
|
user = cfg[:user].nil? ? "" : "#{cfg[:user]}@"
|
@@ -255,6 +256,7 @@ module ChefCore
|
|
255
256
|
i = 1
|
256
257
|
while i <= backtrace1.size && i <= backtrace2.size
|
257
258
|
break if backtrace1[-i] != backtrace2[-i]
|
259
|
+
|
258
260
|
i += 1
|
259
261
|
end
|
260
262
|
backtrace1[0..-i]
|
@@ -53,9 +53,9 @@ module ChefCore
|
|
53
53
|
# keys :top :middle and :bottom can contain Strings that are used to
|
54
54
|
# indent the spinners. Ignored if message is blank
|
55
55
|
multispinner = get_multispinner.new("[:spinner] #{header}",
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
output: @location,
|
57
|
+
hide_cursor: true,
|
58
|
+
style: indent_style)
|
59
59
|
jobs.each do |job|
|
60
60
|
multispinner.register(spinner_prefix(job.prefix), hide_cursor: true) do |spinner|
|
61
61
|
reporter = StatusReporter.new(spinner, prefix: job.prefix, key: :status)
|
@@ -94,7 +94,7 @@ module ChefCore
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def show_cursor
|
97
|
-
TTY::Cursor.show
|
97
|
+
TTY::Cursor.show
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
data/lib/chef_core/error.rb
CHANGED
@@ -25,7 +25,7 @@ module ChefCore
|
|
25
25
|
# These values may exist in .ssh/config but will be ignored by train
|
26
26
|
# in favor of its defaults unless we specify them explicitly.
|
27
27
|
# See #apply_ssh_config
|
28
|
-
SSH_CONFIG_OVERRIDE_KEYS =
|
28
|
+
SSH_CONFIG_OVERRIDE_KEYS = %i{user port proxy}.freeze
|
29
29
|
|
30
30
|
# We're borrowing a page from train here - because setting up a
|
31
31
|
# reliable connection for testing is a multi-step process,
|
@@ -34,7 +34,7 @@ module ChefCore
|
|
34
34
|
# OS, this instance will mix-in the supporting methods for the given platform;
|
35
35
|
# otherwise those methods will raise NotImplementedError.
|
36
36
|
def self.mock_instance(url, family: "unknown", name: "unknown",
|
37
|
-
|
37
|
+
release: "unknown", arch: "x86_64")
|
38
38
|
# Specifying sudo: false ensures that attempted operations
|
39
39
|
# don't fail because the mock platform doesn't support sudo
|
40
40
|
target_host = TargetHost.new(url, { sudo: false })
|
@@ -92,7 +92,7 @@ module ChefCore
|
|
92
92
|
|
93
93
|
# From WinRM gem: It is recommended that you :disable_sspi => true if you are using the plaintext or ssl transport.
|
94
94
|
# See note here: https://github.com/mwrock/WinRM#example
|
95
|
-
if
|
95
|
+
if %w{ssl plaintext}.include?(target_opts[:winrm_transport])
|
96
96
|
target_opts[:winrm_disable_sspi] = true
|
97
97
|
end
|
98
98
|
|
@@ -128,6 +128,7 @@ module ChefCore
|
|
128
128
|
def connect!
|
129
129
|
# Keep existing connections
|
130
130
|
return unless @backend.nil?
|
131
|
+
|
131
132
|
@backend = train_connection.connection
|
132
133
|
@backend.wait_until_ready
|
133
134
|
|
@@ -159,6 +160,7 @@ module ChefCore
|
|
159
160
|
# Returns the user being used to connect. Defaults to train's default user if not specified
|
160
161
|
def user
|
161
162
|
return config[:user] unless config[:user].nil?
|
163
|
+
|
162
164
|
require "train/transports/ssh"
|
163
165
|
# TODO - this should use the right transport, not default to SSH
|
164
166
|
Train::Transports::SSH.default_options[:user][:default]
|
@@ -196,6 +198,7 @@ module ChefCore
|
|
196
198
|
if result.exit_status != 0
|
197
199
|
raise RemoteExecutionFailed.new(@config[:host], command, result)
|
198
200
|
end
|
201
|
+
|
199
202
|
result
|
200
203
|
end
|
201
204
|
|
@@ -205,13 +208,13 @@ module ChefCore
|
|
205
208
|
|
206
209
|
# TODO spec
|
207
210
|
def save_as_remote_file(content, remote_path)
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
211
|
+
t = Tempfile.new("chef-content")
|
212
|
+
t << content
|
213
|
+
t.close
|
214
|
+
upload_file(t.path, remote_path)
|
212
215
|
ensure
|
213
|
-
|
214
|
-
|
216
|
+
t.close
|
217
|
+
t.unlink
|
215
218
|
end
|
216
219
|
|
217
220
|
def upload_file(local_path, remote_path)
|
@@ -234,9 +237,10 @@ module ChefCore
|
|
234
237
|
# be found.
|
235
238
|
def installed_chef_version
|
236
239
|
return @installed_chef_version if @installed_chef_version
|
240
|
+
|
237
241
|
# Note: In the case of a very old version of chef (that has no manifest - pre 12.0?)
|
238
242
|
# this will report as not installed.
|
239
|
-
manifest = read_chef_version_manifest
|
243
|
+
manifest = read_chef_version_manifest
|
240
244
|
|
241
245
|
# We split the version here because unstable builds install from)
|
242
246
|
# are in the form "Major.Minor.Build+HASH" which is not a valid
|
@@ -247,6 +251,7 @@ module ChefCore
|
|
247
251
|
def read_chef_version_manifest
|
248
252
|
manifest = fetch_file_contents(omnibus_manifest_path)
|
249
253
|
raise ChefNotInstalled.new if manifest.nil?
|
254
|
+
|
250
255
|
JSON.parse(manifest)
|
251
256
|
end
|
252
257
|
|
@@ -258,7 +263,7 @@ module ChefCore
|
|
258
263
|
#
|
259
264
|
# The base temp dir is cached and will only be created once per connection lifetime.
|
260
265
|
def temp_dir
|
261
|
-
dir = make_temp_dir
|
266
|
+
dir = make_temp_dir
|
262
267
|
chown(dir, user)
|
263
268
|
dir
|
264
269
|
end
|
@@ -28,7 +28,7 @@ module ChefCore
|
|
28
28
|
# Use resolver_inst.targets to get the expanded list of TargetHost instances.
|
29
29
|
class TargetResolver
|
30
30
|
MAX_EXPANDED_TARGETS = 24
|
31
|
-
SUPPORTED_PROTOCOLS = %w{winrm ssh}
|
31
|
+
SUPPORTED_PROTOCOLS = %w{winrm ssh}.freeze
|
32
32
|
def initialize(target, default_protocol, conn_options, max_expanded_targets: MAX_EXPANDED_TARGETS)
|
33
33
|
@max_expanded_targets = max_expanded_targets
|
34
34
|
@default_proto = default_protocol
|
@@ -42,6 +42,7 @@ module ChefCore
|
|
42
42
|
# Returns the list of targets as an array of TargetHost instances
|
43
43
|
def targets
|
44
44
|
return @targets unless @targets.nil?
|
45
|
+
|
45
46
|
expanded_urls = []
|
46
47
|
@split_targets.each do |target|
|
47
48
|
expand_targets(target).each { |t| expanded_urls << t }
|
@@ -100,7 +101,7 @@ module ChefCore
|
|
100
101
|
end
|
101
102
|
|
102
103
|
def prefix_from_target(target)
|
103
|
-
if target =~
|
104
|
+
if target =~ %r{^(.+?)://(.*)}
|
104
105
|
# We'll store the existing prefix to avoid it interfering
|
105
106
|
# with the check further below.
|
106
107
|
if SUPPORTED_PROTOCOLS.include? $1.downcase
|
@@ -131,6 +132,7 @@ module ChefCore
|
|
131
132
|
|
132
133
|
def do_parse(targets, depth = 0)
|
133
134
|
raise TooManyRanges.new(@current_target) if depth > 2
|
135
|
+
|
134
136
|
new_targets = []
|
135
137
|
done = false
|
136
138
|
targets.each do |target|
|
@@ -191,7 +193,7 @@ module ChefCore
|
|
191
193
|
end
|
192
194
|
# Provide an error base for all targetresolver errors, to simplify
|
193
195
|
# handling when caller is not concerned with the specific failure.
|
194
|
-
class TargetResolverError
|
196
|
+
class TargetResolverError < ChefCore::Error; end
|
195
197
|
|
196
198
|
class InvalidRange < TargetResolverError
|
197
199
|
def initialize(unresolved_target, given_range)
|
data/lib/chef_core/telemeter.rb
CHANGED
@@ -70,16 +70,16 @@ module ChefCore
|
|
70
70
|
timed_capture(:run, arguments: arguments, &block)
|
71
71
|
end
|
72
72
|
|
73
|
-
def timed_capture(name, data = {})
|
73
|
+
def timed_capture(name, data = {}, options = {})
|
74
74
|
time = Benchmark.measure { yield }
|
75
75
|
data[:duration] = time.real
|
76
|
-
capture(name, data)
|
76
|
+
capture(name, data, options)
|
77
77
|
end
|
78
78
|
|
79
|
-
def capture(name, data = {})
|
79
|
+
def capture(name, data = {}, options = {})
|
80
80
|
# Adding it to the head of the list will ensure that the
|
81
81
|
# sequence of events is preserved when we send the final payload
|
82
|
-
payload = make_event_payload(name, data)
|
82
|
+
payload = make_event_payload(name, data, options)
|
83
83
|
@events_to_send.unshift payload
|
84
84
|
end
|
85
85
|
|
@@ -91,16 +91,21 @@ module ChefCore
|
|
91
91
|
@events_to_send = []
|
92
92
|
end
|
93
93
|
|
94
|
-
def make_event_payload(name, data)
|
95
|
-
{
|
94
|
+
def make_event_payload(name, data, options)
|
95
|
+
payload = {
|
96
96
|
event: name,
|
97
97
|
properties: {
|
98
98
|
installation_id: installation_id,
|
99
99
|
run_timestamp: run_timestamp,
|
100
100
|
host_platform: host_platform,
|
101
|
-
event_data: data,
|
102
101
|
},
|
103
102
|
}
|
103
|
+
if options[:flatten]
|
104
|
+
payload[:properties].merge! data
|
105
|
+
else
|
106
|
+
payload[:properties][:event_data] = data
|
107
|
+
end
|
108
|
+
payload
|
104
109
|
end
|
105
110
|
|
106
111
|
def installation_id
|
@@ -16,13 +16,6 @@
|
|
16
16
|
#
|
17
17
|
|
18
18
|
class Telemetry
|
19
|
-
class Session
|
20
|
-
# The telemetry session data is normally kept in .chef, which we don't have.
|
21
|
-
def session_file
|
22
|
-
ChefCore::Config.telemetry_session_file.freeze
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
19
|
def deliver(data = {})
|
27
20
|
if ChefCore::Telemeter.instance.enabled?
|
28
21
|
payload = event.prepare(data)
|
@@ -83,12 +83,12 @@ module ChefCore
|
|
83
83
|
FileUtils.rm_rf(config[:session_file])
|
84
84
|
# We'll use the version captured in the sesion file
|
85
85
|
entries = content["entries"]
|
86
|
-
cli_version = content["version"]
|
87
86
|
total = entries.length
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
87
|
+
product_info = config[:product] || {}
|
88
|
+
telemetry = Telemetry.new(product: product_info[:name] || "chef-workstation",
|
89
|
+
origin: product_info[:origin] || "command-line",
|
90
|
+
product_version: product_info[:version] || content["version"],
|
91
|
+
install_context: product_info[:install_context] || "omnibus")
|
92
92
|
total = entries.length
|
93
93
|
entries.each_with_index do |entry, x|
|
94
94
|
submit_entry(telemetry, entry, x + 1, total)
|
data/lib/chef_core/text.rb
CHANGED
@@ -35,6 +35,7 @@ module ChefCore
|
|
35
35
|
|
36
36
|
def self.add_localization(base_path)
|
37
37
|
return if @raw_localization_paths.include? base_path
|
38
|
+
|
38
39
|
# @localization_paths will get modified by R18n, so we'll
|
39
40
|
# keep them as strings as well, to ensure we can avoid duplicate loading.
|
40
41
|
errors_path = File.join(base_path, "errors")
|
@@ -20,20 +20,19 @@ module ChefCore
|
|
20
20
|
# Represents an error loaded from translation, with
|
21
21
|
# display attributes set.
|
22
22
|
class ErrorTranslation
|
23
|
-
ATTRIBUTES =
|
23
|
+
ATTRIBUTES = %i{decorations header footer stack log}.freeze
|
24
24
|
attr_reader :message, *ATTRIBUTES
|
25
25
|
|
26
26
|
def initialize(id, params: [])
|
27
27
|
error_translation = error_translation_for_id(id)
|
28
28
|
|
29
|
-
options = YAML.load(Text.errors.display_defaults, "display_defaults"
|
30
|
-
symbolize_names: true)
|
29
|
+
options = _sym(YAML.load(Text.errors.display_defaults, "display_defaults"))
|
31
30
|
|
32
31
|
# Display metadata is a string containing a YAML hash that is optionally under
|
33
32
|
# the error's 'options' attribute
|
34
33
|
# Note that we couldn't use :display, as that conflicts with a method on Object.
|
35
34
|
display_opts = if error_translation.methods.include?(:options)
|
36
|
-
YAML.load(error_translation.options, @id
|
35
|
+
_sym(YAML.load(error_translation.options, @id))
|
37
36
|
else
|
38
37
|
{}
|
39
38
|
end
|
@@ -53,6 +52,10 @@ module ChefCore
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
55
|
+
def _sym hash
|
56
|
+
hash.map { |k,v| [k.to_sym, v] }.to_h
|
57
|
+
end
|
58
|
+
|
56
59
|
def inspect
|
57
60
|
inspection = "#{self}: "
|
58
61
|
ATTRIBUTES.each do |attribute|
|
@@ -32,6 +32,7 @@ module ChefCore
|
|
32
32
|
if k.class == Integer
|
33
33
|
raise MissingPlural.new(@tree.instance_variable_get(:@path), k)
|
34
34
|
end
|
35
|
+
|
35
36
|
k = k.to_sym
|
36
37
|
define_singleton_method k do |*args|
|
37
38
|
subtree = @tree.send(k, *args)
|
@@ -56,7 +57,7 @@ module ChefCore
|
|
56
57
|
def set_call_context
|
57
58
|
# TODO - this can vary (8 isn't always right) - inspect
|
58
59
|
@line = caller(8, 1).first
|
59
|
-
if @line =~
|
60
|
+
if @line =~ %r{.*/lib/(.*\.rb):(\d+)}
|
60
61
|
@line = "File: #{$1} Line: #{$2}"
|
61
62
|
end
|
62
63
|
end
|
data/lib/chef_core/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software, Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pastel
|
@@ -297,17 +297,16 @@ require_paths:
|
|
297
297
|
- lib
|
298
298
|
required_ruby_version: !ruby/object:Gem::Requirement
|
299
299
|
requirements:
|
300
|
-
- - "
|
300
|
+
- - "~>"
|
301
301
|
- !ruby/object:Gem::Version
|
302
|
-
version: 2.
|
302
|
+
version: 2.4.0
|
303
303
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
304
304
|
requirements:
|
305
305
|
- - ">="
|
306
306
|
- !ruby/object:Gem::Version
|
307
307
|
version: '0'
|
308
308
|
requirements: []
|
309
|
-
|
310
|
-
rubygems_version: 2.7.6
|
309
|
+
rubygems_version: 3.0.3
|
311
310
|
signing_key:
|
312
311
|
specification_version: 4
|
313
312
|
summary: Composable common actions for assembling Chef workflows
|