wavefront-cli 0.0.5 → 1.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/.travis.yml +2 -1
- data/Gemfile +1 -1
- data/README.md +21 -21
- data/Rakefile +2 -2
- data/bin/{wavefront → wf} +6 -2
- data/lib/wavefront-cli/alert.rb +7 -6
- data/lib/wavefront-cli/base.rb +27 -6
- data/lib/wavefront-cli/commands/alert.rb +2 -1
- data/lib/wavefront-cli/commands/base.rb +54 -29
- data/lib/wavefront-cli/commands/dashboard.rb +1 -0
- data/lib/wavefront-cli/commands/event.rb +7 -3
- data/lib/wavefront-cli/commands/integration.rb +2 -1
- data/lib/wavefront-cli/commands/link.rb +2 -2
- data/lib/wavefront-cli/commands/proxy.rb +2 -1
- data/lib/wavefront-cli/commands/savedsearch.rb +2 -1
- data/lib/wavefront-cli/commands/source.rb +3 -2
- data/lib/wavefront-cli/commands/webhook.rb +2 -1
- data/lib/wavefront-cli/commands/window.rb +2 -1
- data/lib/wavefront-cli/commands/write.rb +10 -6
- data/lib/wavefront-cli/constants.rb +1 -1
- data/lib/wavefront-cli/controller.rb +6 -4
- data/lib/wavefront-cli/dashboard.rb +6 -6
- data/lib/wavefront-cli/display/alert.rb +8 -4
- data/lib/wavefront-cli/display/base.rb +115 -170
- data/lib/wavefront-cli/display/cloudintegration.rb +2 -2
- data/lib/wavefront-cli/display/event.rb +1 -1
- data/lib/wavefront-cli/display/maintenancewindow.rb +1 -1
- data/lib/wavefront-cli/display/metric.rb +6 -7
- data/lib/wavefront-cli/display/printer/base.rb +24 -0
- data/lib/wavefront-cli/display/printer/long.rb +186 -0
- data/lib/wavefront-cli/display/printer/terse.rb +55 -0
- data/lib/wavefront-cli/display/query.rb +1 -2
- data/lib/wavefront-cli/display/savedsearch.rb +1 -1
- data/lib/wavefront-cli/display/source.rb +7 -3
- data/lib/wavefront-cli/display/webhook.rb +3 -4
- data/lib/wavefront-cli/event.rb +62 -23
- data/lib/wavefront-cli/exception.rb +1 -1
- data/lib/wavefront-cli/opt_handler.rb +6 -6
- data/lib/wavefront-cli/query.rb +5 -6
- data/lib/wavefront-cli/source.rb +5 -1
- data/lib/wavefront-cli/string.rb +59 -0
- data/lib/wavefront-cli/version.rb +1 -1
- data/lib/wavefront-cli/write.rb +4 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/wavefront-cli/alert_spec.rb +16 -5
- data/spec/wavefront-cli/base_spec.rb +5 -2
- data/spec/wavefront-cli/cli_help_spec.rb +7 -5
- data/spec/wavefront-cli/cloudintegration_spec.rb +9 -0
- data/spec/wavefront-cli/commands/alert_spec.rb +16 -0
- data/spec/wavefront-cli/commands/base_spec.rb +133 -0
- data/spec/wavefront-cli/commands/dashboard_spec.rb +16 -0
- data/spec/wavefront-cli/commands/event_spec.rb +17 -0
- data/spec/wavefront-cli/commands/integration_spec.rb +21 -0
- data/spec/wavefront-cli/commands/link_spec.rb +21 -0
- data/spec/wavefront-cli/commands/message_spec.rb +16 -0
- data/spec/wavefront-cli/commands/metric_spec.rb +16 -0
- data/spec/wavefront-cli/commands/proxy_spec.rb +16 -0
- data/spec/wavefront-cli/commands/query_spec.rb +16 -0
- data/spec/wavefront-cli/commands/spec_helper.rb +4 -0
- data/spec/wavefront-cli/commands/webhook_spec.rb +16 -0
- data/spec/wavefront-cli/commands/window_spec.rb +21 -0
- data/spec/wavefront-cli/commands/write_spec.rb +17 -0
- data/spec/wavefront-cli/dashboard_spec.rb +14 -4
- data/spec/wavefront-cli/display/base_spec.rb +162 -0
- data/spec/wavefront-cli/display/printer/base_spec.rb +20 -0
- data/spec/wavefront-cli/display/printer/long_spec.rb +137 -0
- data/spec/wavefront-cli/display/printer/terse_spec.rb +46 -0
- data/spec/wavefront-cli/display/spec_helper.rb +5 -0
- data/spec/wavefront-cli/event_spec.rb +9 -0
- data/spec/wavefront-cli/externallink_spec.rb +9 -0
- data/spec/wavefront-cli/maintanancewindow_spec.rb +10 -0
- data/spec/wavefront-cli/proxy_spec.rb +9 -0
- data/spec/wavefront-cli/savedsearch_spec.rb +9 -0
- data/spec/wavefront-cli/source_spec.rb +13 -1
- data/spec/wavefront-cli/string_spec.rb +51 -0
- data/spec/wavefront-cli/user_spec.rb +2 -2
- data/spec/wavefront-cli/webhook_spec.rb +9 -0
- data/wavefront-cli.gemspec +5 -5
- metadata +59 -22
- data/Gemfile.lock +0 -65
@@ -0,0 +1,186 @@
|
|
1
|
+
require_relative './base'
|
2
|
+
require_relative '../../string'
|
3
|
+
|
4
|
+
module WavefrontDisplayPrinter
|
5
|
+
#
|
6
|
+
# Print the long indented descriptions of things
|
7
|
+
#
|
8
|
+
class Long < Base
|
9
|
+
attr_reader :indent, :indent_str, :indent_step, :kw, :hide_blank
|
10
|
+
|
11
|
+
def initialize(data, fields = nil, modified_data = nil)
|
12
|
+
@out = []
|
13
|
+
@indent = 0
|
14
|
+
@indent_step = 2
|
15
|
+
@hide_blank = true
|
16
|
+
_two_columns(modified_data || data, nil, fields)
|
17
|
+
end
|
18
|
+
|
19
|
+
# A recursive function which displays a key-value hash in two
|
20
|
+
# columns. The key column width is automatically calculated.
|
21
|
+
# Multiple-value 'v's are printed one per line. Hashes are nested.
|
22
|
+
#
|
23
|
+
# @param data [Array] and array of objects to display. Each object
|
24
|
+
# should be a hash.
|
25
|
+
# @param indent [Integer] how many characters to indent the current
|
26
|
+
# data.
|
27
|
+
# @kw [Integer] the width of the first (key) column.
|
28
|
+
# @returns [Nil]
|
29
|
+
#
|
30
|
+
def _two_columns(data, kw = nil, fields = nil)
|
31
|
+
[data].flatten.each do |item|
|
32
|
+
preen_fields(item, fields)
|
33
|
+
kw = key_width(item) unless kw
|
34
|
+
@kw = kw unless @kw
|
35
|
+
mk_indent(indent)
|
36
|
+
item.each { |k, v| parse_line(k, v) }
|
37
|
+
add_line(nil) if indent.zero?
|
38
|
+
end
|
39
|
+
|
40
|
+
@indent -= indent_step if indent > 0
|
41
|
+
@kw += 2
|
42
|
+
mk_indent(indent)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Drop any fields not required.
|
46
|
+
#
|
47
|
+
# @param item [Hash, Map] the raw data
|
48
|
+
# @param fields [Array[Symbol]] the fields we wish to keep
|
49
|
+
# @return [Hash, Map]
|
50
|
+
#
|
51
|
+
def preen_fields(item, fields = nil)
|
52
|
+
return item unless fields
|
53
|
+
item.keep_if { |k, _v| fields.include?(k.to_sym) }
|
54
|
+
end
|
55
|
+
|
56
|
+
# Remove HTML and stuff
|
57
|
+
#
|
58
|
+
# @param [String] raw value
|
59
|
+
# @return [String] value with all HTML stripped out
|
60
|
+
#
|
61
|
+
def preen_value(value)
|
62
|
+
return value unless value.is_a?(String) && value =~ /<.*>/
|
63
|
+
value.gsub(%r{<\/?[^>]*>}, '').delete("\n")
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return true if this line is blank and we don't want to print
|
67
|
+
# blank lines
|
68
|
+
#
|
69
|
+
# @param value [Object] thing to check
|
70
|
+
# @return [Boolean]
|
71
|
+
#
|
72
|
+
def blank?(value)
|
73
|
+
value.respond_to?(:empty?) && value.empty? && hide_blank
|
74
|
+
end
|
75
|
+
|
76
|
+
# Parse a line and add it to the output or pass it on to another
|
77
|
+
# method which knows how to add it to the output.
|
78
|
+
#
|
79
|
+
# @param key [String] a key
|
80
|
+
# @param value [Object] the value: could be anything
|
81
|
+
# @return [Nil]
|
82
|
+
#
|
83
|
+
def parse_line(key, value)
|
84
|
+
return if blank?(value)
|
85
|
+
|
86
|
+
value = preen_value(value)
|
87
|
+
|
88
|
+
if value.is_a?(Hash)
|
89
|
+
add_hash(key, value)
|
90
|
+
elsif value.is_a?(Array)
|
91
|
+
add_array(key, value)
|
92
|
+
else
|
93
|
+
add_line(key, value)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Add a key-value pair to the output when value is an array. It
|
98
|
+
# will put the key and the first value element on the first
|
99
|
+
# line, with subsequent value elements aligned at the same
|
100
|
+
# offset, but with no key. If any value element is a hash, it is
|
101
|
+
# handled by a separate method. For instance:
|
102
|
+
#
|
103
|
+
# key value1
|
104
|
+
# value2
|
105
|
+
# value3
|
106
|
+
#
|
107
|
+
# @param key [String] the key
|
108
|
+
# @param value_arr [Array] an array of values
|
109
|
+
# @return [Nil]
|
110
|
+
#
|
111
|
+
def add_array(key, value_arr)
|
112
|
+
value_arr.each_with_index do |element, index|
|
113
|
+
if element.is_a?(Hash)
|
114
|
+
add_hash(key, element, value_arr.size, index)
|
115
|
+
else
|
116
|
+
add_line(index.zero? ? key : nil, element)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Add a hash to the output. It will put the key on a line on its
|
122
|
+
# own, followed by other keys indented. All values are aligned
|
123
|
+
# to the same point. If this hash is a member of an array, we
|
124
|
+
# are able to print a horizontal rule at the end of it. We don't
|
125
|
+
# do this if it is the final member of the array.
|
126
|
+
#
|
127
|
+
# For instance:
|
128
|
+
#
|
129
|
+
# key
|
130
|
+
# subkey1 value1
|
131
|
+
# subkey2 value2
|
132
|
+
#
|
133
|
+
# @param key [String] the key
|
134
|
+
# @param value [Hash] hash of values to display
|
135
|
+
# @param size [Integer] the size of the parent array, if there
|
136
|
+
# is one
|
137
|
+
# @param index [Integer] the index of this element in parent
|
138
|
+
# array, if there is one.
|
139
|
+
# @return [Nil]
|
140
|
+
#
|
141
|
+
def add_hash(key, value, arr_size = 0, arr_index = 0)
|
142
|
+
add_line(key) if arr_index.zero?
|
143
|
+
@indent += indent_step
|
144
|
+
@kw -= 2
|
145
|
+
_two_columns([value], kw - indent_step)
|
146
|
+
add_rule(kw) if arr_index + 1 < arr_size
|
147
|
+
end
|
148
|
+
|
149
|
+
# Add a horizontal rule, from the start of the second column to
|
150
|
+
# just shy of the end of the terminal
|
151
|
+
#
|
152
|
+
def add_rule(kw)
|
153
|
+
add_line(nil, '-' * (TW - kw - 4))
|
154
|
+
end
|
155
|
+
|
156
|
+
# Make the string which is prepended to each line. Stepping is
|
157
|
+
# controlled by @indent_step.
|
158
|
+
#
|
159
|
+
# @param indent [Integer] how many characters to indent by.
|
160
|
+
#
|
161
|
+
def mk_indent(indent)
|
162
|
+
@indent_str = ' ' * indent
|
163
|
+
end
|
164
|
+
|
165
|
+
# Print a single line of output, handling the necessary
|
166
|
+
# indentation and tabulation.
|
167
|
+
#
|
168
|
+
# @param key [String] what to print in the first (key) column.
|
169
|
+
# Make this an empty string to print
|
170
|
+
# @param val [String, Numeric] what to print in the second column
|
171
|
+
# @param tw [Integer] terminal width
|
172
|
+
#
|
173
|
+
def mk_line(key, value = '', tw = TW)
|
174
|
+
return indent_str + ' ' * kw + value if !key || key.empty?
|
175
|
+
|
176
|
+
indent_str + format("%-#{kw}s%s", key, value)
|
177
|
+
.fold(tw, kw + indent_str.size, '').rstrip
|
178
|
+
end
|
179
|
+
|
180
|
+
# Add a line, prepped by #mk_line() to the out array.
|
181
|
+
#
|
182
|
+
def add_line(*args)
|
183
|
+
@out.<< mk_line(*args)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative './base'
|
2
|
+
|
3
|
+
module WavefrontDisplayPrinter
|
4
|
+
|
5
|
+
# Print things which are per-row. The terse listings, primarily
|
6
|
+
#
|
7
|
+
class Terse < Base
|
8
|
+
attr_reader :data, :keys, :fmt_string
|
9
|
+
|
10
|
+
def initialize(data, *keys)
|
11
|
+
# require 'json'
|
12
|
+
# File.open('/tmp/1', 'w') { |f| f.puts data.to_json }
|
13
|
+
@data = data
|
14
|
+
@keys = keys
|
15
|
+
@fmt_string = format_string.rstrip
|
16
|
+
@out = prep_output
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String] a Ruby format string for each line
|
20
|
+
#
|
21
|
+
def format_string
|
22
|
+
lk = longest_keys
|
23
|
+
keys.each_with_object('') { |k, out| out.<< "%-#{lk[k]}s " }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Find the length of the longest value for each member of @keys,
|
27
|
+
# in @data.
|
28
|
+
#
|
29
|
+
# @return [Hash] with the same keys as :keys and Integer values
|
30
|
+
#
|
31
|
+
def longest_keys
|
32
|
+
keys.each_with_object(Hash[*keys.map { |k| [k, 0] }.flatten]) \
|
33
|
+
do |k, aggr|
|
34
|
+
data.each do |obj|
|
35
|
+
val = obj[k]
|
36
|
+
val = val.join(', ') if val.is_a?(Array)
|
37
|
+
aggr[k] = val.size if val.size > aggr[k]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Print multiple column output. This method does no word
|
43
|
+
# wrapping.
|
44
|
+
#
|
45
|
+
# @param keys [Symbol] the keys you want in the output. They
|
46
|
+
# will be printed in the order given.
|
47
|
+
#
|
48
|
+
def prep_output
|
49
|
+
data.each_with_object([]) do |o, aggr|
|
50
|
+
args = keys.map { |k| o[k].is_a?(Array) ? o[k].join(', ') : o[k] }
|
51
|
+
aggr.<< format(fmt_string, *args).rstrip
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -6,7 +6,6 @@ module WavefrontDisplay
|
|
6
6
|
#
|
7
7
|
class Query < Base
|
8
8
|
def do_default
|
9
|
-
|
10
9
|
ts = if data.key?(:timeseries)
|
11
10
|
data[:timeseries].each do |s|
|
12
11
|
s[:data] = humanize_series(s[:data])
|
@@ -62,7 +61,7 @@ module WavefrontDisplay
|
|
62
61
|
date, time = ht.split
|
63
62
|
ds = date == last_date ? '' : date
|
64
63
|
last_date = date
|
65
|
-
format('
|
64
|
+
format('%-12s %s %s', ds, time, val)
|
66
65
|
end
|
67
66
|
end
|
68
67
|
end
|
@@ -12,13 +12,17 @@ module WavefrontDisplay
|
|
12
12
|
|
13
13
|
def do_list_brief
|
14
14
|
drop_cluster_sources
|
15
|
-
|
15
|
+
multicolumn(:id, :description)
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
def do_search_brief
|
19
|
+
multicolumn(:id)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Filter out the Wavefront cluster sources. Don't sort them, or
|
23
|
+
# using offset and cursor becomes confusing.
|
19
24
|
#
|
20
25
|
def drop_cluster_sources
|
21
|
-
data.sort_by! { |k, _v| k }
|
22
26
|
return if options[:all]
|
23
27
|
data.delete_if { |k| k.id =~ /prod-[\da-f]{2}-/ }
|
24
28
|
end
|
@@ -6,13 +6,12 @@ module WavefrontDisplay
|
|
6
6
|
#
|
7
7
|
class Webhook < Base
|
8
8
|
def do_list
|
9
|
-
long_output([:id, :description, :createdEpochMillis,
|
10
|
-
:updatedEpochMillis, :updaterId, :creatorId
|
11
|
-
:title])
|
9
|
+
long_output([:id, :title, :description, :createdEpochMillis,
|
10
|
+
:updatedEpochMillis, :updaterId, :creatorId])
|
12
11
|
end
|
13
12
|
|
14
13
|
def do_list_brief
|
15
|
-
|
14
|
+
multicolumn(:id, :title)
|
16
15
|
end
|
17
16
|
|
18
17
|
def do_describe
|
data/lib/wavefront-cli/event.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'wavefront-sdk/mixins'
|
3
3
|
require_relative './base'
|
4
|
+
require 'open3'
|
4
5
|
|
5
6
|
EVENT_STATE_DIR = Pathname.new('/var/tmp/wavefront')
|
6
7
|
|
@@ -26,7 +27,7 @@ module WavefrontCli
|
|
26
27
|
options[:start] = Time.now - 600 unless options[:start]
|
27
28
|
options[:end] = Time.now unless options[:end]
|
28
29
|
wf.list(options[:start], options[:end], options[:limit] || 100,
|
29
|
-
options[:
|
30
|
+
options[:cursor] || nil)
|
30
31
|
end
|
31
32
|
|
32
33
|
def do_update
|
@@ -34,32 +35,37 @@ module WavefrontCli
|
|
34
35
|
wf.update(options[:'<id>'], k => v)
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
-
|
38
|
+
# You can override the options generated by docopt. This is how
|
39
|
+
# #wrap() works.
|
40
|
+
#
|
41
|
+
def do_create(opts = nil)
|
42
|
+
opts ||= options
|
43
|
+
|
44
|
+
opts[:start] = Time.now unless opts[:start]
|
39
45
|
|
40
|
-
t_start = parse_time(
|
41
|
-
id = [t_start,
|
46
|
+
t_start = parse_time(opts[:start], true)
|
47
|
+
id = [t_start, opts[:'<event>']].join(':')
|
42
48
|
|
43
|
-
body = { name:
|
49
|
+
body = { name: opts[:'<event>'],
|
44
50
|
startTime: t_start,
|
45
51
|
id: id,
|
46
52
|
annotations: {} }
|
47
53
|
|
48
|
-
body[:annotations][:details] =
|
49
|
-
body[:annotations][:severity] =
|
50
|
-
body[:annotations][:type] =
|
51
|
-
body[:hosts] =
|
54
|
+
body[:annotations][:details] = opts[:desc] if opts[:desc]
|
55
|
+
body[:annotations][:severity] = opts[:severity] if opts[:severity]
|
56
|
+
body[:annotations][:type] = opts[:type] if opts[:type]
|
57
|
+
body[:hosts] = opts[:host] if opts[:host]
|
52
58
|
|
53
|
-
if
|
59
|
+
if opts[:instant]
|
54
60
|
body[:endTime] = t_start + 1
|
55
|
-
elsif
|
56
|
-
body[:endTime] = parse_time(
|
61
|
+
elsif opts[:end]
|
62
|
+
body[:endTime] = parse_time(opts[:end], true)
|
57
63
|
end
|
58
64
|
|
59
65
|
resp = wf.create(body)
|
60
66
|
|
61
|
-
unless
|
62
|
-
create_state_file(id,
|
67
|
+
unless opts[:nostate] || opts[:end] || opts[:instant]
|
68
|
+
create_state_file(id, opts[:host])
|
63
69
|
end
|
64
70
|
|
65
71
|
resp
|
@@ -71,19 +77,20 @@ module WavefrontCli
|
|
71
77
|
# name, we'll look for something on the stack. If it does look
|
72
78
|
# like a real event, we'll make and API call straight away.
|
73
79
|
#
|
74
|
-
def do_close
|
80
|
+
def do_close(id = nil)
|
81
|
+
id ||= options[:'<id>']
|
75
82
|
ev_file = nil
|
76
83
|
|
77
|
-
ev = if
|
84
|
+
ev = if !id
|
78
85
|
pop_event
|
79
|
-
elsif
|
80
|
-
ev_file = state_dir +
|
81
|
-
|
86
|
+
elsif id =~ /^\d{13}:.+/
|
87
|
+
ev_file = state_dir + id
|
88
|
+
id
|
82
89
|
else
|
83
|
-
pop_event(
|
90
|
+
pop_event(id)
|
84
91
|
end
|
85
92
|
|
86
|
-
abort "No locally stored event matches '#{
|
93
|
+
abort "No locally stored event matches '#{id}'." unless ev
|
87
94
|
|
88
95
|
res = wf.close(ev)
|
89
96
|
ev_file.unlink if ev_file && ev_file.exist? && res.status.code == 200
|
@@ -106,14 +113,46 @@ module WavefrontCli
|
|
106
113
|
exit
|
107
114
|
end
|
108
115
|
|
116
|
+
def do_wrap
|
117
|
+
create_opts = options
|
118
|
+
create_opts[:desc] ||= create_opts[:command]
|
119
|
+
event_id = do_create(create_opts).response.id
|
120
|
+
exit_code = run_wrapped_cmd(options[:command])
|
121
|
+
do_close(event_id)
|
122
|
+
puts "Command exited #{exit_code}"
|
123
|
+
exit exit_code
|
124
|
+
end
|
125
|
+
|
109
126
|
private
|
110
127
|
|
128
|
+
# Run a command, stream stderr and stdout to the screen (they
|
129
|
+
# get combined -- could be an issue for someone somewhere) and
|
130
|
+
# return the command's exit code
|
131
|
+
#
|
132
|
+
# rubocop:disable Lint/AssignmentInCondition
|
133
|
+
#
|
134
|
+
def run_wrapped_cmd(cmd)
|
135
|
+
puts 'Command output follows, on STDERR:'
|
136
|
+
puts '-' * (TW - 4)
|
137
|
+
ret = nil
|
138
|
+
|
139
|
+
Open3.popen2e(cmd) do |_in, out, thr|
|
140
|
+
while l = out.gets
|
141
|
+
STDERR.puts l
|
142
|
+
end
|
143
|
+
|
144
|
+
ret = thr.value.exitstatus
|
145
|
+
end
|
146
|
+
|
147
|
+
puts '-' * (TW - 4)
|
148
|
+
ret
|
149
|
+
end
|
150
|
+
|
111
151
|
# Write a state file. We put the hosts bound to the event into the
|
112
152
|
# file. These aren't currently used by anything in the CLI, but they
|
113
153
|
# might be useful to someone, somewhere, someday.
|
114
154
|
#
|
115
155
|
def create_state_file(id, hosts = [])
|
116
|
-
puts "statfile fir #{id}"
|
117
156
|
fname = state_dir + id
|
118
157
|
|
119
158
|
begin
|
@@ -37,13 +37,13 @@ module WavefrontCli
|
|
37
37
|
@opts = DEFAULT_OPTS.merge(load_profile).merge(@cli_opts)
|
38
38
|
end
|
39
39
|
|
40
|
+
# Load in configuration options from the (optionally) given
|
41
|
+
# section of an ini-style configuration file. If the file's not
|
42
|
+
# there, we don't consider that an error. Returns a hash of
|
43
|
+
# options which matches what Docopt gives us.
|
44
|
+
#
|
45
|
+
# rubocop:disable Metrics/AbcSize
|
40
46
|
def load_profile
|
41
|
-
#
|
42
|
-
# Load in configuration options from the (optionally) given
|
43
|
-
# section of an ini-style configuration file. If the file's
|
44
|
-
# not there, we don't consider that an error. Returns a hash
|
45
|
-
# of options which matches what Docopt gives us.
|
46
|
-
#
|
47
47
|
unless conf_file.exist?
|
48
48
|
puts "config file '#{conf_file}' not found. Taking options " \
|
49
49
|
'from command-line.'
|
data/lib/wavefront-cli/query.rb
CHANGED
@@ -19,11 +19,11 @@ module WavefrontCli
|
|
19
19
|
sorted: true
|
20
20
|
}
|
21
21
|
|
22
|
-
if options[:start]
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
options[:start] = if options[:start]
|
23
|
+
parse_time(options[:start], true)
|
24
|
+
else
|
25
|
+
(Time.now - 600).to_i
|
26
|
+
end
|
27
27
|
|
28
28
|
if options[:end]
|
29
29
|
options[:end] = parse_time(options[:end], true)
|
@@ -42,7 +42,6 @@ module WavefrontCli
|
|
42
42
|
options[:start], options[:end] || nil, opts)
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
45
|
# Work out a sensible granularity based on the time window
|
47
46
|
#
|
48
47
|
def default_granularity(window)
|
data/lib/wavefront-cli/source.rb
CHANGED
@@ -5,6 +5,10 @@ module WavefrontCli
|
|
5
5
|
# CLI coverage for the v2 'source' API.
|
6
6
|
#
|
7
7
|
class Source < WavefrontCli::Base
|
8
|
+
def do_list
|
9
|
+
wf.list(options[:limit], options[:cursor])
|
10
|
+
end
|
11
|
+
|
8
12
|
def do_clear
|
9
13
|
wf.delete(options[:'<id>'])
|
10
14
|
end
|
@@ -14,7 +18,7 @@ module WavefrontCli
|
|
14
18
|
end
|
15
19
|
|
16
20
|
def do_description_clear
|
17
|
-
wf.update(options[:'<id>'], { description: ''}, false)
|
21
|
+
wf.update(options[:'<id>'], { description: '' }, false)
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Extensions to the String class to help with formatting.
|
2
|
+
#
|
3
|
+
class String
|
4
|
+
# Fold long command lines. We can't break on a space after an
|
5
|
+
# option or it confuses docopt.
|
6
|
+
#
|
7
|
+
# @param tw [Integer] terminal width
|
8
|
+
# @param indent [Integer] size of hanging indent, in chars
|
9
|
+
#
|
10
|
+
def cmd_fold(tw = TW, indent = 10)
|
11
|
+
#gsub(/\s(?=\w+\])/, '^').scan_line(tw - 8).join("\n" + ' ' * indent)
|
12
|
+
gsub(/(-\w) /, "\\1^").scan_line(tw - 12).join("\n" + ' ' * indent)
|
13
|
+
.tr('^', ' ')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Wrapper around #fold()
|
17
|
+
#
|
18
|
+
# @param tw [Integer] width of terminal, in chars
|
19
|
+
# @param indent [Integer] hanging indent of following lines
|
20
|
+
# @return [String] folded and indented string
|
21
|
+
#
|
22
|
+
def opt_fold(tw = TW, indent = 10)
|
23
|
+
fold(tw, indent, ' ')
|
24
|
+
end
|
25
|
+
|
26
|
+
# Fold long lines with a hanging indent. Originally a special case
|
27
|
+
# for option folding, now addded the prefix parameter to make it
|
28
|
+
# more general.
|
29
|
+
#
|
30
|
+
# rubocop:disable Metrics/AbcSize
|
31
|
+
#
|
32
|
+
# @param tw [Integer] terminal width
|
33
|
+
# @param indent [Integer] size of hanging indent, in chars
|
34
|
+
# @param prefix [String] prepended to every line
|
35
|
+
# @return [String] the folded line
|
36
|
+
#
|
37
|
+
def fold(tw = TW, indent = 10, prefix = '')
|
38
|
+
chunks = self.scan_line(tw - 8)
|
39
|
+
|
40
|
+
line_1 = prefix + chunks.shift + "\n"
|
41
|
+
|
42
|
+
return line_1 if chunks.empty?
|
43
|
+
|
44
|
+
rest = chunks.join(' ').scan_line(tw - indent - 5).map do |l|
|
45
|
+
prefix + ' ' * indent + l
|
46
|
+
end
|
47
|
+
|
48
|
+
line_1 + rest.join("\n") + "\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param width [Integer] length of longest string (width of
|
52
|
+
# terminal less some margin)
|
53
|
+
# @return [Array] original string chunked into an array width
|
54
|
+
# elements whose length < width
|
55
|
+
#
|
56
|
+
def scan_line(width)
|
57
|
+
scan(/\S.{0,#{width}}\S(?=\s|$)|\S+/)
|
58
|
+
end
|
59
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
WF_CLI_VERSION = '0.0
|
1
|
+
WF_CLI_VERSION = '1.0.0'.freeze
|
data/lib/wavefront-cli/write.rb
CHANGED
@@ -5,6 +5,7 @@ module WavefrontCli
|
|
5
5
|
#
|
6
6
|
# Send points to a proxy.
|
7
7
|
#
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
8
9
|
class Write < Base
|
9
10
|
attr_reader :fmt
|
10
11
|
include Wavefront::Mixins
|
@@ -13,6 +14,8 @@ module WavefrontCli
|
|
13
14
|
{ proxy: options[:proxy], port: options[:port] || 2878 }
|
14
15
|
end
|
15
16
|
|
17
|
+
# rubocop:disable Metrics/AbcSize
|
18
|
+
# rubocop:disable Metrics/MethodLength
|
16
19
|
def do_point
|
17
20
|
p = { path: options[:'<metric>'],
|
18
21
|
value: options[:'<value>'].to_f,
|
@@ -152,7 +155,7 @@ module WavefrontCli
|
|
152
155
|
# Merge them, making the -T win if there is a collision.
|
153
156
|
#
|
154
157
|
def line_tags(chunks)
|
155
|
-
file_tags =
|
158
|
+
file_tags = fmt.last == 'T' ? extract_tags(chunks) : {}
|
156
159
|
opt_tags = tags_to_hash(options[:tag])
|
157
160
|
file_tags.merge(opt_tags)
|
158
161
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -50,7 +50,7 @@ def cmd_to_call(word, args, call, sdk_class = nil)
|
|
50
50
|
headers = { 'Accept': /.*/,
|
51
51
|
'Accept-Encoding': /.*/,
|
52
52
|
'Authorization': 'Bearer 0123456789-ABCDEF',
|
53
|
-
'User-Agent':
|
53
|
+
'User-Agent': "wavefront-cli-#{WF_CLI_VERSION}"
|
54
54
|
}
|
55
55
|
|
56
56
|
sdk_class ||= Object.const_get("WavefrontCli::#{word.capitalize}")
|
@@ -18,19 +18,30 @@ describe "#{word} command" do
|
|
18
18
|
|
19
19
|
it 'deletes with a check on inTrash' do
|
20
20
|
stub_request(:get,
|
21
|
-
'https://other.wavefront.com/api/v2/alert/1481553823153')
|
22
|
-
|
23
|
-
'Accept-Encoding':
|
21
|
+
'https://other.wavefront.com/api/v2/alert/1481553823153')
|
22
|
+
.with(headers: { 'Accept': '*/*',
|
23
|
+
'Accept-Encoding':
|
24
|
+
'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
24
25
|
'Authorization': 'Bearer 0123456789-ABCDEF',
|
25
|
-
'User-Agent': /wavefront.*/})
|
26
|
-
|
26
|
+
'User-Agent': /wavefront.*/ })
|
27
|
+
.to_return(status: 200, body: '', headers: {})
|
27
28
|
cmd_to_call(word, "delete #{id}",
|
28
29
|
method: :delete, path: "/api/v2/#{word}/#{id}")
|
29
30
|
end
|
31
|
+
|
30
32
|
cmd_to_call(word, "undelete #{id}",
|
31
33
|
method: :post, path: "/api/v2/#{word}/#{id}/undelete")
|
32
34
|
cmd_to_call(word, "snooze #{id}",
|
33
35
|
method: :post, path: "/api/v2/#{word}/#{id}/snooze")
|
36
|
+
cmd_to_call(word, "search id=#{id}",
|
37
|
+
{ method: :post, path: "/api/v2/search/#{word}",
|
38
|
+
body: { limit: 10,
|
39
|
+
offset: 0,
|
40
|
+
query: [{key: 'id',
|
41
|
+
value: id,
|
42
|
+
matchingMethod: 'EXACT'}],
|
43
|
+
sort: {field: 'id', ascending: true}},
|
44
|
+
headers: JSON_POST_HEADERS })
|
34
45
|
cmd_to_call(word, "snooze -T 800 #{id}",
|
35
46
|
method: :post,
|
36
47
|
path: "/api/v2/#{word}/#{id}/snooze?seconds=800")
|