wavefront-sdk 1.6.2 → 2.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/HISTORY.md +39 -13
  4. data/README.md +75 -28
  5. data/Rakefile +1 -1
  6. data/lib/wavefront-sdk/alert.rb +113 -17
  7. data/lib/wavefront-sdk/cloudintegration.rb +8 -8
  8. data/lib/wavefront-sdk/core/api.rb +99 -0
  9. data/lib/wavefront-sdk/core/api_caller.rb +211 -0
  10. data/lib/wavefront-sdk/{exception.rb → core/exception.rb} +11 -6
  11. data/lib/wavefront-sdk/{logger.rb → core/logger.rb} +2 -3
  12. data/lib/wavefront-sdk/{response.rb → core/response.rb} +69 -52
  13. data/lib/wavefront-sdk/credentials.rb +6 -3
  14. data/lib/wavefront-sdk/dashboard.rb +14 -14
  15. data/lib/wavefront-sdk/{constants.rb → defs/constants.rb} +1 -0
  16. data/lib/wavefront-sdk/defs/version.rb +1 -0
  17. data/lib/wavefront-sdk/derivedmetric.rb +14 -14
  18. data/lib/wavefront-sdk/distribution.rb +75 -0
  19. data/lib/wavefront-sdk/event.rb +13 -13
  20. data/lib/wavefront-sdk/externallink.rb +8 -8
  21. data/lib/wavefront-sdk/integration.rb +9 -9
  22. data/lib/wavefront-sdk/maintenancewindow.rb +54 -8
  23. data/lib/wavefront-sdk/message.rb +4 -4
  24. data/lib/wavefront-sdk/metric.rb +3 -3
  25. data/lib/wavefront-sdk/notificant.rb +9 -9
  26. data/lib/wavefront-sdk/paginator/base.rb +148 -0
  27. data/lib/wavefront-sdk/paginator/delete.rb +11 -0
  28. data/lib/wavefront-sdk/paginator/get.rb +11 -0
  29. data/lib/wavefront-sdk/paginator/post.rb +64 -0
  30. data/lib/wavefront-sdk/paginator/put.rb +11 -0
  31. data/lib/wavefront-sdk/proxy.rb +7 -7
  32. data/lib/wavefront-sdk/query.rb +4 -4
  33. data/lib/wavefront-sdk/report.rb +9 -25
  34. data/lib/wavefront-sdk/savedsearch.rb +8 -8
  35. data/lib/wavefront-sdk/search.rb +16 -13
  36. data/lib/wavefront-sdk/source.rb +14 -14
  37. data/lib/wavefront-sdk/{mixins.rb → support/mixins.rb} +8 -2
  38. data/lib/wavefront-sdk/{parse_time.rb → support/parse_time.rb} +2 -0
  39. data/lib/wavefront-sdk/types/status.rb +52 -0
  40. data/lib/wavefront-sdk/user.rb +8 -8
  41. data/lib/wavefront-sdk/validators.rb +52 -3
  42. data/lib/wavefront-sdk/webhook.rb +8 -8
  43. data/lib/wavefront-sdk/write.rb +153 -52
  44. data/lib/wavefront-sdk/writers/api.rb +38 -0
  45. data/lib/wavefront-sdk/writers/core.rb +146 -0
  46. data/lib/wavefront-sdk/writers/http.rb +42 -0
  47. data/lib/wavefront-sdk/writers/socket.rb +66 -0
  48. data/lib/wavefront-sdk/writers/summary.rb +39 -0
  49. data/lib/wavefront_sdk.rb +9 -0
  50. data/spec/spec_helper.rb +3 -0
  51. data/spec/wavefront-sdk/alert_spec.rb +6 -0
  52. data/spec/wavefront-sdk/{base_spec.rb → core/api_caller_spec.rb} +28 -41
  53. data/spec/wavefront-sdk/core/api_spec.rb +31 -0
  54. data/spec/wavefront-sdk/{logger_spec.rb → core/logger_spec.rb} +3 -3
  55. data/spec/wavefront-sdk/core/response_spec.rb +77 -0
  56. data/spec/wavefront-sdk/credentials_spec.rb +15 -10
  57. data/spec/wavefront-sdk/distribution_spec.rb +78 -0
  58. data/spec/wavefront-sdk/paginator/base_spec.rb +67 -0
  59. data/spec/wavefront-sdk/paginator/post_spec.rb +53 -0
  60. data/spec/wavefront-sdk/report_spec.rb +3 -1
  61. data/spec/wavefront-sdk/search_spec.rb +25 -0
  62. data/spec/wavefront-sdk/stdlib/array_spec.rb +2 -1
  63. data/spec/wavefront-sdk/stdlib/hash_spec.rb +6 -1
  64. data/spec/wavefront-sdk/stdlib/string_spec.rb +2 -0
  65. data/spec/wavefront-sdk/{mixins_spec.rb → support/mixins_spec.rb} +2 -2
  66. data/spec/wavefront-sdk/{parse_time_spec.rb → support/parse_time_spec.rb} +2 -2
  67. data/spec/wavefront-sdk/validators_spec.rb +64 -1
  68. data/spec/wavefront-sdk/write_spec.rb +55 -77
  69. data/spec/wavefront-sdk/writers/api_spec.rb +45 -0
  70. data/spec/wavefront-sdk/writers/core_spec.rb +49 -0
  71. data/spec/wavefront-sdk/writers/http_spec.rb +69 -0
  72. data/spec/wavefront-sdk/writers/socket_spec.rb +104 -0
  73. data/spec/wavefront-sdk/writers/summary_spec.rb +38 -0
  74. data/wavefront-sdk.gemspec +1 -1
  75. metadata +52 -24
  76. data/lib/wavefront-sdk/base.rb +0 -264
  77. data/lib/wavefront-sdk/base_write.rb +0 -185
  78. data/lib/wavefront-sdk/stdlib.rb +0 -5
  79. data/lib/wavefront-sdk/version.rb +0 -1
  80. data/spec/wavefront-sdk/base_write_spec.rb +0 -82
  81. data/spec/wavefront-sdk/response_spec.rb +0 -39
