wavefront-cli 8.5.1 → 10.0.0
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/.github/workflows/release.yml +4 -4
- data/.github/workflows/test.yml +2 -2
- data/.rubocop.yml +1 -4
- data/Gemfile +10 -0
- data/HISTORY.md +17 -0
- data/README.md +4 -2
- data/lib/wavefront-cli/base.rb +4 -4
- data/lib/wavefront-cli/commands/base.rb +13 -10
- data/lib/wavefront-cli/commands/config.rb +3 -7
- data/lib/wavefront-cli/commands/derivedmetric.rb +1 -1
- data/lib/wavefront-cli/commands/metric.rb +3 -3
- data/lib/wavefront-cli/commands/metricspolicy.rb +33 -0
- data/lib/wavefront-cli/commands/query.rb +5 -5
- data/lib/wavefront-cli/commands/write.rb +12 -12
- data/lib/wavefront-cli/config.rb +31 -35
- data/lib/wavefront-cli/constants.rb +3 -2
- data/lib/wavefront-cli/controller.rb +19 -15
- data/lib/wavefront-cli/display/base.rb +2 -2
- data/lib/wavefront-cli/display/cluster.rb +21 -0
- data/lib/wavefront-cli/display/metricspolicy.rb +15 -0
- data/lib/wavefront-cli/display/printer/long.rb +11 -17
- data/lib/wavefront-cli/display/printer/sparkline.rb +3 -3
- data/lib/wavefront-cli/display/query.rb +1 -1
- data/lib/wavefront-cli/display/write.rb +2 -1
- data/lib/wavefront-cli/event.rb +2 -2
- data/lib/wavefront-cli/exception_handler.rb +8 -1
- data/lib/wavefront-cli/helpers/load_file.rb +2 -2
- data/lib/wavefront-cli/maintenancewindow.rb +1 -1
- data/lib/wavefront-cli/metricspolicy.rb +42 -0
- data/lib/wavefront-cli/opt_handler.rb +2 -3
- data/lib/wavefront-cli/output/csv/query.rb +3 -3
- data/lib/wavefront-cli/output/hcl/base.rb +4 -4
- data/lib/wavefront-cli/output/hcl/dashboard.rb +7 -7
- data/lib/wavefront-cli/output/hcl/stdlib/array.rb +1 -1
- data/lib/wavefront-cli/output/wavefront/query.rb +7 -7
- data/lib/wavefront-cli/stdlib/array.rb +1 -1
- data/lib/wavefront-cli/stdlib/string.rb +5 -5
- data/lib/wavefront-cli/usage.rb +1 -1
- data/lib/wavefront-cli/version.rb +1 -1
- data/lib/wavefront-cli/write.rb +15 -19
- data/spec/constants.rb +5 -6
- data/spec/support/command_base.rb +13 -1
- data/spec/support/minitest_assertions.rb +14 -10
- data/spec/support/output_tester.rb +2 -2
- data/spec/support/supported_commands.rb +3 -1
- data/spec/test_mixins/import.rb +2 -2
- data/spec/test_mixins/search.rb +9 -7
- data/spec/test_mixins/set.rb +1 -1
- data/spec/wavefront-cli/account_spec.rb +6 -4
- data/spec/wavefront-cli/alert_spec.rb +29 -6
- data/spec/wavefront-cli/base_spec.rb +1 -1
- data/spec/wavefront-cli/commands/base_spec.rb +3 -3
- data/spec/wavefront-cli/commands/config_spec.rb +6 -6
- data/spec/wavefront-cli/config_spec.rb +84 -44
- data/spec/wavefront-cli/controller_spec.rb +4 -2
- data/spec/wavefront-cli/dashboard_spec.rb +1 -1
- data/spec/wavefront-cli/derivedmetric_spec.rb +9 -7
- data/spec/wavefront-cli/display/base_spec.rb +1 -1
- data/spec/wavefront-cli/display/printer/long_spec.rb +6 -4
- data/spec/wavefront-cli/display/printer/terse_spec.rb +2 -2
- data/spec/wavefront-cli/event_spec.rb +14 -11
- data/spec/wavefront-cli/event_store_spec.rb +17 -13
- data/spec/wavefront-cli/externallink_spec.rb +5 -3
- data/spec/wavefront-cli/maintenancewindow_spec.rb +25 -19
- data/spec/wavefront-cli/message_spec.rb +3 -3
- data/spec/wavefront-cli/metricspolicy_spec.rb +30 -0
- data/spec/wavefront-cli/opt_handler_spec.rb +2 -2
- data/spec/wavefront-cli/output/csv/query_spec.rb +1 -1
- data/spec/wavefront-cli/output/csv_spec.rb +1 -1
- data/spec/wavefront-cli/output/hcl_spec.rb +1 -1
- data/spec/wavefront-cli/output/helpers.rb +1 -1
- data/spec/wavefront-cli/output/json_spec.rb +1 -1
- data/spec/wavefront-cli/output/ruby_spec.rb +1 -1
- data/spec/wavefront-cli/output/wavefront/query_spec.rb +1 -1
- data/spec/wavefront-cli/output/wavefront_spec.rb +1 -1
- data/spec/wavefront-cli/output/yaml_spec.rb +1 -1
- data/spec/wavefront-cli/proxy_spec.rb +1 -1
- data/spec/wavefront-cli/query_spec.rb +2 -2
- data/spec/wavefront-cli/role_spec.rb +4 -3
- data/spec/wavefront-cli/serviceaccount_spec.rb +7 -5
- data/spec/wavefront-cli/stdlib/array_spec.rb +1 -1
- data/spec/wavefront-cli/stdlib/string_spec.rb +4 -2
- data/spec/wavefront-cli/usage_spec.rb +2 -2
- data/spec/wavefront-cli/{write_spec.rb → write_class_spec.rb} +2 -15
- data/wavefront-cli.gemspec +4 -16
- metadata +17 -259
- data/spec/spec_helper.rb +0 -113
@@ -45,8 +45,8 @@ module WavefrontDisplay
|
|
45
45
|
run_list
|
46
46
|
elsif method == 'do_search'
|
47
47
|
run_search
|
48
|
-
elsif respond_to?("#{method}_brief") && !options[:long]
|
49
|
-
send("#{method}_brief")
|
48
|
+
elsif respond_to?(:"#{method}_brief") && !options[:long]
|
49
|
+
send(:"#{method}_brief")
|
50
50
|
elsif respond_to?(method)
|
51
51
|
send(method)
|
52
52
|
else
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module WavefrontDisplay
|
6
|
+
#
|
7
|
+
# Format human-readable output for config commands.
|
8
|
+
#
|
9
|
+
class Cluster < Base
|
10
|
+
def do_location
|
11
|
+
puts data
|
12
|
+
end
|
13
|
+
alias do_profiles do_location
|
14
|
+
alias do_show do_location
|
15
|
+
alias do_envvars do_location
|
16
|
+
|
17
|
+
def do_about
|
18
|
+
long_output
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module WavefrontDisplay
|
6
|
+
#
|
7
|
+
# Format human-readable output of the metrics policy.
|
8
|
+
#
|
9
|
+
class MetricsPolicy < Base
|
10
|
+
def do_history
|
11
|
+
readable_time_arr(:updateTime)
|
12
|
+
long_output
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -77,17 +77,15 @@ module WavefrontDisplayPrinter
|
|
77
77
|
#
|
78
78
|
# Make an array of hashes: { key, value, depth }
|
79
79
|
#
|
80
|
-
# rubocop:disable Style/CaseLikeIf
|
81
80
|
def make_list(data, aggr = [], depth = 0, last_key = nil)
|
82
81
|
if data.is_a?(Hash)
|
83
82
|
append_hash(data, aggr, depth)
|
84
83
|
elsif data.is_a?(Array)
|
85
84
|
append_array(data, aggr, depth, last_key)
|
86
85
|
else
|
87
|
-
aggr
|
86
|
+
aggr << ['', preened_value(data), depth]
|
88
87
|
end
|
89
88
|
end
|
90
|
-
# rubocop:enable Style/CaseLikeIf
|
91
89
|
|
92
90
|
def smart_value(val)
|
93
91
|
val.to_s.empty? && opts[:none] ? '<none>' : preened_value(val)
|
@@ -99,16 +97,14 @@ module WavefrontDisplayPrinter
|
|
99
97
|
# @return [Integer]
|
100
98
|
#
|
101
99
|
def longest_key_col(data)
|
102
|
-
data.map { |d| d[0].size + opts[:padding] + opts[:indent] * d[2] }.max
|
100
|
+
data.map { |d| d[0].size + opts[:padding] + (opts[:indent] * d[2]) }.max
|
103
101
|
end
|
104
102
|
|
105
103
|
# Turn the list made by #make_list into user output
|
106
104
|
# @return [String]
|
107
105
|
#
|
108
106
|
def to_s
|
109
|
-
list.map
|
110
|
-
stringify_line(item)
|
111
|
-
end.join("\n")
|
107
|
+
list.map { |item| stringify_line(item) }.join("\n")
|
112
108
|
end
|
113
109
|
|
114
110
|
# @param item [Array] of the form [key, value, indent_level]
|
@@ -154,7 +150,6 @@ module WavefrontDisplayPrinter
|
|
154
150
|
# @param depth [Integer]
|
155
151
|
# @return [Array[Array]]
|
156
152
|
#
|
157
|
-
# rubocop:disable Style/CaseLikeIf
|
158
153
|
def append_hash(data, aggr, depth)
|
159
154
|
data.each_pair do |k, v|
|
160
155
|
if v.is_a?(Hash)
|
@@ -162,13 +157,12 @@ module WavefrontDisplayPrinter
|
|
162
157
|
elsif v.is_a?(Array)
|
163
158
|
aggr = append_array_values(k, v, aggr, depth)
|
164
159
|
else
|
165
|
-
aggr
|
160
|
+
aggr << [k, smart_value(v), depth]
|
166
161
|
end
|
167
162
|
end
|
168
163
|
|
169
164
|
aggr
|
170
165
|
end
|
171
|
-
# rubocop:enable Style/CaseLikeIf
|
172
166
|
|
173
167
|
# Part of the #make_list recursion. Deals with arrays.
|
174
168
|
#
|
@@ -183,7 +177,7 @@ module WavefrontDisplayPrinter
|
|
183
177
|
|
184
178
|
if opts[:separator] && element.is_a?(Hash) && i < data.size &&
|
185
179
|
depth < opts[:sep_depth]
|
186
|
-
aggr
|
180
|
+
aggr << ['', :separator, depth]
|
187
181
|
end
|
188
182
|
end
|
189
183
|
|
@@ -202,9 +196,9 @@ module WavefrontDisplayPrinter
|
|
202
196
|
#
|
203
197
|
def append_hash_values(key, values, aggr, depth)
|
204
198
|
if values.empty? && opts[:none]
|
205
|
-
aggr
|
199
|
+
aggr << [key, '<none>', depth]
|
206
200
|
else
|
207
|
-
aggr
|
201
|
+
aggr << [key, nil, depth]
|
208
202
|
make_list(values, aggr, depth + 1)
|
209
203
|
end
|
210
204
|
end
|
@@ -218,13 +212,13 @@ module WavefrontDisplayPrinter
|
|
218
212
|
#
|
219
213
|
def append_array_values(key, values, aggr, depth)
|
220
214
|
if values.empty? && opts[:none]
|
221
|
-
aggr
|
222
|
-
elsif values.all?
|
215
|
+
aggr << [key, '<none>', depth]
|
216
|
+
elsif values.all?(String)
|
223
217
|
values.sort!
|
224
|
-
aggr
|
218
|
+
aggr << [key, preened_value(values.shift), depth]
|
225
219
|
make_list(values, aggr, depth, key)
|
226
220
|
else
|
227
|
-
aggr
|
221
|
+
aggr << [key, nil, depth]
|
228
222
|
make_list(values, aggr, depth + 1, key)
|
229
223
|
end
|
230
224
|
end
|
@@ -16,7 +16,7 @@ class WavefrontSparkline
|
|
16
16
|
attr_reader :sparkline
|
17
17
|
|
18
18
|
def initialize(series)
|
19
|
-
@sparkline =
|
19
|
+
@sparkline = ">#{generate_sparkline(series)}<"
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [String] the block corresponding to the given value in
|
@@ -38,8 +38,8 @@ class WavefrontSparkline
|
|
38
38
|
def make_fit(vals)
|
39
39
|
return vals if vals.size < SPARK_WIDTH
|
40
40
|
|
41
|
-
vals
|
42
|
-
ret = vals.each_slice(2).with_object([]) { |s, a| a
|
41
|
+
vals << vals.last if vals.size.odd?
|
42
|
+
ret = vals.each_slice(2).with_object([]) { |s, a| a << (s.sum / 2) }
|
43
43
|
make_fit(ret)
|
44
44
|
end
|
45
45
|
|
data/lib/wavefront-cli/event.rb
CHANGED
@@ -38,7 +38,7 @@ module WavefrontCli
|
|
38
38
|
def do_show
|
39
39
|
events = state.list
|
40
40
|
|
41
|
-
if events.
|
41
|
+
if events.empty?
|
42
42
|
puts 'No open events.'
|
43
43
|
else
|
44
44
|
events.sort.reverse_each { |e| puts e.basename }
|
@@ -94,7 +94,7 @@ module WavefrontCli
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def window_start
|
97
|
-
parse_time((options[:start] || Time.now - 600), true)
|
97
|
+
parse_time((options[:start] || (Time.now - 600)), true)
|
98
98
|
end
|
99
99
|
|
100
100
|
def window_end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'faraday'
|
4
|
+
|
3
5
|
module WavefrontCli
|
4
6
|
#
|
5
7
|
# Handle fatal errors.
|
@@ -19,7 +21,8 @@ module WavefrontCli
|
|
19
21
|
abort "\nOperation aborted at user request."
|
20
22
|
when WavefrontCli::Exception::ConfigFileNotFound
|
21
23
|
abort "Configuration file #{exception}' not found."
|
22
|
-
when WavefrontCli::Exception::CredentialError
|
24
|
+
when WavefrontCli::Exception::CredentialError,
|
25
|
+
Wavefront::Exception::CredentialError
|
23
26
|
handle_missing_credentials(exception)
|
24
27
|
when WavefrontCli::Exception::MandatoryValue
|
25
28
|
abort 'A value must be supplied.'
|
@@ -41,6 +44,8 @@ module WavefrontCli
|
|
41
44
|
abort "'#{exception}' is not a valid API token ID."
|
42
45
|
when Wavefront::Exception::InvalidIngestionPolicyId
|
43
46
|
abort "'#{exception}' is not a valid ingestion policy ID."
|
47
|
+
when Wavefront::Exception::InvalidVersion
|
48
|
+
abort "'#{exception}' is not a valid version."
|
44
49
|
when WavefrontCli::Exception::InvalidValue
|
45
50
|
abort "Invalid value for #{exception}."
|
46
51
|
when WavefrontCli::Exception::ProfileExists
|
@@ -77,6 +82,8 @@ module WavefrontCli
|
|
77
82
|
abort 'Search on non-existent key. Please use a top-level field.'
|
78
83
|
when Wavefront::Exception::InvalidSamplingValue
|
79
84
|
abort 'Sampling rates must be between 0 and 0.05.'
|
85
|
+
when Faraday::ConnectionFailed
|
86
|
+
abort 'Error connecting to remote host.'
|
80
87
|
else
|
81
88
|
warn "general error: #{exception}"
|
82
89
|
backtrace_message(exception)
|
@@ -40,11 +40,11 @@ module WavefrontCli
|
|
40
40
|
private
|
41
41
|
|
42
42
|
def load_json(file)
|
43
|
-
read_json(
|
43
|
+
read_json(File.read(file))
|
44
44
|
end
|
45
45
|
|
46
46
|
def load_yaml(file)
|
47
|
-
read_yaml(
|
47
|
+
read_yaml(File.read(file))
|
48
48
|
end
|
49
49
|
|
50
50
|
# Read STDIN and return a Ruby object, assuming that STDIN is
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'wavefront-sdk/support/mixins'
|
4
|
+
require_relative 'base'
|
5
|
+
require_relative 'helpers/load_file'
|
6
|
+
|
7
|
+
module WavefrontCli
|
8
|
+
#
|
9
|
+
# CLI coverage for the metricspolicy part of the v2 'usage' API.
|
10
|
+
#
|
11
|
+
class MetricsPolicy < WavefrontCli::Base
|
12
|
+
def do_describe
|
13
|
+
wf.describe(options[:version])
|
14
|
+
end
|
15
|
+
|
16
|
+
def do_history
|
17
|
+
wf.history(options[:offset] || 0, options[:limit] || 100)
|
18
|
+
end
|
19
|
+
|
20
|
+
def do_revert
|
21
|
+
wf.revert(options[:'<version>'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def do_update
|
25
|
+
raw = WavefrontCli::Helper::LoadFile.new(options[:'<file>']).load
|
26
|
+
rules = process_update(raw)
|
27
|
+
wf.update(policyRules: rules)
|
28
|
+
end
|
29
|
+
|
30
|
+
# It looks like the API expects arrays of ID strings for accounts, groups,
|
31
|
+
# and roles, but when you export one, those fields are objects with name
|
32
|
+
# and ID.
|
33
|
+
#
|
34
|
+
def process_update(raw)
|
35
|
+
raw[:policyRules].tap do |rule|
|
36
|
+
rule[:accounts] = rule[:accounts].map { |r| r[:id] }
|
37
|
+
rule[:userGroups] = rule[:userGroups].map { |r| r[:id] }
|
38
|
+
rule[:roles] = rule[:roles].map { |r| r[:id] }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -43,11 +43,10 @@ module WavefrontCli
|
|
43
43
|
# constructor.
|
44
44
|
# @param cli_opts [Hash] options from docopt, which may include
|
45
45
|
# the location of the config file and the stanza within it
|
46
|
-
# @return [Hash] keys are none, one, or both of :file and
|
47
|
-
# :profile
|
46
|
+
# @return [Hash] keys are none, one, or both of :file and :profile
|
48
47
|
#
|
49
48
|
def setup_cred_opts(cli_opts)
|
50
|
-
cred_opts = { raise_on_no_profile: true }
|
49
|
+
cred_opts = cli_opts[:config] ? { raise_on_no_profile: true } : {}
|
51
50
|
|
52
51
|
if cli_opts[:config]
|
53
52
|
cred_opts[:file] = Pathname.new(cli_opts[:config])
|
@@ -32,7 +32,7 @@ module WavefrontCsvOutput
|
|
32
32
|
def raw_output
|
33
33
|
resp.each_with_object([]) do |point, a|
|
34
34
|
point[:points].each do |p|
|
35
|
-
a
|
35
|
+
a << csv_format(options[:'<metric>'],
|
36
36
|
p[:value],
|
37
37
|
p[:timestamp],
|
38
38
|
options[:host],
|
@@ -48,7 +48,7 @@ module WavefrontCsvOutput
|
|
48
48
|
|
49
49
|
resp[:timeseries].each_with_object([]) do |ts, a|
|
50
50
|
ts[:data].each do |point|
|
51
|
-
a
|
51
|
+
a << csv_format(ts[:label],
|
52
52
|
point[1],
|
53
53
|
point[0],
|
54
54
|
ts[:host],
|
@@ -92,7 +92,7 @@ module WavefrontCsvOutput
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def quote_value(value)
|
95
|
-
format('"%<value>s"', value: value.to_s.gsub(
|
95
|
+
format('"%<value>s"', value: value.to_s.gsub('"', '\"'))
|
96
96
|
end
|
97
97
|
|
98
98
|
# Turn a string of output options into an easy-to-query array
|
@@ -61,9 +61,9 @@ module WavefrontHclOutput
|
|
61
61
|
# @return [String]
|
62
62
|
#
|
63
63
|
def handler(key, val)
|
64
|
-
key_handler = "khandle_#{key}"
|
65
|
-
value_handler = "vhandle_#{key}"
|
66
|
-
quote_handler = "qhandle_#{key}"
|
64
|
+
key_handler = :"khandle_#{key}"
|
65
|
+
value_handler = :"vhandle_#{key}"
|
66
|
+
quote_handler = :"qhandle_#{key}"
|
67
67
|
key = send(key_handler) if respond_to?(key_handler)
|
68
68
|
val = send(value_handler, val) if respond_to?(value_handler)
|
69
69
|
|
@@ -92,7 +92,7 @@ module WavefrontHclOutput
|
|
92
92
|
def quote_value(val)
|
93
93
|
case val.class.to_s.to_sym
|
94
94
|
when :String
|
95
|
-
format('"%<value>s"', value: val.gsub(
|
95
|
+
format('"%<value>s"', value: val.gsub('"', '\"'))
|
96
96
|
else
|
97
97
|
val
|
98
98
|
end
|
@@ -32,19 +32,19 @@ module WavefrontHclOutput
|
|
32
32
|
# @return [String] HCL list of vals
|
33
33
|
#
|
34
34
|
def listmaker(vals, method)
|
35
|
-
vals.each_with_object([]) { |v, a| a
|
35
|
+
vals.each_with_object([]) { |v, a| a << send(method, v) }.to_hcl_list
|
36
36
|
end
|
37
37
|
|
38
38
|
def vhandle_sections(vals)
|
39
39
|
vals.each_with_object([]) do |section, a|
|
40
|
-
a
|
40
|
+
a << ("name = \"#{section[:name]}\"\n row = " +
|
41
41
|
handle_rows(section[:rows])).braced(4)
|
42
42
|
end.to_hcl_list
|
43
43
|
end
|
44
44
|
|
45
45
|
def handle_rows(rows)
|
46
46
|
rows.each_with_object([]) do |row, a|
|
47
|
-
a
|
47
|
+
a << "chart = #{handle_charts(row[:charts])}".braced(8)
|
48
48
|
end.to_hcl_list
|
49
49
|
end
|
50
50
|
|
@@ -58,10 +58,10 @@ module WavefrontHclOutput
|
|
58
58
|
lines = chart.each_with_object([]) do |(k, v), a|
|
59
59
|
next unless fields.include?(k)
|
60
60
|
|
61
|
-
a
|
61
|
+
a << format('%<key>s = %<value>s', key: k, value: quote_value(v))
|
62
62
|
end
|
63
63
|
|
64
|
-
lines
|
64
|
+
lines << "source = #{handle_sources(chart[:sources])}"
|
65
65
|
lines.to_hcl_obj(10)
|
66
66
|
end
|
67
67
|
|
@@ -75,7 +75,7 @@ module WavefrontHclOutput
|
|
75
75
|
|
76
76
|
k = 'queryBuilderEnabled' if k == 'querybuilderEnabled'
|
77
77
|
|
78
|
-
a
|
78
|
+
a << format('%<key>s = %<value>s',
|
79
79
|
key: k.to_snake,
|
80
80
|
value: quote_value(v))
|
81
81
|
end.to_hcl_obj(14)
|
@@ -91,7 +91,7 @@ module WavefrontHclOutput
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def quote_value(val)
|
94
|
-
val.gsub!(
|
94
|
+
val.gsub!('$', '$$') if val.is_a?(String)
|
95
95
|
super
|
96
96
|
end
|
97
97
|
end
|
@@ -20,11 +20,11 @@ module WavefrontWavefrontOutput
|
|
20
20
|
def raw_output
|
21
21
|
resp.each_with_object('') do |point, a|
|
22
22
|
point[:points].each do |p|
|
23
|
-
a
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
a << "#{wavefront_format(options[:'<metric>'],
|
24
|
+
p[:value],
|
25
|
+
p[:timestamp],
|
26
|
+
options[:host],
|
27
|
+
point[:tags])}\n"
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -34,7 +34,7 @@ module WavefrontWavefrontOutput
|
|
34
34
|
|
35
35
|
resp[:timeseries].each_with_object([]) do |ts, a|
|
36
36
|
ts[:data].each do |point|
|
37
|
-
a
|
37
|
+
a << wavefront_format(ts[:label],
|
38
38
|
point[1],
|
39
39
|
point[0],
|
40
40
|
ts[:host],
|
@@ -46,7 +46,7 @@ module WavefrontWavefrontOutput
|
|
46
46
|
def wavefront_format(path, value, timestamp, source, tags = nil)
|
47
47
|
arr = [path, value, timestamp, format('source=%<source>s',
|
48
48
|
source: source)]
|
49
|
-
arr
|
49
|
+
arr << tags.to_wf_tag if tags && !tags.empty?
|
50
50
|
arr.join(' ')
|
51
51
|
end
|
52
52
|
end
|
@@ -10,7 +10,7 @@ class String
|
|
10
10
|
# @param indent [Integer] size of hanging indent, in chars
|
11
11
|
#
|
12
12
|
def cmd_fold(twidth = TW, indent = 10)
|
13
|
-
gsub(/(-\w) /, '\\1^').scan_line(twidth - 12).join("\n
|
13
|
+
gsub(/(-\w) /, '\\1^').scan_line(twidth - 12).join("\n#{' ' * indent}")
|
14
14
|
.restored
|
15
15
|
end
|
16
16
|
|
@@ -35,7 +35,7 @@ class String
|
|
35
35
|
# @return [String] the folded line
|
36
36
|
#
|
37
37
|
def fold(twidth = TW, indent = 10, prefix = '')
|
38
|
-
chunks = gsub(
|
38
|
+
chunks = gsub('default: ', 'default:^').scan_line(twidth - 8)
|
39
39
|
first_line = format("%<padding>s%<text>s\n",
|
40
40
|
padding: prefix,
|
41
41
|
text: chunks.shift)
|
@@ -58,7 +58,7 @@ class String
|
|
58
58
|
#
|
59
59
|
def value_fold(indent = 0, twidth = TW)
|
60
60
|
max_line_length = twidth - indent - 4
|
61
|
-
scan_line(max_line_length).join("\n
|
61
|
+
scan_line(max_line_length).join("\n#{' ' * indent}")
|
62
62
|
end
|
63
63
|
|
64
64
|
# @param width [Integer] length of longest string (width of
|
@@ -94,7 +94,7 @@ class String
|
|
94
94
|
#
|
95
95
|
def to_snake
|
96
96
|
gsub(/(.)([A-Z])/) do
|
97
|
-
Regexp.last_match[1]
|
97
|
+
"#{Regexp.last_match[1]}_#{Regexp.last_match[2].downcase}"
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
@@ -102,7 +102,7 @@ class String
|
|
102
102
|
|
103
103
|
def indent_folded_lines(chunks, twidth, indent, prefix)
|
104
104
|
chunks.join(' ').scan_line(twidth - indent - 5).map do |line|
|
105
|
-
prefix
|
105
|
+
"#{prefix}#{' ' * indent}#{line}"
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
data/lib/wavefront-cli/usage.rb
CHANGED
data/lib/wavefront-cli/write.rb
CHANGED
@@ -11,7 +11,7 @@ module WavefrontCli
|
|
11
11
|
attr_reader :fmt
|
12
12
|
|
13
13
|
include Wavefront::Mixins
|
14
|
-
SPLIT_PATTERN = /\s(?=(?:[^"]|"[^"]*")*$)
|
14
|
+
SPLIT_PATTERN = /\s(?=(?:[^"]|"[^"]*")*$)/
|
15
15
|
|
16
16
|
# rubocop:disable Metrics/AbcSize
|
17
17
|
def do_point(value = options[:'<value>'])
|
@@ -74,8 +74,8 @@ module WavefrontCli
|
|
74
74
|
end
|
75
75
|
# rubocop:enable Metrics/AbcSize
|
76
76
|
|
77
|
-
# Turn our user's representation of a distribution into one
|
78
|
-
#
|
77
|
+
# Turn our user's representation of a distribution into one which suits
|
78
|
+
# Wavefront. The SDK can do this for us.
|
79
79
|
#
|
80
80
|
def mk_dist
|
81
81
|
xpanded = expand_dist(options[:'<val>'])
|
@@ -83,7 +83,11 @@ module WavefrontCli
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def extra_options
|
86
|
-
|
86
|
+
if options[:using]
|
87
|
+
{ writer: options[:using] }
|
88
|
+
else
|
89
|
+
{ writer: :http }
|
90
|
+
end
|
87
91
|
end
|
88
92
|
|
89
93
|
# I chose to prioritise UI consistency over internal elegance
|
@@ -108,6 +112,7 @@ module WavefrontCli
|
|
108
112
|
port: options[:port] || default_port,
|
109
113
|
socket: options[:socket],
|
110
114
|
endpoint: options[:endpoint],
|
115
|
+
agent: "wavefront-cli-#{WF_CLI_VERSION}",
|
111
116
|
token: options[:token] }
|
112
117
|
end
|
113
118
|
|
@@ -115,18 +120,9 @@ module WavefrontCli
|
|
115
120
|
distribution? ? 40_000 : 2878
|
116
121
|
end
|
117
122
|
|
123
|
+
# The SDK writer plugins validate the credentials they need
|
118
124
|
def validate_opts
|
119
125
|
validate_opts_file if options[:file]
|
120
|
-
|
121
|
-
if options[:using] == 'unix'
|
122
|
-
return true if options[:socket]
|
123
|
-
|
124
|
-
raise(WavefrontCli::Exception::CredentialError, 'No socket path.')
|
125
|
-
end
|
126
|
-
|
127
|
-
return true if options[:proxy]
|
128
|
-
|
129
|
-
raise(WavefrontCli::Exception::CredentialError, 'No proxy address.')
|
130
126
|
end
|
131
127
|
|
132
128
|
def validate_opts_file
|
@@ -167,7 +163,7 @@ module WavefrontCli
|
|
167
163
|
#
|
168
164
|
def process_input_file(data)
|
169
165
|
data.each_with_object([]) do |l, a|
|
170
|
-
a
|
166
|
+
a << process_line(l)
|
171
167
|
rescue WavefrontCli::Exception::UnparseableInput => e
|
172
168
|
puts "Bad input. #{e.message}."
|
173
169
|
next
|
@@ -239,7 +235,7 @@ module WavefrontCli
|
|
239
235
|
#
|
240
236
|
def extract_ts(chunks)
|
241
237
|
ts = chunks[fmt.index('t')]
|
242
|
-
|
238
|
+
parse_time(ts) if valid_timestamp?(ts)
|
243
239
|
rescue TypeError
|
244
240
|
Time.now.utc.to_i
|
245
241
|
end
|
@@ -426,17 +422,17 @@ module WavefrontCli
|
|
426
422
|
#
|
427
423
|
def valid_timestamp?(timestamp)
|
428
424
|
(timestamp.is_a?(Integer) ||
|
429
|
-
timestamp.is_a?(String) && timestamp.match(/^\d+$/)) &&
|
425
|
+
(timestamp.is_a?(String) && timestamp.match(/^\d+$/))) &&
|
430
426
|
timestamp.to_i > 946_684_800 &&
|
431
427
|
timestamp.to_i < (Time.now.to_i + 31_557_600)
|
432
428
|
end
|
433
429
|
|
434
430
|
def setup_fmt(fmt)
|
435
|
-
@fmt = fmt.
|
431
|
+
@fmt = fmt.chars
|
436
432
|
end
|
437
433
|
|
438
434
|
def load_data(file)
|
439
|
-
|
435
|
+
File.read(file)
|
440
436
|
rescue StandardError
|
441
437
|
raise WavefrontCli::Exception::FileNotFound
|
442
438
|
end
|
data/spec/constants.rb
CHANGED
@@ -12,10 +12,9 @@ TW = 80
|
|
12
12
|
|
13
13
|
ENDPOINT = 'metrics.wavefront.com'
|
14
14
|
TOKEN = '0123456789-ABCDEF'
|
15
|
-
RES_DIR = ROOT
|
16
|
-
CF = RES_DIR
|
17
|
-
CF_VAL =
|
18
|
-
JSON_POST_HEADERS = {
|
19
|
-
|
20
|
-
}.freeze
|
15
|
+
RES_DIR = ROOT.join('spec', 'wavefront-cli', 'resources')
|
16
|
+
CF = RES_DIR.join('wavefront.conf')
|
17
|
+
CF_VAL = IniFile.load(CF)
|
18
|
+
JSON_POST_HEADERS = { 'Content-Type': 'application/json',
|
19
|
+
Accept: 'application/json' }.freeze
|
21
20
|
TEE_ZERO = Time.now.freeze
|