wavefront-sdk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +20 -0
  3. data/.gitignore +4 -0
  4. data/.rubocop.yml +1157 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +58 -0
  8. data/LICENSE.txt +27 -0
  9. data/README.md +103 -0
  10. data/Rakefile +18 -0
  11. data/lib/wavefront-sdk/alert.rb +195 -0
  12. data/lib/wavefront-sdk/base.rb +251 -0
  13. data/lib/wavefront-sdk/cloudintegration.rb +88 -0
  14. data/lib/wavefront-sdk/credentials.rb +79 -0
  15. data/lib/wavefront-sdk/dashboard.rb +157 -0
  16. data/lib/wavefront-sdk/event.rb +173 -0
  17. data/lib/wavefront-sdk/exception.rb +39 -0
  18. data/lib/wavefront-sdk/externallink.rb +77 -0
  19. data/lib/wavefront-sdk/maintenancewindow.rb +75 -0
  20. data/lib/wavefront-sdk/message.rb +36 -0
  21. data/lib/wavefront-sdk/metric.rb +52 -0
  22. data/lib/wavefront-sdk/mixins.rb +60 -0
  23. data/lib/wavefront-sdk/proxy.rb +95 -0
  24. data/lib/wavefront-sdk/query.rb +96 -0
  25. data/lib/wavefront-sdk/response.rb +56 -0
  26. data/lib/wavefront-sdk/savedsearch.rb +88 -0
  27. data/lib/wavefront-sdk/search.rb +58 -0
  28. data/lib/wavefront-sdk/source.rb +131 -0
  29. data/lib/wavefront-sdk/user.rb +108 -0
  30. data/lib/wavefront-sdk/validators.rb +395 -0
  31. data/lib/wavefront-sdk/version.rb +1 -0
  32. data/lib/wavefront-sdk/webhook.rb +73 -0
  33. data/lib/wavefront-sdk/write.rb +225 -0
  34. data/pkg/wavefront-client-3.5.0.gem +0 -0
  35. data/spec/.rubocop.yml +14 -0
  36. data/spec/spec_helper.rb +157 -0
  37. data/spec/wavefront-sdk/alert_spec.rb +83 -0
  38. data/spec/wavefront-sdk/base_spec.rb +88 -0
  39. data/spec/wavefront-sdk/cloudintegration_spec.rb +54 -0
  40. data/spec/wavefront-sdk/credentials_spec.rb +55 -0
  41. data/spec/wavefront-sdk/dashboard_spec.rb +74 -0
  42. data/spec/wavefront-sdk/event_spec.rb +83 -0
  43. data/spec/wavefront-sdk/externallink_spec.rb +65 -0
  44. data/spec/wavefront-sdk/maintenancewindow_spec.rb +48 -0
  45. data/spec/wavefront-sdk/message_spec.rb +19 -0
  46. data/spec/wavefront-sdk/metric_spec.rb +21 -0
  47. data/spec/wavefront-sdk/mixins_spec.rb +27 -0
  48. data/spec/wavefront-sdk/proxy_spec.rb +41 -0
  49. data/spec/wavefront-sdk/query_spec.rb +51 -0
  50. data/spec/wavefront-sdk/resources/test.conf +10 -0
  51. data/spec/wavefront-sdk/response_spec.rb +47 -0
  52. data/spec/wavefront-sdk/savedsearch_spec.rb +54 -0
  53. data/spec/wavefront-sdk/search_spec.rb +47 -0
  54. data/spec/wavefront-sdk/source_spec.rb +48 -0
  55. data/spec/wavefront-sdk/user_spec.rb +56 -0
  56. data/spec/wavefront-sdk/validators_spec.rb +238 -0
  57. data/spec/wavefront-sdk/webhook_spec.rb +50 -0
  58. data/spec/wavefront-sdk/write_spec.rb +167 -0
  59. data/wavefront-sdk.gemspec +34 -0
  60. metadata +269 -0