@@ -1,10 +1,10 @@
1
- require_relative 'base'
1
+ require_relative 'core/api'
2
2
 
3
3
  module Wavefront
4
4
  #
5
5
  # Manage and query Wavefront integrations.
6
6
  #
7
- class Integration < Base
7
+ class Integration < CoreApi
8
8
  # GET /api/v2/integration
9
9
  # Gets a flat list of all Wavefront integrations available,
10
10
  # along with their status
@@ -13,7 +13,7 @@ module Wavefront
13
13
  # @param limit [Int] the number of proxies to return
14
14
  #
15
15
  def list(offset = 0, limit = 100)
16
- api_get('', offset: offset, limit: limit)
16
+ api.get('', offset: offset, limit: limit)
17
17
  end
18
18
 
19
19
  # GET /api/v2/integration/id
@@ -25,7 +25,7 @@ module Wavefront
25
25
  #
26
26
  def describe(id)
27
27
  wf_integration_id?(id)
28
- api_get(id)
28
+ api.get(id)
29
29
  end
30
30
 
31
31
  # POST /api/v2/integration/id/install
@@ -36,7 +36,7 @@ module Wavefront
36
36
  #
37
37
  def install(id)
38
38
  wf_integration_id?(id)
39
- api_post([id, 'install'].uri_concat, nil)
39
+ api.post([id, 'install'].uri_concat, nil)
40
40
  end
41
41
 
42
42
  # POST /api/v2/integration/id/uninstall
@@ -47,7 +47,7 @@ module Wavefront
47
47
  #
48
48
  def uninstall(id)
49
49
  wf_integration_id?(id)
