chef-core 0.0.3 → 0.0.5
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/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
|