@@ -0,0 +1,56 @@
1
+ require 'json'
2
+ require_relative './exception'
3
+
4
+ module Wavefront
5
+
6
+ # Every API path has its own response class, which allows us to
7
+ # provide a stable interface. If the API changes underneath us,
8
+ # the SDK will break in a predictable way, throwing a
9
+ # Wavefront::Exception::InvalidResponse exception.
10
+ #
11
+ # Most Wavefront::Response classes present the returned data in
12
+ # two parts, each accessible by dot notation.
13
+ # #status is the status object, which normally contains
14
+ # 'result', 'message', and 'code'. It is a struct.
15
+ # #response contains the JSON response body, turned into a Ruby
16
+ # hash.
17
+ #
18
+ class Response
19
+ class Base
20
+ attr_reader :status, :response, :debug
21
+
22
+ # Create and return a Wavefront::Response object
23
+ # @param json [String] a raw response body from the Wavefront API
24
+ # @param status [Integer] HTTP return code from the API
25
+ # @param debug [Boolean] whether or not to print the exception
26
+ # message if one is thrown
27
+ # @raise Wavefront::InvalidResponse if the response cannot be
28
+ # parsed
29
+ # @return a Wavefront::Response object
30
+ #
31
+ def initialize(json, status, debug = false)
32
+ @debug = debug
33
+ populate(JSON.parse(json, symbolize_names: true), status)
34
+ rescue => e
35
+ puts e.message if debug
36
+ raise Wavefront::Exception::InvalidResponse
37
+ end
38
+
39
+ def populate(raw, _status = 200)
40
+ if raw.key?(:status)
41
+ @status = Struct.new(*raw[:status].keys).
42
+ new(*raw[:status].values).freeze
43
+ end
44
+
45
+ if raw.key?(:response)
46
+ if raw[:response].key?(:items)
47
+ @response = Struct.new(*raw[:response].keys).
48
+ new(*raw[:response].values).freeze
49
+ else
50
+ @response = raw[:response]
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,88 @@
1
+ require_relative './base'
2
+
3
+ module Wavefront
4
+ #
5
+ # View and manage Cloud Integrations. These are identified by
6
+ # a UUID.
7
+ #
8
+ class SavedSearch < Wavefront::Base
9
+
10
+ # GET /api/v2/savedsearch
11
+ # Get all saved searches for a user.
12
+ #
13
+ # @param offset [Int] saved search at which the list begins
14
+ # @param limit [Int] the number of saved searches to return
15
+ # @return [Hash]
16
+ #
17
+ def list(offset = 0, limit = 100)
18
+ api_get('', { offset: offset, limit: limit })
19
+ end
20
+
21
+ # POST /api/v2/savedsearch
22
+ # Create a saved search. Refer to the Swagger API docs for
23
+ # valid keys.
24
+ #
25
+ # @param body [Hash] description of saved search
26
+ # @return [Hash]
27
+ #
28
+ def create(body)
29
+ raise ArgumentError unless body.is_a?(Hash)
30
+ api_post('', body, 'application/json')
31
+ end
32
+
33
+ # DELETE /api/v2/savedsearch/{id}
34
+ # Delete a specific saved search.
35
+ #
36
+ # @param id [String] ID of the saved search
37
+ # @return [Hash]
38
+ #
39
+ def delete(id)
40
+ wf_savedsearch_id?(id)
41
+ api_delete(id)
42
+ end
43
+
44
+ # GET /api/v2/savedsearch/{id}
45
+ # Get a specific saved search.
46
+ #
47
+ # @param id [String] ID of the saved search
48
+ # @return [Hash]
49
+ #
50
+ def describe(id)
51
+ wf_savedsearch_id?(id)
52
+ api_get(id)
53
+ end
54
+
55
+ # PUT /api/v2/savedsearch/{id}
56
+ # Update a specific saved search.
57
+ #
58
+ # @param id [String] ID of the saved search
59
+ # @param body [Hash] description of saved search
60
+ #
61
+ def update(id, body)
62
+ wf_savedsearch_id?(id)
63
+ raise ArgumentError unless body.is_a?(Hash)
64
+ api_put(id, body)
65
+ end
66
+
67
+ # GET /api/v2/savedsearch/type/{entitytype}
68
+ # Get all saved searches for a specific entity type for a user.
69
+ #
70
+ # @param entitytype [String] type of entity to retrieve
71
+ # @param offset [Int] saved search at which the list begins
72
+ # @param limit [Int] the number of saved searches to return
73
+ # @return [Hash]
74
+ #
75
+ def entity(entitytype, offset = 0, limit = 100)
76
+ wf_savedsearch_entity?(entitytype)
77
+ api_get(['type', entitytype].uri_concat, { offset: offset,
78
+ limit: limit })
79
+
80
+ end
81
+ end
82
+
83
+ # A standard response
84
+ #
85
+ class Response
86
+ class SavedSearch < Base; end
87
+ end
88
+ end
@@ -0,0 +1,58 @@
1
+ require_relative './base'
2
+
3
+ module Wavefront
4
+ #
5
+ # Manage and query Wavefront searches. The /search API path has a
6
+ # lot of paths, with a lot of duplication. The current state of
7
+ # this class covers the whole API with two methods, but leaves a
8
+ # lot up to the user. It may grow, with convenience methods.
9
+ #
10
+ class Search < Wavefront::Base
11
+
12
+ # POST /api/v2/search/agent
13
+ # POST /api/v2/search/agent/deleted
14
+ # Run a search query. This single method maps to many API paths.
15
+ #
16
+ # @param entity [String] the type of Wavefront object you wish
17
+ # to search
18
+ # @param body [Hash] the query to use for searching. Refer to
19
+ # the Wavefront Swagger docs for the correct format.
20
+ # @param deleted [Boolean] whether to search deleted (true) or
21
+ # active (false) entities
22
+ #
23
+ def search(entity = nil, body = nil, deleted = false)
24
+ raise ArgumentError unless entity.is_a?(String)
25
+ raise ArgumentError unless body.is_a?(Hash)
26
+ path = ['agent']
27
+ path.<< 'deleted' if deleted
28
+ api_post(path, body, 'application/json')
29
+ end
30
+
31
+ # @param entity [String] the type of Wavefront object you wish
32
+ # to search
33
+ # @param body [Hash] the query to use for searching. Refer to
34
+ # the Wavefront Swagger docs for the correct format.
35
+ # @param deleted [Boolean] whether to search deleted (true) or
36
+ # active (false) entities
37
+ # @param facet [String] the facet on which to search. If this is
38
+ # false, the assumption is that multiple facets will be
39
+ # specified in the body. See the Swagger docs for more
40
+ # information.
41
+ #
42
+ def facet_search(entity = nil, body = nil, deleted = false,
43
+ facet = false)
44
+ raise ArgumentError unless entity.is_a?(String)
45
+ raise ArgumentError unless body.is_a?(Hash)
46
+ path = ['agent']
47
+ path.<< 'deleted' if deleted
48
+ path.<< facet ? facet : 'facets'
49
+ api_post(path, body, 'application/json')
50
+ end
51
+ end
52
+
53
+ # A standard response
54
+ #
55
+ class Response
56
+ class Search < Base; end
57
+ end
58
+ end
@@ -0,0 +1,131 @@
1
+ require_relative './base'
2
+
3
+ module Wavefront
4
+ #
5
+ # View and manage source metadata.
6
+ #
7
+ class Source < Wavefront::Base
8
+
9
+ # GET /api/v2/source
10
+ # Get all sources for a customer
11
+ #
12
+ # @param offset [Int] source at which the list begins
13
+ # @param limit [Int] the number of sources to return
14
+ # @return [Hash]
15
+ #
16
+ def list(offset = 0, limit = 100)
17
+ api_get('', { offset: offset, limit: limit })
18
+ end
19
+
20
+ # POST /api/v2/source
21
+ # Create metadata (description or tags) for a specific source.
22
+ #
23
+ # Refer to the Swagger API docs for valid keys.
24
+ #
25
+ # @param body [Hash] description of source
26
+ # @return [Hash]
27
+ #
28
+ def create(body)
29
+ raise ArgumentError unless body.is_a?(Hash)
30
+ api_post('', body, 'application/json')
31
+ end
32
+
33
+ # DELETE /api/v2/source/{id}
34
+ # Delete metadata (description and tags) for a specific source.
35
+ #
36
+ # @param id [String] ID of the source
37
+ # @return [Hash]
38
+ #
39
+ def delete(id)
40
+ wf_source_id?(id)
41
+ api_delete(id)
42
+ end
43
+
44
+ # GET /api/v2/source/{id}
45
+ # Get a specific source for a customer.
46
+ #
47
+ # @param id [String] ID of the source
48
+ # @return [Hash]
49
+ #
50
+ def describe(id, version = nil)
51
+ wf_source_id?(id)
52
+ wf_version?(version) if version
53
+ fragments = [id]
54
+ fragments += ['history', version] if version
55
+ api_get(fragments.uri_concat)
56
+ end
57
+
58
+ # PUT /api/v2/source/{id}
59
+ # Update metadata (description or tags) for a specific source.
60
+ #
61
+ # Refer to the Swagger API docs for valid keys.
62
+ #
63
+ # @param body [Hash] description of source
64
+ # @return [Hash]
65
+ #
66
+ def update(id, body)
67
+ wf_source_id?(id)
68
+ raise ArgumentError unless body.is_a?(Hash)
69
+ api_put(id, body)
70
+ end
71
+
72
+ # GET /api/v2/source/{id}/tag
73
+ # Get all tags associated with a specific source.
74
+ #
75
+ # @param id [String] ID of the source
76
+ # @returns [Hash] object describing the source with status and
77
+ # response keys
78
+ #
79
+ def tags(id)
80
+ wf_source_id?(id)
81
+ api_get([id, 'tag'].uri_concat)
82
+ end
83
+
84
+ # POST /api/v2/source/{id}/tag
85
+ # Set all tags associated with a specific source.
86
+ #
87
+ # @param id [String] ID of the source
88
+ # @param tags [Array] list of tags to set.
89
+ # @returns [Hash] object describing the source with status and
90
+ # response keys
91
+ #
92
+ def tag_set(id, tags)
93
+ wf_source_id?(id)
94
+ tags = Array(tags)
95
+ tags.each { |t| wf_string?(t) }
96
+ api_post([id, 'tag'].uri_concat, tags.to_json, 'application/json')
97
+ end
98
+
99
+ # DELETE /api/v2/source/{id}/tag/{tagValue}
100
+ # Remove a tag from a specific source.
101
+ #
102
+ # @param id [String] ID of the source
103
+ # @param tag [String] tag to delete
104
+ # @returns [Hash] object with 'status' key and empty 'repsonse'
105
+ #
106
+ def tag_delete(id, tag)
107
+ wf_source_id?(id)
108
+ wf_string?(tag)
109
+ api_delete([id, 'tag', tag].uri_concat)
110
+ end
111
+
112
+ # PUT /api/v2/source/{id}/tag/{tagValue}
113
+ # Add a tag to a specific source
114
+ #
115
+ # @param id [String] ID of the source
116
+ # @param tag [String] tag to set.
117
+ # @returns [Hash] object with 'status' key and empty 'repsonse'
118
+ #
119
+ def tag_add(id, tag)
120
+ wf_source_id?(id)
121
+ wf_string?(tag)
122
+ api_put([id, 'tag', tag].uri_concat)
123
+ end
124
+ end
125
+
126
+ # A standard response
127
+ #
128
+ class Response
129
+ class Source < Base; end
130
+ end
131
+ end
@@ -0,0 +1,108 @@
1
+ require_relative './base'
2
+
3
+ module Wavefront
4
+ #
5
+ # Manage and query Wavefront users
6
+ #
7
+ class User < Wavefront::Base
8
+
9
+ # GET /api/v2/user
10
+ # Get all users.
11
+ #
12
+ def list
13
+ api_get('')
14
+ end
15
+
16
+ # POST /api/v2/user
17
+ # Creates or updates a user
18
+ #
19
+ # @param body [Hash] a hash of parameters describing the user.
20
+ # Please refer to the Wavefront Swagger docs for key:value
21
+ # information
22
+ # @return [Hash]
23
+ #
24
+ def create(body, send_email = false)
25
+ raise ArgumentError unless body.is_a?(Hash)
26
+ api_post("?sendEmail=#{send_email}", body, 'application/json')
27
+ end
28
+
29
+ # DELETE /api/v2/user/{id}
30
+ # Delete a specific user.
31
+ #
32
+ # @param id [String] ID of the user
33
+ # @return [Hash]
34
+ #
35
+ def delete(id)
36
+ wf_user_id?(id)
37
+ api_delete(id)
38
+ end
39
+
40
+ # GET /api/v2/user/{id}
41
+ # Retrieves a user by identifier (email addr).
42
+ #
43
+ # @param id [String] ID of the user
44
+ # @return [Hash]
45
+ #
46
+ def describe(id)
47
+ wf_user_id?(id)
48
+ api_get(id)
49
+ end
50
+
51
+ # PUT /api/v2/user/{id}/grant
52
+ # Grants a specific user permission.
53
+ #
54
+ # @param id [String] ID of the user
55
+ # @param group [String] group to add user to. We do not validate
56
+ # this so that changes to the API do not mandate changes to
57
+ # the SDK. At the time of writing, valid values are browse,
58
+ # agent_management, alerts_management, dashboard_management,
59
+ # embedded_charts, events_management,
60
+ # external_links_management, host_tag_management,
61
+ # metrics_management, user_management,
62
+ # @return [Hash]
63
+ #
64
+ def grant(id, group)
65
+ wf_user_id?(id)
66
+ raise ArgumentError unless group.is_a?(String)
67
+ api_post([id, 'grant'].uri_concat, "group=#{group}",
68
+ 'application/x-www-form-urlencoded')
69
+ end
70
+
71
+ # PUT /api/v2/user/{id}/revoke
72
+ # Revokes a specific user permission.
73
+ #
74
+ # @param id [String] ID of the user
75
+ # @param group [String] group to add user to. We do not validate
76
+ # this so that changes to the API do not mandate changes to
77
+ # the SDK. See #update for valid values.
78
+ # @return [Hash]
79
+ #
80
+ def revoke(id, group)
81
+ wf_user_id?(id)
82
+ raise ArgumentError unless group.is_a?(String)
83
+ api_post([id, 'revoke'].uri_concat, "group=#{group}",
84
+ 'application/x-www-form-urlencoded')
85
+ end
86
+ end
87
+
88
+ class Response
89
+
90
+ # The User response forges status and response methods to look
91
+ # like other classes and create a more consistent interface.
92
+ #
93
+ class User < Base
94
+ def populate(raw, status)
95
+ @response = if raw.is_a?(Array)
96
+ Struct.new(:items).new(raw).freeze
97
+ elsif raw.is_a?(Hash)
98
+ Struct.new(*raw.keys).new(*raw.values).freeze
99
+ end
100
+
101
+ result = status == 200 ? 'OK' : 'ERROR'
102
+
103
+ @status = Struct.new(:result, :message, :code).
104
+ new(result, nil, status)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,395 @@
1
+ require_relative './exception'
2
+
3
+ module Wavefront
4
+ #
5
+ # A module of mixins to validate input. The Wavefront documentation
6
+ # lays down restrictions on types and sizes of various inputs, which
7
+ # we will check on the user's behalf. Most of the information used in
8
+ # this file comes from https://community.wavefront.com/docs/DOC-1031
9
+ # Some comes from the Swagger API documentation, some has come
10
+ # directly from Wavefront engineers.
11
+ #
12
+ module Validators
13
+
14
+ # Ensure the given argument is a valid external link template
15
+ #
16
+ # @return true if it is valid
17
+ # @raise Wavefront::Exception::InvalidTemplate if not
18
+ #
19
+ def wf_link_template?(v)
20
+ if v.is_a?(String) && (v.start_with?('http://') ||
21
+ v.start_with?('https://'))
22
+ return true
23
+ end
24
+
25
+ raise Wavefront::Exception::InvalidLinkTemplate
26
+ end
27
+
28
+ # Ensure the given argument is a valid Wavefront metric name, or
29
+ # path.
30
+ #
31
+ # @param v [String] the metric name to validate
32
+ # @return True if the metric name is valid
33
+ # @raise Wavefront::Exception::InvalidMetricName if metric name
34
+ # is not valid.
35
+ #
36
+ def wf_metric_name?(v)
37
+ if v.is_a?(String) && v.size < 1024 &&
38
+ (v.match(/^[\w\-\.]+$/) || v.match(%r{^\"[\w\-\.\/,]+\"$}))
39
+ return true
40
+ end
41
+
42
+ raise Wavefront::Exception::InvalidMetricName
43
+ end
44
+
45
+ # Ensure the given argument is a valid name, for instance for an
46
+ # event. Names can contain, AFAIK, word characters.
47
+ #
48
+ # @param v [String] the name to validate
49
+ # @return true if the name is valid
50
+ # raise Wavefront::Exception::InvalidName if name is not valid
51
+ #
52
+ def wf_name?(v)
53
+ return true if v.is_a?(String) && v.size < 1024 && v =~ /^\w+$/
54
+ raise Wavefront::Exception::InvalidName
55
+ end
56
+
57
+ # Ensure the given argument is a valid string, for a tag name.
58
+ #
59
+ # @param v [String] the string name to validate
60
+ # @return True if the string is valid
61
+ # @raise Wavefront::Exception::InvalidString if string is not valid.
62
+ #
63
+ def wf_string?(v)
64
+ #
65
+ # Only allows PCRE "word" characters, spaces, full-stops and
66
+ # commas in tags and descriptions. This might be too restrictive,
67
+ # but if it is, this is the only place we need to change it.
68
+ #
69
+ return true if v.is_a?(String) && v.size < 1024 && v =~ /^[\-\w \.,]*$/
70
+
71
+ raise Wavefront::Exception::InvalidString
72
+ end
73
+
74
+ # Ensure the given argument is a valid timestamp
75
+ #
76
+ # @param v [DateTime] the timestamp name to validate
77
+ # @return True if the value is valid
78
+ # @raise Wavefront::Exception::InvalidTimestamp
79
+ #
80
+ def wf_ts?(v)
81
+ return true if v.is_a?(Time) || v.is_a?(Date)
82
+ raise Wavefront::Exception::InvalidTimestamp
83
+ end
84
+
85
+ # Ensure the given argument is a valid millisecond epoch
86
+ # timestamp. We do no checking of the value, because who am I to
87
+ # say that the user doesn't want to send a point relating to 1ms
88
+ # after the epoch, or a thousand years in the future?
89
+ #
90
+ # @param v [Integer] the timestamp name to validate
91
+ # @return True if the value is valid
92
+ # @raise Wavefront::Exception::InvalidTimestamp
93
+ #
94
+ def wf_ms_ts?(v)
95
+ return true if v.is_a?(Numeric)
96
+ raise Wavefront::Exception::InvalidTimestamp
97
+ end
98
+
99
+ # Ensure the given argument is a valid epoch timestamp. Again,
100
+ # no range checking.
101
+ #
102
+ # @param v [String, Integer]
103
+ # @return True if the timestamp is valid
104
+ # @raise Wavefront::Exception::InvalidMaintenanceWindow
105
+ #
106
+ def wf_epoch?(v)
107
+ return true if v.is_a?(Numeric)
108
+ raise Wavefront::Exception::InvalidTimestamp
109
+ end
110
+
111
+ # Ensure one, or an array, of tags are valid. These tags are
112
+ # used as source tags, or tags for maintenance windows etc. They
113
+ # can contain letters, numbers, -, _ and :, and must be less
114
+ # than 256 characters long
115
+ #
116
+ # @param v [String, Array] a tag or list of tags
117
+ # @return True if all tags are valid
118
+ # @raise Wavefront::Exception::InvalidTag
119
+ #
120
+ def wf_tag?(*v)
121
+ Array(*v).each do |t|
122
+ unless t.is_a?(String) && t.size < 255 && t =~ /^[\w:\-\.]+$/
123
+ raise Wavefront::Exception::InvalidTag
124
+ end
125
+ end
126
+
127
+ true
128
+ end
129
+
130
+ # Ensure the given argument is a valid Wavefront value. Can be
131
+ # any form of Numeric, including standard notation.
132
+ #
133
+ # @param v [Numeric] the source name to validate
134
+ # @return True if the value is valid
135
+ # @raise Wavefront::Exception::InvalidValue if the value is not valid
136
+ #
137
+ def wf_value?(v)
138
+ return true if v.is_a?(Numeric)
139
+ raise Wavefront::Exception::InvalidMetricValue
140
+ end
141
+
142
+ # Ensure the given argument is a valid version number
143
+ #
144
+ # @param [Integer] the version number to validate
145
+ # @return True if the version is valid
146
+ # @raise Wavefront::Exception::InvalidVersion if the alert ID is
147
+ # not valid
148
+ #
149
+ def wf_version?(v)
150
+ v = v.to_i if v.is_a?(String) && v =~ /^\d+$/
151
+ return true if v.is_a?(Integer) && v > 0
152
+ raise Wavefront::Exception::InvalidVersion
153
+ end
154
+
155
+ # Ensure a hash of key:value point tags are value. Not to be
156
+ # confused with source tags.
157
+ #
158
+ # @param tags [Hash] a hash of key:value tags
159
+ # @return True if all tags are valid
160
+ # @raise Wavefront::Exception::InvalidTag if any tags in the has
161
+ # do not validate
162
+ #
163
+ def wf_point_tags?(tags)
164
+ raise Wavefront::Exception::InvalidTag unless tags.is_a?(Hash)
165
+
166
+ tags.each do |k, v|
167
+ unless (k.size + v.size < 254) && k.match(/^[\w\-\.:]+$/)
168
+ raise Wavefront::Exception::InvalidTag
169
+ end
170
+ end
171
+ true
172
+ end
173
+
174
+ # Ensure the given argument is a valid Wavefront proxy ID
175
+ #
176
+ # @param v [String] the proxy ID to validate
177
+ # @return True if the proxy ID is valid
178
+ # @raise Wavefront::Exception::InvalidProxyId if the proxy ID
179
+ # is not valid
180
+ #
181
+ def wf_proxy_id?(v)
182
+ if v.is_a?(String) && v.match(
183
+ /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/
184
+ )
185
+ return true
186
+ end
187
+
188
+ raise Wavefront::Exception::InvalidProxyId
189
+ end
190
+
191
+ # Ensure the given argument is a valid Wavefront alert ID.
192
+ # Alerts are identified by the epoch-nanosecond at which they
193
+ # were created.
194
+ #
195
+ # @param v [String] the alert ID to validate
196
+ # @return True if the alert ID is valid
197
+ # @raise Wavefront::Exception::InvalidAlertId if the alert ID is
198
+ # not valid
199
+ #
200
+ def wf_alert_id?(v)
201
+ v = v.to_s if v.is_a?(Numeric)
202
+ return true if v.is_a?(String) && v.match(/^\d{13}$/)
203
+ raise Wavefront::Exception::InvalidAlertId
204
+ end
205
+
206
+ # Ensure the given argument is a valid Wavefront cloud
207
+ # integration ID
208
+ #
209
+ # @param v [String] the integration name to validate
210
+ # @return True if the integration name is valid
211
+ # @raise Wavefront::Exception::InvalidCloudIntegrationId if the
212
+ # integration ID is not valid
213
+ #
214
+ def wf_cloudintegration_id?(v)
215
+ if v.is_a?(String) && v.match(
216
+ /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/
217
+ )
218
+ return true
219
+ end
220
+
221
+ raise Wavefront::Exception::InvalidCloudIntegrationId
222
+ end
223
+
224
+ # There doesn't seem to be a public statement on what's allowed
225
+ # in a dashboard name. For now I'm going to assume up to 255 word
226
+ # characters.
227
+ #
228
+ # @param v [String] the dashboard ID to validate
229
+ # @return true if the dashboard ID is valid
230
+ # @raise Wavefront::Exception::InvalidDashboardID if the
231
+ # dashboard ID is not valid
232
+ #
233
+ def wf_dashboard_id?(v)
234
+ return true if v.is_a?(String) && v.size < 256 && v.match(/^[\w\-]+$/)
235
+ raise Wavefront::Exception::InvalidDashboardId
236
+ end
237
+
238
+ # Ensure the given argument is a valid event ID. Event IDs are
239
+ # an epoch-millisecond timestamp followed by a : followed by the
240
+ # name of the event.
241
+ #
242
+ # @param v [String] the event ID to validate
243
+ # @return true if the event ID is valid
244
+ # @raise Wavefront::Exception::InvalidEventID if the
245
+ # event ID is not valid
246
+ #
247
+ def wf_event_id?(v)
248
+ return true if v.is_a?(String) && v =~ /^\d{13}:[\w\- ]+$/
249
+ raise Wavefront::Exception::InvalidEventId
250
+ end
251
+
252
+ # Ensure the given argument is a valid external Link ID
253
+ #
254
+ # @param v [String] the external link ID to validate
255
+ # @return True if the link ID is valid
256
+ # @raise Wavefront::Exception::InvalidExternalLinkId if the
257
+ # link ID is not valid
258
+ #
259
+ def wf_link_id?(v)
260
+ return true if v.is_a?(String) && v =~ /^\w{16}$/
261
+ raise Wavefront::Exception::InvalidExternalLinkId
262
+ end
263
+
264
+ # Ensure the given argument is a valid maintenance window ID.
265
+ # IDs are the millisecond epoch timestamp at which the window
266
+ # was created.
267
+ #
268
+ # @param v [String, Integer]
269
+ # @return True if the ID is valid
270
+ # @raise Wavefront::Exception::InvalidMaintenanceWindowId
271
+ #
272
+ def wf_maintenance_window_id?(v)
273
+ v = v.to_s if v.is_a?(Numeric)
274
+ return true if v.is_a?(String) && v =~ /^\d{13}$/
275
+
276
+ raise Wavefront::Exception::InvalidMaintenanceWindowId
277
+ end
278
+
279
+ # Ensure the given argument is a valid alert severity
280
+ #
281
+ # @param v [String] severity
282
+ # @return true if valid
283
+ # @raise Wavefront::Exceptions::InvalidAlertSeverity if not
284
+ # valid
285
+ #
286
+ def wf_alert_severity?(v)
287
+ return true if %w(INFO SMOKE WARN SEVERE).include?(v)
288
+ raise Wavefront::Exception::InvalidAlertSeverity
289
+ end
290
+
291
+ # Ensure the given argument is a valid message ID
292
+ #
293
+ # @param v [String] severity
294
+ # @return true if valid
295
+ # @raise Wavefront::Exceptions::InvalidMessageId if not
296
+ # valid
297
+ #
298
+ def wf_message_id?(v)
299
+ return true if v.is_a?(String) && v =~ /^\w+$/
300
+ raise Wavefront::Exception::InvalidMessageId
301
+ end
302
+
303
+ # Ensure the given argument is a valid query granularity
304
+ #
305
+ # @param v [String] granularity
306
+ # @return true if valid
307
+ # @raise Wavefront::Exceptions::InvalidGranularity if not
308
+ # valid
309
+ #
310
+ def wf_granularity?(v)
311
+ return true if %w(d h m s).include?(v.to_s)
312
+ raise Wavefront::Exception::InvalidGranularity
313
+ end
314
+
315
+ # Ensure the given argument is a valid saved search ID.
316
+ #
317
+ # @param v [String] saved search ID
318
+ # @return true if valid
319
+ # @raise Wavefront::Exceptions::InvalidSavedSearchId if not valid
320
+ #
321
+ def wf_savedsearch_id?(v)
322
+ return true if v.is_a?(String) && v =~ /^\w{8}$/
323
+ raise Wavefront::Exception::InvalidSavedSearchId
324
+ end
325
+
326
+ # Ensure the given argument is a valid saved search entity type.
327
+ #
328
+ # @param v [String] entity type
329
+ # @return true if valid
330
+ # @raise Wavefront::Exceptions::InvalidSavedSearchEntity if not
331
+ # valid
332
+ #
333
+ def wf_savedsearch_entity?(v)
334
+ return true if %w(DASHBOARD ALERT MAINTENANCE_WINDOW
335
+ NOTIFICANT EVENT SOURCE EXTERNAL_LINK AGENT
336
+ CLOUD_INTEGRATION).include?(v)
337
+ raise Wavefront::Exception::InvalidSavedSearchEntity
338
+ end
339
+
340
+ # Ensure the given argument is a valid Wavefront source name
341
+ #
342
+ # @param v [String] the source name to validate
343
+ # @return True if the source name is valid
344
+ # @raise Wavefront::Exception::InvalidSourceId if the source name
345
+ # is not valid
346
+ #
347
+ def wf_source_id?(v)
348
+ if v.is_a?(String) && v.match(/^[\w\.\-]+$/) && v.size < 1024
349
+ return true
350
+ end
351
+
352
+ raise Wavefront::Exception::InvalidSourceId
353
+ end
354
+
355
+ # Ensure the given argument is a valid user.
356
+ #
357
+ # @param v [String] user identifier
358
+ # @return true if valid
359
+ # @raise Wavefront::Exceptions::InvalidUserId if not valid
360
+ #
361
+ def wf_user_id?(v)
362
+ return true if v.is_a?(String) &&
363
+ v =~ /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
364
+ raise Wavefront::Exception::InvalidUserId
365
+ end
366
+
367
+ # Ensure the given argument is a valid webhook ID.
368
+ #
369
+ # @param v [String] webhook ID
370
+ # @return true if valid
371
+ # @raise Wavefront::Exceptions::InvalidWebhook if not valid
372
+ #
373
+ def wf_webhook_id?(v)
374
+ return true if v.is_a?(String) && v =~ /^[a-zA-Z0-9]{16}$/
375
+ raise Wavefront::Exception::InvalidWebhookId
376
+ end
377
+
378
+ # Validate a point so it conforms to the standard described in
379
+ # https://community.wavefront.com/docs/DOC-1031
380
+ #
381
+ # @param v [Hash] description of point
382
+ # @return true if valie
383
+ # @raise whichever exception is thrown first when validating
384
+ # each component of the point.
385
+ #
386
+ def wf_point?(v)
387
+ wf_metric_name?(v[:path])
388
+ wf_value?(v[:value])
389
+ wf_epoch?(v[:ts]) if v[:ts]
390
+ wf_source_id?(v[:source]) if v[:source]
391
+ wf_point_tags?(v[:tags]) if v[:tags]
392
+ true
393
+ end
394
+ end
395
+ end