50
- api_post([id, 'uninstall'].uri_concat, nil)
50
+ api.post([id, 'uninstall'].uri_concat, nil)
51
51
  end
52
52
 
53
53
  # GET /api/v2/integration/id/status
@@ -58,7 +58,7 @@ module Wavefront
58
58
  #
59
59
  def status(id)
60
60
  wf_integration_id?(id)
61
- api_get([id, 'status'].uri_concat)
61
+ api.get([id, 'status'].uri_concat)
62
62
  end
63
63
 
64
64
  # GET /api/v2/integration/status
@@ -67,7 +67,7 @@ module Wavefront
67
67
  # @return [Wavefront::Response]
68
68
  #
69
69
  def statuses
70
- api_get('status')
70
+ api.get('status')
71
71
  end
72
72
 
73
73
  # GET /api/v2/integration/manifests
@@ -75,7 +75,7 @@ module Wavefront
75
75
  # integration manifests, along with their status
76
76
  #
77
77
  def manifests
78
- api_get('manifests')
78
+ api.get('manifests')
79
79
  end
80
80
  end
81
81
  end
@@ -1,10 +1,10 @@
1
- require_relative 'base'
1
+ require_relative 'core/api'
2
2
 
3
3
  module Wavefront
4
4
  #
5
5
  # Manage and query Wavefront maintenance windows
6
6
  #
7
- class MaintenanceWindow < Base
7
+ class MaintenanceWindow < CoreApi
8
8
  def update_keys
9
9
  %i[reason title startTimeInSeconds endTimeInSeconds
10
10
  relevantCustomerTags relevantHostTags relevantHostNames]
@@ -17,7 +17,7 @@ module Wavefront
17
17
  # @param limit [Integer] the number of window to return
18
18
  #
19
19
  def list(offset = 0, limit = 100)
20
- api_get('', offset: offset, limit: limit)
20
+ api.get('', offset: offset, limit: limit)
21
21
  end
22
22
 
23
23
  # POST /api/v2/maintenancewindow
@@ -32,7 +32,7 @@ module Wavefront
32
32
  #
33
33
  def create(body)
34
34
  raise ArgumentError unless body.is_a?(Hash)
35
- api_post('', body, 'application/json')
35
+ api.post('', body, 'application/json')
36
36
  end
37
37
 
38
38
  # DELETE /api/v2/maintenancewindow/id
@@ -43,7 +43,7 @@ module Wavefront
43
43
  #
44
44
  def delete(id)
45
45
  wf_maintenance_window_id?(id)
46
- api_delete(id)
46
+ api.delete(id)
47
47
  end
48
48
 
49
49
  # GET /api/v2/maintenancewindow/id
@@ -54,7 +54,7 @@ module Wavefront
54
54
  #
55
55
  def describe(id)
56
56
  wf_maintenance_window_id?(id)
57
- api_get(id)
57
+ api.get(id)
58
58
  end
59
59
 
60
60
  # PUT /api/v2/maintenancewindow/id
@@ -72,10 +72,56 @@ module Wavefront
72
72
  wf_maintenance_window_id?(id)
73
73
  raise ArgumentError unless body.is_a?(Hash)
74
74
 
75
- return api_put(id, body, 'application/json') unless modify
75
+ return api.put(id, body, 'application/json') unless modify
76
76
 
77
- api_put(id, hash_for_update(describe(id).response, body),
77
+ api.put(id, hash_for_update(describe(id).response, body),
78
78
  'application/json')
79
79
  end
80
+
81
+ # Windows currently open.
82
+ # @return [Wavefront::Response]
83
+ #
84
+ def ongoing
85
+ windows_in_state(:ongoing)
86
+ end
87
+
88
+ # Get the windows which will be open in the next so-many hours
89
+ # @param hours [Numeric] how many hours to look ahead
90
+ # @return [Wavefront::Response]
91
+ #
92
+ def pending(hours = 24)
93
+ cutoff = Time.now.to_i + hours * 3600
94
+
95
+ windows_in_state(:pending).tap do |r|
96
+ r.response.items.delete_if { |w| w.startTimeInSeconds > cutoff }
97
+ end
98
+ end
99
+
100
+ # This method mimics the similarly named method from the v1 SDK,
101
+ # which called the 'GET /api/alert/maintenancewindow/summary'
102
+ # path.
103
+ # @return [Wavefront::Response]
104
+ #
105
+ def summary
106
+ ret = pending
107
+
108
+ items = { UPCOMING: ret.response.items,
109
+ CURRENT: ongoing.response.items }
110
+
111
+ ret.response.items = items
112
+ ret
113
+ end
114
+
115
+ # Return all maintenance windows in the given state. At the time
116
+ # of writing valid states are ONGOING, PENDING, and ENDED.
117
+ # @param state [Symbol]
118
+ # @return [Wavefront::Response]
119
+ #
120
+ def windows_in_state(state)
121
+ require_relative 'search'
122
+ wfs = Wavefront::Search.new(creds, opts)
123
+ query = { key: 'runningState', value: state, matchingMethod: 'EXACT' }
124
+ wfs.search(:maintenancewindow, query, limit: :all, offset: PAGE_SIZE)
125
+ end
80
126
  end
81
127
  end
@@ -1,10 +1,10 @@
1
- require_relative 'base'
1
+ require_relative 'core/api'
2
2
 
3
3
  module Wavefront
4
4
  #
5
5
  # Manage and query Wavefront messages.
6
6
  #
7
- class Message < Base
7
+ class Message < CoreApi
8
8
  # GET /api/v2/message
9
9
  # Gets messages applicable to the current user, i.e. within time
10
10
  # range and distribution scope
@@ -13,7 +13,7 @@ module Wavefront
13
13
  # @param limit [Int] the number of agents to return
14
14
  #
15
15
  def list(offset = 0, limit = 100, unread_only = true)
16
- api_get('', offset: offset, limit: limit, unreadOnly: unread_only)
16
+ api.get('', offset: offset, limit: limit, unreadOnly: unread_only)
17
17
  end
18
18
 
19
19
  # POST /api/v2/message/id/read
@@ -23,7 +23,7 @@ module Wavefront
23
23
  #
24
24
  def read(id)
25
25
  wf_message_id?(id)
26
- api_post([id, 'read'].uri_concat)
26
+ api.post([id, 'read'].uri_concat)
27
27
  end
28
28
  end
29
29
  end
@@ -1,10 +1,10 @@
1
- require_relative 'base'
1
+ require_relative 'core/api'
2
2
 
3
3
  module Wavefront
4
4
  #
5
5
  # Query Wavefront metrics.
6
6
  #
7
- class Metric < Base
7
+ class Metric < CoreApi
8
8
  def api_base
9
9
  'chart/metric'
10
10
  end
@@ -29,7 +29,7 @@ module Wavefront
29
29
 
30
30
  sources.each { |source| query.<< [:h, source] }
31
31
 
32
- api_get('detail', query)
32
+ api.get('detail', query)
33
33
  end
34
34
  end
35
35
  end
@@ -1,10 +1,10 @@
1
- require_relative 'base'
1
+ require_relative 'core/api'
2
2
 
3
3
  module Wavefront
4
4
  #
5
5
  # Manage and query Wavefront notification targets.
6
6
  #
7
- class Notificant < Base
7
+ class Notificant < CoreApi
8
8
  # GET /api/v2/notificant
9
9
  # Get all notification targets for a customer
10
10
  #
@@ -12,7 +12,7 @@ module Wavefront
12
12
  # @param limit [Int] the number of notification targets to return
13
13
  #
14
14
  def list(offset = 0, limit = 100)
15
- api_get('', offset: offset, limit: limit)
15
+ api.get('', offset: offset, limit: limit)
16
16
  end
17
17
 
18
18
  # POST /api/v2/notificant
@@ -23,7 +23,7 @@ module Wavefront
23
23
  #
24
24
  def create(body)
25
25
  raise ArgumentError unless body.is_a?(Hash)
26
- api_post('', body, 'application/json')
26
+ api.post('', body, 'application/json')
27
27
  end
28
28
 
29
29
  # DELETE /api/v2/notificant/id
@@ -34,7 +34,7 @@ module Wavefront
34
34
  #
35
35
  def delete(id)
36
36
  wf_notificant_id?(id)
37
- api_delete(id)
37
+ api.delete(id)
38
38
  end
39
39
 
40
40
  # GET /api/v2/notificant/id
@@ -45,7 +45,7 @@ module Wavefront
45
45
  #
46
46
  def describe(id)
47
47
  wf_notificant_id?(id)
48
- api_get(id)
48
+ api.get(id)
49
49
  end
50
50
 
51
51
  # PUT /api/v2/notificant/id
@@ -63,9 +63,9 @@ module Wavefront
63
63
  wf_notificant_id?(id)
64
64
  raise ArgumentError unless body.is_a?(Hash)
65
65
 
66
- return api_put(id, body, 'application/json') unless modify
66
+ return api.put(id, body, 'application/json') unless modify
67
67
 
68
- api_put(id, hash_for_update(describe(id).response, body),
68
+ api.put(id, hash_for_update(describe(id).response, body),
69
69
  'application/json')
70
70
  end
71
71
 
@@ -77,7 +77,7 @@ module Wavefront
77
77
  #
78
78
  def test(id)
79
79
  wf_notificant_id?(id)
80
- api_post(['test', id].uri_concat, nil)
80
+ api.post(['test', id].uri_concat, nil)
81
81
  end
82
82
  end
83
83
  end
@@ -0,0 +1,148 @@
1
+ require_relative '../defs/constants'
2
+
3
+ module Wavefront
4
+ module Paginator
5
+ #
6
+ # Automatically handle pagination. This is an abstract class
7
+ # made concrete by an extension for each HTTP request type.
8
+ #
9
+ # This class and its children do slightly unpleasant things with
10
+ # the HTTP request passed to us by the user, extracting and
11
+ # changing values in the URI, query string, or POST/PUT body.
12
+ # The POST class is particularly onerous.
13
+ #
14
+ # Automatic pagination works by letting the user override the
15
+ # limit and offset values in API calls. Setting the limit to
16
+ # :all iteratively calls the Wavefront API, returning all
17
+ # requested objects an a standard Wavefront::Response wrapper;
18
+ # setting limit to :lazy returns a lazy Enumerable. The number
19
+ # of objects fetched in each API call, whether eager or lazy
20
+ # defaults to PAGE_SIZE, but the user can override that value by
21
+ # using the offset argument in conjunction with limit = :lazy |
22
+ # :all.
23
+ #
24
+ class Base
25
+ attr_reader :api_caller, :conn, :method, :args, :page_size,
26
+ :initial_limit
27
+
28
+ # @param api_caller [Wavefront::ApiCaller] the class which
29
+ # creates an instance of this one. We need to access its
30
+ # #response method.
31
+ # @param conn [Faraday::Connection]
32
+ # @param method [Symbol] HTTP request method
33
+ # @param *args arguments to pass to Faraday's #get method
34
+ #
35
+ def initialize(api_caller, conn, method, *args)
36
+ @api_caller = api_caller
37
+ @conn = conn
38
+ @method = method
39
+ @args = args
40
+ setup_vars
41
+ end
42
+
43
+ def setup_vars
44
+ @initial_limit = limit_and_offset(args)[:limit]
45
+ @page_size = user_page_size(args) unless initial_limit.is_a?(Integer)
46
+ end
47
+
48
+ # An API call may or may not have a limit and/or offset value.
49
+ # They could (I think) be anywhere. Safely find and return
50
+ # them. If multiple elements of @args have :limit or :offset
51
+ # keys, the last value wins.
52
+ #
53
+ # @param args [Array] arguments to be passed to a Faraday
54
+ # connection object
55
+ # @return [Hash] with keys :offset and :limit. Either's value
56
+ # can be nil
57
+ #
58
+ def limit_and_offset(args)
59
+ ret = { offset: nil, limit: nil }
60
+
61
+ args.select { |a| a.is_a?(Hash) }.each_with_object(ret) do |arg|
62
+ ret[:limit] = arg[:limit] if arg.key?(:limit)
63
+ ret[:offset] = arg[:offset] if arg.key?(:offset)
64
+ end
65
+ end
66
+
67
+ # How many objects to get on each iteration? The user can pass
68
+ # it in as an alternative to the offset argument, If it's not a
69
+ # positive integer, default to 999
70
+ #
71
+ def user_page_size(args)
72
+ arg_val = limit_and_offset(args)[:offset].to_i
73
+ return arg_val if arg_val && arg_val > 0
74
+ PAGE_SIZE
75
+ end
76
+
77
+ # @param offset [Integer] where to start fetching from
78
+ # @param page_size [Integer] how many objects to fetch
79
+ # @param args [Array] arguments to pass to Faraday.get
80
+ #
81
+ def set_pagination(offset, page_size, args)
82
+ args.map do |arg|
83
+ if arg.is_a?(Hash)
84
+ arg.tap do |a|
85
+ a[:limit] = page_size if a.key?(:limit)
86
+ a[:offset] = offset if a.key?(:offset)
87
+ end
88
+ end
89
+ arg
90
+ end
91
+ end
92
+
93
+ # 'get' eagerly. Re-run the get operation, merging together
94
+ # returned items until we have them all.
95
+ # @return [Wavefront::Response]
96
+ #
97
+ # rubocop:disable Metrics/MethodLength
98
+ # rubocop:disable Metrics/AbcSize
99
+ def make_recursive_call
100
+ offset = 0
101
+ p_args = set_pagination(offset, page_size, args)
102
+ ret = api_caller.respond(conn.public_send(method, *p_args))
103
+
104
+ return ret unless ret.more_items?
105
+
106
+ loop do
107
+ offset += page_size
108
+ p_args = set_pagination(offset, page_size, p_args)
109
+ api_caller.verbosity(conn, method, *p_args)
110
+ resp = api_caller.respond(conn.public_send(method, *p_args))
111
+ raise StopIteration unless resp.ok?
112
+ ret.response.items += resp.response.items
113
+ raise StopIteration unless resp.more_items?
114
+ end
115
+
116
+ ret
117
+ end
118
+
119
+ # Return all objects using a lazy enumerator.
120
+ # @return [Enumerable] with each item being
121
+ # @raise [Wavefront::Exception::EnumerableError] if an API error
122
+ # is encountered at any point. The exception message is a
123
+ # Wavefront::Type::Status object, which will include the HTTP
124
+ # status code and any error string passed back by the API.
125
+ #
126
+ def make_lazy_call
127
+ offset = 0
128
+ p_args = set_pagination(offset, page_size, args)
129
+
130
+ Enumerator.new do |y|
131
+ loop do
132
+ offset += page_size
133
+ api_caller.verbosity(conn, method, *p_args)
134
+ resp = api_caller.respond(conn.public_send(method, *p_args))
135
+ unless resp.ok?
136
+ raise(Wavefront::Exception::EnumerableError, resp.status)
137
+ end
138
+ p_args = set_pagination(offset, page_size, p_args)
139
+ resp.response.items.map { |i| y.<< i }
140
+ raise StopIteration unless resp.more_items?
141
+ end
142
+ end.lazy
143
+ end
144
+ # rubocop:enable Metrics/AbcSize
145
+ # rubocop:enable Metrics/MethodLength
146
+ end
147
+ end
148
+ end