snitcher 0.4.0.pre2 → 0.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52b46733dac8b3d6892d836ce73c27527c705f4c
4
- data.tar.gz: 8117b728733b857dd8840491a6fa16f0a2db6ba0
3
+ metadata.gz: 85ae5078348c51d73c8830f198ff49a276a5ef36
4
+ data.tar.gz: 18bf74b6a9b887f3ca6c213cbf2cd38bb7814be0
5
5
  SHA512:
6
- metadata.gz: fe9a30bdb596ffc377f951fd853ac66b00b22370cde6989224bd7a9e8ffa05a8b5a8832f14e74b0a779d458a29c4216e8efd8098720311c53fdb15491460dad0
7
- data.tar.gz: f37a6ee3a9473e27e2a905bb81469c7df72990f3a35c16cc5892ffa5961ac92b5a52e7917af65a223767004666464104e6c2f7cce04ea620186e441f813d5318
6
+ metadata.gz: fabe574bb26a7766144e532bcf6e12562e2a9ad0d8029dd5e04984ba5ba97ac5de44b7da7dba229618bfc388d43639182f38d5cfb3ba6f5b5b53688329b89d55
7
+ data.tar.gz: b67166b247c7648b4d6a18a22c0894373176afb7bd5b62ecb5595770e9b25ced02462360c408ee69db4ff95c6ed1fa845d7f01c95ccc2becb87e61790c7cc70e
data/Gemfile CHANGED
@@ -4,10 +4,11 @@ gemspec
4
4
 
5
5
  group :development do
6
6
  gem "pry"
7
+ gem "yard-ghpages"
7
8
  end
8
9
 
9
10
  group :test do
10
11
  gem "coveralls", require: false
11
12
  gem "rspec"
12
- gem "webmock"
13
+ gem "webmock", ">= 2.0"
13
14
  end
data/README.md CHANGED
@@ -68,7 +68,7 @@ client = Snitcher::API::Client.new(ENV["DEADMANSSNITCH_API_KEY"])
68
68
  client.snitches
69
69
  ```
70
70
 
71
- Returns an array of snitches.
71
+ Returns an array of Snitches.
72
72
 
73
73
  ### Retrieve a Single Snitch
74
74
 
@@ -77,7 +77,7 @@ token = "c2354d53d2"
77
77
  client.snitch(token)
78
78
  ```
79
79
 
80
- Returns a snitch.
80
+ Returns a Snitch.
81
81
 
82
82
  ### Retrieve Snitches That Match a Set of Tags
83
83
 
@@ -86,11 +86,12 @@ tags = ["critical", "sales"]
86
86
  client.tagged_snitches(tags)
87
87
  ```
88
88
 
89
- Returns an array of snitches.
89
+ Returns an array of Snitches.
90
90
 
91
91
  ### Create a Snitch
92
92
 
93
- Required attributes are name and interval. Optional attributes are notes and tags.
93
+ Required attributes are name and interval. Optional attributes are notes and
94
+ tags.
94
95
 
95
96
  ```ruby
96
97
  attributes = { "name": "Nightly User Data Backups",
@@ -101,23 +102,24 @@ attributes = { "name": "Nightly User Data Backups",
101
102
  client.create_snitch(attributes)
102
103
  ```
103
104
 
104
- Returns the newly-created snitch.
105
+ Returns the newly-created Snitch.
105
106
 
106
- ### Edit a Snitch
107
+ ### Updating a Snitch
107
108
 
108
- You only need to pass the edit_snitch function the attributes you want to change. The rest of a snitch's attributes will remain the same.
109
+ You only need to pass the update_snitch function the attributes you want to
110
+ change. The rest of a Snitch's attributes will remain the same.
109
111
 
110
112
  ```ruby
111
113
  token = "c2354d53d2"
112
114
  new_attributes = { "name": "Important Nightly User Data Backups" }
113
- client.edit_snitch(token, new_attributes)
115
+ client.update_snitch(token, new_attributes)
114
116
  ```
115
117
 
116
- Returns the edited snitch.
118
+ Returns the edited Snitch.
117
119
 
118
120
  ### Adding Tags to a Snitch
119
121
 
120
- This function adds tags to a snitch, retaining whatever tags it already has.
122
+ This function adds tags to a Snitch, retaining whatever tags it already has.
121
123
 
122
124
  ```ruby
123
125
  token = "c2354d53d2"
@@ -125,11 +127,11 @@ tags = ["spring_campaign", "support"]
125
127
  client.add_tags(token, tags)
126
128
  ```
127
129
 
128
- Returns an array of all of the snitch's tags.
130
+ Returns an array of all of the Snitch's tags.
129
131
 
130
132
  ### Deleting a Tag From a Snitch
131
133
 
132
- This function is for deleting a single tag from a snitch.
134
+ This function is for deleting a single tag from a Snitch.
133
135
 
134
136
  ```ruby
135
137
  token = "c2354d53d2"
@@ -137,11 +139,11 @@ tag = "support"
137
139
  client.remove_tag(token, tag)
138
140
  ```
139
141
 
140
- Returns an array of all of the snitch's remaining tags.
142
+ Returns an array of all of the Snitch's remaining tags.
141
143
 
142
144
  ### Replace Tags on a Snitch
143
145
 
144
- Replaces all of a snitch's tags with an array of new tags.
146
+ Replaces all of a Snitch's tags with an array of new tags.
145
147
 
146
148
  ```ruby
147
149
  token = "c2354d53d2"
@@ -149,18 +151,18 @@ tags = ["csv", "server_a"]
149
151
  client.replace_tags(token, tags)
150
152
  ```
151
153
 
152
- Returns the updated snitch.
154
+ Returns the updated Snitch.
153
155
 
154
156
  ### Remove Tags From a Snitch
155
157
 
156
- Removes all of a snitch's tags.
158
+ Removes all of a Snitch's tags.
157
159
 
158
160
  ```ruby
159
161
  token = "c2354d53d2"
160
162
  client.clear_tags(token)
161
163
  ```
162
164
 
163
- Returns the updated snitch.
165
+ Returns the updated Snitch.
164
166
 
165
167
  ### Pause a Snitch
166
168
 
data/Rakefile CHANGED
@@ -1,8 +1,10 @@
1
1
  require "bundler"
2
- require "rspec/core/rake_task"
3
-
4
2
  Bundler::GemHelper.install_tasks
5
3
 
4
+ require "rspec/core/rake_task"
6
5
  RSpec::Core::RakeTask.new(:spec)
7
6
 
7
+ require "yard-ghpages"
8
+ Yard::GHPages::Tasks.install_tasks
9
+
8
10
  task default: :spec
@@ -6,20 +6,28 @@ require "snitcher/version"
6
6
  module Snitcher
7
7
  extend self
8
8
 
9
- # Public: Check-in to Deadman's Snitch
9
+ # Check-in to Dead Man's Snitch.
10
10
  #
11
- # token: The Snitch token given by Deadman's Snitch (see the install page).
12
- # opts: The hash of optional parameters that can be given during check-in:
13
- # :message - Text message limited to ~250 characters.
14
- # :timeout - Number of seconds to set as connect and read timeout.
15
- # :uri - URL to use for snitch checkins.
11
+ # @param token [String] The unique Snitch token to check-in with. This can be
12
+ # found on the Setup page as the last part of the HTTP check-in url. For
13
+ # example, c2354d53d2 is the token in http://nosnch.in/c2354d53d2.
16
14
  #
17
- # Examples
15
+ # @param [Hash] opts
18
16
  #
17
+ # @option opts [String] :message Text message to include with the check-in.
18
+ # The message is limited to 256 characters.
19
+ #
20
+ # @option opts [Float, Fixnum] :timeout Number of seconds to wait for a
21
+ # response from the server. Default is 5 seconds.
22
+ # no
23
+ #
24
+ # @example
19
25
  # Snitch.snitch("c2354d53d2")
20
26
  # # => true
21
27
  #
22
- # Returns true if the check-in succeeded or false if it failed
28
+ # @raise [Timeout::Error] if the request took too long and timed out.
29
+ #
30
+ # @return [Boolean] if the check-in succeeded.
23
31
  def snitch(token, opts = {})
24
32
  uri = URI.parse(checkin_url(opts, token))
25
33
  uri.query = URI.encode_www_form(m: opts[:message]) if opts[:message]
@@ -12,23 +12,25 @@ module Snitcher
12
12
  # Snitcher::API::Error and subclasses
13
13
  require "snitcher/api/error"
14
14
 
15
- # Public: Retrieve API Key
15
+ # Retrieve an API Key for your account.
16
16
  #
17
- # username: The username associated with a Deadman's Snitch account
18
- # password: The password associated with a Deadman's Snitch account
17
+ # @param username [String] username for your Dead Man's Snitch account.
18
+ # @param password [String] password for your Dead Man's Snitch account.
19
19
  #
20
- # options:
21
- # uri - String URL of the DMS API to connect to.
22
- # timeout - Number of seconds to wait for open, read, and ssl handshake.
23
- #
24
- # Example
20
+ # @param [Hash] options
21
+ # @option options [String] uri location of alternative Dead Man's Snitch API
22
+ # @option timeout [Float, Fixnum] timeout number of seconds to wait for
23
+ # server response before timing out.
25
24
  #
25
+ # @example
26
26
  # Snitcher::API.get_key("alice@example.com", "password")
27
27
  # # => "_caeEiZXnEyEzXXYVh2NhQ"
28
28
  #
29
- # Returns the string api_key
30
- # Raises Snitcher::API::Error based on the type from the server.
31
- # Raises Timeout::Error if the request timed out.
29
+ # @raise [Timeout::Error] if the API request took too long to execute.
30
+ # @raise [Snitcher::API::AuthenticationError] credentials are invalid.
31
+ # @raise [Snitcher::API::Error] if any other API errors occur.
32
+ #
33
+ # @return [String] the API key to use for further API requests.
32
34
  def get_key(username, password, options={})
33
35
  api = options.fetch(:uri, "https://api.deadmanssnitch.com")
34
36
  uri = URI.parse("#{api}/v1/api_key")
@@ -10,19 +10,21 @@ require "snitcher/api/error"
10
10
  class Snitcher::API::Client
11
11
  DEFAULT_ENDPOINT = "https://api.deadmanssnitch.com"
12
12
 
13
- # Public: Create a new Client
13
+ # Create a new API Client for taling to Dead Man's Snitch's API.
14
14
  #
15
- # key - Access key available at https://deadmanssnitch.com/account/keys.
15
+ # @param key [String] API access key (available at
16
+ # https://deadmanssnitch.com/account/keys).
16
17
  #
17
- # options
18
- # endpoint - String URL of the DMS API connecting to.
19
- # timeout - Number of seconds to wait at most when making a request.
18
+ # @param [Hash] options advanced options for customizing the client
19
+ # @option options [String] :endpoint URL of the DMS API to connect to
20
+ # @option options [Float, Fixnum] :timeout number of seconds to wait at most
21
+ # for a response from the API.
20
22
  #
21
- # Example
22
- #
23
- # Initialize API client for user with api key "abc123"
24
- # @client = Snitcher::API::Client.new("abc123")
23
+ # @example Creating a new Client with an API key
24
+ # client = Snitcher::API::Client.new("abc123")
25
+ # # => #<Snitcher::API::Client...>
25
26
  #
27
+ # @return [Snitcher::API::Client] New API Client.
26
28
  def initialize(key, options = {})
27
29
  endpoint = options[:endpoint] || DEFAULT_ENDPOINT
28
30
 
@@ -31,70 +33,58 @@ class Snitcher::API::Client
31
33
  @timeout = options.fetch(:timeout, 5.0)
32
34
  end
33
35
 
34
- # Public: List snitches on the account
36
+ # Get the list snitches on the account
35
37
  #
36
- # Example
38
+ # @example List the Snitches on an account
39
+ # client.snitches
40
+ # # => [ #<Snitcher::API::Snitch:...>, #<Snitcher::API::Snitch:...> ]
37
41
  #
38
- # Get a list of all snitches
39
- # @client.snitches
40
- # => [#<Snitcher::API::Snitch:0x007fdcf51ec380 @token="c2354d53d3",
41
- # @name="Daily Backups", @tags=["production", "critical"],
42
- # @status="healthy", @checked_in_at="2014-01-01T12:00:00.000Z",
43
- # @interval="daily", @check_in_url="https://nosnch.in/c2354d53d3",
44
- # @created_at="2014-01-01T08:00:00.000Z", @notes=nil>,
45
- # #<Snitcher::API::Snitch:0x007fdcf51ec358 @token="c2354d53d4",
46
- # @name="Hourly Emails", @tags=[], @status="healthy",
47
- # @checked_in_at="2014-01-01T12:00:00.000Z", @interval="hourly",
48
- # @check_in_url="https://nosnch.in/c2354d53d4",
49
- # @created_at="2014-01-01T07:50:00.000Z", @notes=nil>]
42
+ # @raise [Timeout::Error] if the API request took too long to execute.
43
+ # @raise [Snitcher::API::Error] if any API errors occur.
50
44
  #
51
- # Raise Timeout::Error if the API request times out
45
+ # @return [Array<Snitcher::API::Snitch>] the snitches on the account.
52
46
  def snitches
53
47
  snitch_array(get("/v1/snitches"))
54
48
  end
55
49
 
56
- # Public: Get a single snitch by unique token
50
+ # Get a single Snitch by it's unique token.
57
51
  #
58
- # token: The unique token of the snitch to get. Should be a string.
52
+ # @param token [String] The unique token of the Snitch to get
59
53
  #
60
- # Example
54
+ # @example Get the Snitch with token "c2354d53d2"
55
+ # client.snitch("c2354d53d2")
61
56
  #
62
- # Get the snitch with token "c2354d53d2"
57
+ # # => #<Snitcher::API:: @token="c2354d53d2" ...>
63
58
  #
64
- # @client.snitch("c2354d53d2")
65
- # => #<Snitcher::API::Snitch:0x007fdcf50ad2d0 @token="c2354d53d3",
66
- # @name="Daily Backups", @tags=["production", "critical"],
67
- # @status="pending", @checked_in_at=nil, @interval="daily",
68
- # @check_in_url="https://nosnch.in/c2354d53d3",
69
- # @created_at="2015-08-15T12:15:00.234Z",
70
- # @notes="Important user data.">
59
+ # @raise [Timeout::Error] if the API request took too long to execute.
60
+ # @raise [Snitcher::API::ResourceNotFoundError] if a Snitch does not exist
61
+ # with that token
62
+ # @raise [Snitcher::API::Error] if any other API errors occur.
71
63
  #
72
- # Raise Timeout::Error if the API request times out
64
+ # @return [Snitcher::API::Snitch] the Snitch
73
65
  def snitch(token)
74
66
  payload = get("/v1/snitches/#{token}")
75
67
  Snitcher::API::Snitch.new(payload)
76
68
  end
77
69
 
78
- # Public: Retrieve snitches that match all of the tags in a list
70
+ # Retrieve Snitches filtered by a list of tags. Only Snitches that are tagged
71
+ # with all of the given tags will be returned.
79
72
  #
80
- # tags: An array of strings. Each string is a tag.
73
+ # @param tags [String, Array<String>] the tag(s) to filter by.
81
74
  #
82
- # Example
75
+ # @example Get the snitches that match a list of tags
76
+ # client.tagged_snitches(["production","critical"])
83
77
  #
84
- # Get the snitches that match a list of tags
85
- # @client.tagged_snitches(["production","critical"])
86
- # => [#<Snitcher::API::Snitch:0x007fdcf51ec380 @token="c2354d53d3",
87
- # @name="Daily Backups", @tags=["production", "critical"],
88
- # @status="pending", @checked_in_at=nil, @interval="daily",
89
- # @check_in_url="https://nosnch.in/c2354d53d3",
90
- # @created_at="2014-01-01T08:00:00.000Z", @notes=nil>,
91
- # #<Snitcher::API::Snitch:0x007fdcf51ec358 @token="c2354d53d4",
92
- # @name="Hourly Emails", @tags=["production", "critical"],
93
- # @status="healthy", @checked_in_at="2014-01-01T12:00:00.000Z",
94
- # @interval="hourly", @check_in_url="https://nosnch.in/c2354d53d4",
95
- # @created_at="2014-01-01T07:50:00.000Z", @notes=nil>]
78
+ # # => [
79
+ # #<Snitcher::API::Snitch tags=["production", "critical"]>,
80
+ # #<Snitcher::API::Snitch tags=["production", "critical"]>,
81
+ # ]
96
82
  #
97
- # Raise Timeout::Error if the API request times out
83
+ # @raise [Timeout::Error] if the API request took too long to execute.
84
+ # with that token
85
+ # @raise [Snitcher::API::Error] if any API errors occur.
86
+ #
87
+ # @return [Array<Snitcher::API::Snitch>] list of Snitches matching all tags.
98
88
  def tagged_snitches(*tags)
99
89
  (tags ||= []).flatten!
100
90
 
@@ -107,204 +97,179 @@ class Snitcher::API::Client
107
97
  snitch_array(get("/v1/snitches?#{query}"))
108
98
  end
109
99
 
110
- # Public: Create a snitch using passed-in values. Returns the new snitch.
111
- #
112
- # attributes: A hash of the snitch properties. It should include these keys:
113
- # "name": String value is the name of the snitch
114
- # "interval": String value representing how often the snitch is
115
- # expected to fire. Options are "hourly", "daily",
116
- # "weekly", "monthly"
117
- # "notes": Optional string value for recording additional
118
- # information about the snitch
119
- # "tags": Optional array of string tags
120
- #
121
- # Example
122
- #
123
- # Create a new snitch
124
- # attributes = {
125
- # "name": "Daily Backups",
126
- # "interval": "daily",
127
- # "notes": "Customer and supplier tables",
128
- # "tags": ["backups", "maintenance"]
129
- # }
130
- # @client.create_snitch(attributes)
131
- # => #<Snitcher::API::Snitch:0x007fdcf50ad2d0 @token="c2354d53d3",
132
- # @name="Daily Backups", @tags=["backups", "maintenance"],
133
- # @status="pending", @checked_in_at=nil, @interval="daily",
134
- # @check_in_url="https://nosnch.in/c2354d53d3",
135
- # @created_at="2015-08-15T12:15:00.234Z",
136
- # @notes="Customer and supplier tables">
137
- #
138
- # Raise Timeout::Error if the API request times out
100
+ # Create a new Snitch.
101
+ #
102
+ # @param [Hash] attributes The properties for the new Snitch
103
+ # @option attributes [String] :name The label used for the Snitch
104
+ # @option attributes [String] :interval How often the snitch is expected to
105
+ # check-in. One of: "15_minute", "30_minute", "hourly", "daily", "weekly",
106
+ # or "monthly".
107
+ # @option attributes [optional, String] :notes Additional information about
108
+ # the Snitch. Useful to put instructions of investigating or fixing any
109
+ # errors.
110
+ # @option attributes [optional, Array<String>] :tags List of labels to tag the
111
+ # Snitch with.
112
+ #
113
+ # @example Create a new Snitch
114
+ # client.create_snitch({
115
+ # name: "Daily Backups",
116
+ # type: { interval: "hourly" },
117
+ # notes: "On error check the print tray for paper jams",
118
+ # tags: [ "backups", "maintenance" ],
119
+ # })
120
+ #
121
+ # # => #<Snitcher::API::Snitch:...>
122
+ #
123
+ # @raise [Timeout::Error] if the API request took too long to execute.
124
+ # @raise [Snitcher::API::ResourceInvalidError] if the attributes are not valid
125
+ # for a Snitch.
126
+ # @raise [Snitcher::API::Error] if any other API errors occur.
127
+ #
128
+ # @return [Snitcher::API::Snitch] the new Snitch.
139
129
  def create_snitch(attributes={})
140
- payload = post("/v1/snitches", attributes)
141
- Snitcher::API::Snitch.new(payload)
130
+ if attributes.has_key?(:interval)
131
+ type = attributes[:type] ||= {}
132
+ type[:interval] ||= attributes.delete(:interval)
133
+ end
134
+
135
+ response = post("/v1/snitches", attributes)
136
+ Snitcher::API::Snitch.new(response)
142
137
  end
143
138
 
144
- # Public: Edit an existing snitch, identified by token, using passed-in
145
- # values. Only changes those values included in the attributes
146
- # hash; other attributes are not changed. Returns the updated snitch.
147
- #
148
- # token: The unique token of the snitch to get. Should be a string.
149
- # attributes: A hash of the snitch properties. It should only include those
150
- # values you want to change. Options include these keys:
151
- # "name": String value is the name of the snitch
152
- # "interval": String value representing how often the snitch
153
- # is expected to fire. Options are "hourly",
154
- # "daily", "weekly", and "monthly".
155
- # "notes": Optional string value for recording additional
156
- # information about the snitch
157
- # "tags": Optional array of string tags
158
- #
159
- # Example
160
- #
161
- # Edit an existing snitch using values passed in a hash.
162
- # token = "c2354d53d2"
163
- # attributes = {
164
- # "name": "Monthly Backups",
165
- # "interval": "monthly"
166
- # }
167
- # @client.edit_snitch(token, attributes)
168
- # => #<Snitcher::API::Snitch:0x007fdcf50ad2d0 @token="c2354d53d3",
169
- # @name="Monthly Backups", @tags=["backups", "maintenance"],
170
- # @status="pending", @checked_in_at=nil, @interval="monthly",
171
- # @check_in_url="https://nosnch.in/c2354d53d3",
172
- # @created_at="2015-08-15T12:15:00.234Z",
173
- # @notes="Customer and supplier tables">
139
+ # Update a snitch, identified by token, using passed-in values. Only changes
140
+ # those values included in the attributes hash; other attributes are not
141
+ # changed.
142
+ #
143
+ # @param token [String] The unique token of the Snitch.
144
+ # @param [Hash] attributes the set of Snitch attributes to change.
145
+ #
146
+ # @option attributes [String] :name The label used for the Snitch
147
+ # @option attributes [String] :interval How often the snitch is expected to
148
+ # check-in. One of: "15_minute", "30_minute", "hourly", "daily", "weekly",
149
+ # or "monthly".
150
+ # @option attributes [optional, String] :notes Additional information about
151
+ # the Snitch. Useful to put instructions of investigating or fixing any
152
+ # errors.
153
+ # @option attributes [optional, Array<String>, nil] :tags List of labels to
154
+ # tag the Snitch with.
155
+ #
156
+ # @example Update an existing Snitch
157
+ # client.update_snitch("c2354d53d2", {
158
+ # name: "Monthly Backups",
159
+ # })
160
+ # # => #<Snitcher::API::Snitch:...>
161
+ #
162
+ # @example Setting Tags for a Snitch
163
+ # client.update_snitch("c2354d53d2", tags: ["production", "backup"])
164
+ # # => #<Snitcher::API::Snitch: @tags=["production", "backup"])
165
+ #
166
+ # @example Removing Tags from a Snitch
167
+ # client.update_snitch("c2354d53d2", tags: [])
168
+ # or
169
+ # client.update_snitch("c2354d53d2", tags: nil)
170
+ #
171
+ # @raise [Timeout::Error] if the API request took too long to execute.
172
+ # @raise [Snitcher::API::ResourceInvalidError] if the changes are not valid.
173
+ # @raise [Snitcher::API::ResourceNotFoundError] if the Snitch does not exist.
174
+ # @raise [Snitcher::API::Error] if any other API errors occur.
174
175
  #
175
176
  # Raise Timeout::Error if the API request times out
176
- def edit_snitch(token, attributes={})
177
+ def update_snitch(token, attributes={})
178
+ if attributes.has_key?(:tags)
179
+ attributes[:tags] = [attributes[:tags]].flatten.compact
180
+ end
181
+
182
+ if attributes.has_key?(:interval)
183
+ type = attributes[:type] ||= {}
184
+ type[:interval] ||= attributes.delete(:interval)
185
+ end
186
+
177
187
  payload = patch("/v1/snitches/#{token}", attributes)
178
188
  Snitcher::API::Snitch.new(payload)
179
189
  end
180
190
 
181
- # Public: Add one or more tags to an existing snitch, identified by token.
182
- # Returns an array of the snitch's tags.
191
+ # Add one or more tags to an existing snitch, identified by token.
183
192
  #
184
- # token: The unique token of the snitch to edit. Should be a string.
185
- # tags: Array of string tags. Will append these tags to any existing tags.
193
+ # @param token [String] The unique token of the Snitch.
194
+ # @param tags [Array<String>] Tag or tags to add to the list of tags already
195
+ # on the Snitch.
186
196
  #
187
- # Example
197
+ # @example Add tags to an existing snitch.
198
+ # client.add_tags("c2354d53d2", ["red", "green"])
199
+ # # => [ "yellow", "red", "green" ]
188
200
  #
189
- # Add tags to an existing snitch.
190
- # @client.add_tags("c2354d53d2", %w("red", "green")
191
- # => [ "yellow", "red", "green" ]
201
+ # @example Adding a single tag
202
+ # client.add_tags("c2354d53d2", "orange")
203
+ # # => [ "yellow", "orange" ]
192
204
  #
193
- # Adding a single tag
194
- # @client.add_tags("c2354d53d2", "orange")
195
- # => [ "yellow", "orange" ]
205
+ # @raise [Timeout::Error] if the API request took too long to execute.
206
+ # @raise [Snitcher::API::ResourceNotFoundError] if the Snitch does not exist.
207
+ # @raise [Snitcher::API::Error] if an API errors occur.
196
208
  #
197
- # Raise Timeout::Error if the API request times out
209
+ # @return [Array<String>] full list of tags on the Snitch.
198
210
  def add_tags(token, tags=[])
199
211
  tags = [tags].flatten
200
212
  post("/v1/snitches/#{token}/tags", tags)
201
213
  end
202
214
 
203
- # Public: Remove a tag from an existing snitch, identified by token.
204
- # Returns an array of the snitch's tags.
215
+ # Remove a tag from a Snitch.
205
216
  #
206
- # token: The unique token of the snitch to edit. Should be a string.
207
- # tag: Tag to be removed from a snitch's tags. Should be a string.
217
+ # @param token [String] The unique token of the Snitch.
218
+ # @param tag [String] The tag to remove from the Snitch.
208
219
  #
209
- # Example
220
+ # @example Removing the "production" tag from a Snitch
221
+ # client.remove_tag("c2354d53d2", "production")
222
+ # # => [ "critical" ]
210
223
  #
211
- # Assume a snitch that already has the tags "critical" and "production"
212
- # token = "c2354d53d2"
213
- # tag = "production"
214
- # @client.remove_tag(token, tag)
215
- # => [
216
- # "critical"
217
- # ]
224
+ # @raise [Timeout::Error] if the API request took too long to execute.
225
+ # @raise [Snitcher::API::ResourceNotFoundError] if the Snitch does not exist.
226
+ # @raise [Snitcher::API::Error] if any other API errors occur.
218
227
  #
219
- # Raise Timeout::Error if the API request times out
228
+ # @return [Array<String>] list of the remaining tags on the Snitch.
220
229
  def remove_tag(token, tag)
221
230
  delete("/v1/snitches/#{token}/tags/#{tag}")
222
231
  end
223
232
 
224
- # Public: Replace all of a snitch's tags with those supplied.
225
- # Returns the updated snitch.
226
- #
227
- # token: The unique token of the snitch to edit. Should be a string.
228
- # tags: Array of string tags. Will replace the snitch's current tags with
229
- # these.
230
- #
231
- # Example
232
- #
233
- # Assume a snitch with the tag "critical". Replace with tags provided.
234
- # token = "c2354d53d3"
235
- # tags = ["production", "urgent"]
236
- # @client.replace_tags(token, tags)
237
- # => #<Snitcher::API::Snitch:0x007fdcf50ad2d0 @token="c2354d53d3",
238
- # @name="Daily Backups", @tags=["production", "urgent"],
239
- # @status="pending", @checked_in_at=nil, @interval="daily",
240
- # @check_in_url="https://nosnch.in/c2354d53d3",
241
- # @created_at="2015-08-15T12:15:00.234Z",
242
- # @notes="Customer and supplier tables">
243
- #
244
- # Raise Timeout::Error if the API request times out
245
- def replace_tags(token, tags=[])
246
- attributes = {"tags" => tags}
247
-
248
- edit_snitch(token, attributes)
249
- end
250
-
251
- # Public: Remove all of a snitch's tags.
252
- # Returns the updated snitch.
253
- #
254
- # token: The unique token of the snitch to edit. Should be a string.
255
- #
256
- # Example
257
- #
258
- # Remove all tags.
259
- # token = "c2354d53d3"
260
- # @client.clear_tags(token)
261
- # => #<Snitcher::API::Snitch:0x007fdcf50ad2d0 @token="c2354d53d3",
262
- # @name="Daily Backups", @tags=[], @status="pending",
263
- # @checked_in_at=nil, @interval="daily",
264
- # @check_in_url="https://nosnch.in/c2354d53d3",
265
- # @created_at="2015-08-15T12:15:00.234Z",
266
- # @notes="Customer and supplier tables">
267
- #
268
- # Raise Timeout::Error if the API request times out
269
- def clear_tags(token)
270
- edit_snitch(token, :tags => [])
271
- end
272
-
273
- # Public: Pauses a snitch. The return is a hash with the message "Response
274
- # complete".
233
+ # Pauses a Snitch if it can be paused. Snitches can only be paused if their
234
+ # status is currently "failing" or "errored".
275
235
  #
276
- # token: The unique token of the snitch to pause. Should be a string.
236
+ # @param token [String] The unique token of the Snitch.
277
237
  #
278
- # Example
238
+ # @example Pause a Snitch
239
+ # client.pause_snitch("c2354d53d2")
240
+ # # => true
279
241
  #
280
- # Pause a snitch.
281
- # token = "c2354d53d3"
282
- # @client.pause_snitch(token)
283
- # => { :message => "Response complete" }
242
+ # @raise [Timeout::Error] if the API request took too long to execute.
243
+ # @raise [Snitcher::API::ResourceNotFoundError] if the Snitch does not exist.
244
+ # @raise [Snitcher::API::Error] if any other API errors occur.
284
245
  #
285
- # Raise Timeout::Error if the API request times out
246
+ # @return [nil]
286
247
  def pause_snitch(token)
287
248
  post("/v1/snitches/#{token}/pause")
249
+
250
+ nil
288
251
  end
289
252
 
290
- # Public: Deletes a snitch. The return is a hash with the message "Response
291
- # complete".
253
+ # Deletes a Snitch.
292
254
  #
293
- # token: The unique token of the snitch to delete. Should be a string.
255
+ # @param token [String] The unique token of the Snitch to delete.
294
256
  #
295
- # Example
257
+ # @example Delete a Snitch.
258
+ # client.delete_snitch("c2354d53d2")
259
+ # # => { :message => "Response complete" }
296
260
  #
297
- # Delete a snitch.
298
- # token = "c2354d53d3"
299
- # @client.delete_snitch(token)
300
- # => { :message => "Response complete" }
261
+ # @raise [Timeout::Error] if the API request took too long to execute.
262
+ # @raise [Snitcher::API::ResourceNotFoundError] if the Snitch does not exist.
263
+ # @raise [Snitcher::API::Error] if any other API errors occur.
301
264
  #
302
- # Raise Timeout::Error if the API request times out
265
+ # @return [nil]
303
266
  def delete_snitch(token)
304
267
  delete("/v1/snitches/#{token}")
268
+
269
+ nil
305
270
  end
306
271
 
307
- protected
272
+ private
308
273
 
309
274
  def user_agent
310
275
  # RUBY_ENGINE was not added until 1.9.3
@@ -1,11 +1,38 @@
1
1
  class Snitcher::API::Snitch
2
- attr_accessor :token, :name, :tags, :status, :checked_in_at,
3
- :interval, :check_in_url, :created_at, :notes
2
+ # @return [String] unique token used to identify a Snitch.
3
+ attr_accessor :token
4
4
 
5
- # Public: Return a Snitcher::API::Snitch object based on a hash payload.
6
- #
7
- # Example
5
+ # @return [String] useful name for the Snitch to help identify it.
6
+ attr_accessor :name
7
+
8
+ # @return [Array<String>] list of tags on the Snitch.
9
+ attr_accessor :tags
10
+
11
+ # @return [String] the current reporting status of the Snitch. One of
12
+ # "pending", "healthy", "paused", "failed", or "errored".
13
+ attr_accessor :status
14
+
15
+ # @return [String] when the Snitch last checked_in
16
+ attr_accessor :checked_in_at
17
+
18
+ # @return [String] how often Dead Man's Snitch expects to hear from the
19
+ # Snitch. One of "15_minute", "30_minute", "hourly", "daily", "weekly", or
20
+ # "monthly".
21
+ attr_accessor :interval
22
+
23
+ # @return [String] url used to check-in in the Snitch as healthy.
24
+ attr_accessor :check_in_url
25
+
26
+ # @return [String] when the Snitch was created.
27
+ attr_accessor :created_at
28
+
29
+ # @return [String] generic notes for the Snitch. Useful for specifying actions
30
+ # to take when a Snitch stops reporting.
31
+ attr_accessor :notes
32
+
33
+ # Create a new Snitch from an API response.
8
34
  #
35
+ # @example
9
36
  # payload = {
10
37
  # "token" => "c2354d53d3",
11
38
  # "href" => "/v1/snitches/c2354d53d3",
@@ -25,20 +52,19 @@ class Snitcher::API::Snitch
25
52
  # }
26
53
  #
27
54
  # Snitcher::API::Snitch.new(payload)
28
- # => #<Snitcher::API::Snitch:0x007fdcf50ad2d0 @token="c2354d53d3",
29
- # @name="Daily Backups", @tags=["production", "critical"],
30
- # @status="pending", @checked_in_at=nil, @interval="daily",
31
- # @check_in_url="https://nosnch.in/c2354d53d3",
32
- # @created_at="2015-08-15T12:15:00.234Z", @notes="Important user data.">
55
+ # # => #<Snitcher::API::Snitch...>
56
+ #
57
+ # @return Snitcher::API::Snitch
33
58
  def initialize(payload)
34
- @token = payload["token"]
35
- @name = payload["name"]
36
- @tags = payload["tags"]
37
- @status = payload["status"]
59
+ @token = payload["token"]
60
+ @name = payload["name"]
61
+ @tags = payload["tags"]
62
+ @status = payload["status"]
63
+ @interval = payload["type"]["interval"]
64
+ @notes = payload["notes"]
65
+
66
+ @created_at = payload["created_at"]
67
+ @check_in_url = payload["check_in_url"]
38
68
  @checked_in_at = payload["checked_in_at"]
39
- @interval = payload["type"]["interval"]
40
- @check_in_url = payload["check_in_url"]
41
- @created_at = payload["created_at"]
42
- @notes = payload["notes"]
43
69
  end
44
70
  end
@@ -1,3 +1,3 @@
1
1
  module Snitcher
2
- VERSION = "0.4.0.pre2"
2
+ VERSION = "0.4.0.rc1"
3
3
  end
@@ -9,7 +9,7 @@ describe Snitcher::API::Client do
9
9
  end
10
10
 
11
11
  let(:stub_url) { /api\.dms\.dev/ }
12
- let(:snitch_url) { "http://key:@api.dms.dev/v1/snitches" }
12
+ let(:snitch_url) { "http://api.dms.dev/v1/snitches" }
13
13
 
14
14
  describe "#snitches" do
15
15
  let(:url) { snitch_url }
@@ -45,7 +45,9 @@ describe Snitcher::API::Client do
45
45
  }
46
46
 
47
47
  before do
48
- stub_request(:get, stub_url).to_return(:body => body, :status => 200)
48
+ stub_request(:get, stub_url).
49
+ with(basic_auth: ["key", ""]).
50
+ to_return(:body => body, :status => 200)
49
51
  end
50
52
 
51
53
  it "pings API with the api_key" do
@@ -171,10 +173,10 @@ describe Snitcher::API::Client do
171
173
  describe "#create_snitch" do
172
174
  let(:data) {
173
175
  {
174
- "name" => "Daily Backups",
176
+ "name" => "Daily Backups",
175
177
  "interval" => "daily",
176
- "notes" => "Customer and supplier tables",
177
- "tags" => ["backups", "maintenance"]
178
+ "notes" => "Customer and supplier tables",
179
+ "tags" => ["backups", "maintenance"]
178
180
  }
179
181
  }
180
182
  let(:url) { snitch_url }
@@ -211,6 +213,49 @@ describe Snitcher::API::Client do
211
213
  expect(client.create_snitch(data)).to be_a(Snitcher::API::Snitch)
212
214
  end
213
215
 
216
+ it "takes interval as a top level key" do
217
+ # The API as designed requires `type: { interval: "" }` with the
218
+ # expectation that there will be more types of Snitches. This hasn't
219
+ # happend as of 2016 and it's expected that interval will be required
220
+ # regardless of future changes.
221
+ #
222
+ # Allowing interval as a top level key makes using the API easier.
223
+
224
+ req =
225
+ stub_request(:post, stub_url).with do |request|
226
+ payload = JSON.parse(request.body)
227
+
228
+ expect(payload).to have_key("type")
229
+ expect(payload["type"]["interval"]).to eq("hourly")
230
+ end
231
+ .to_return(:body => body, :status => 201)
232
+
233
+ client.create_snitch(name: "Snitch", interval: "hourly")
234
+
235
+ expect(req).to have_been_made
236
+ end
237
+
238
+ it "puts precedences on type/interval over just interval" do
239
+ # :interval is a helper but the API documentation specifies type/interval.
240
+
241
+ req =
242
+ stub_request(:post, stub_url).with do |request|
243
+ payload = JSON.parse(request.body)
244
+
245
+ expect(payload).to have_key("type")
246
+ expect(payload["type"]["interval"]).to eq("weekly")
247
+ end
248
+ .to_return(:body => body, :status => 201)
249
+
250
+ client.create_snitch({
251
+ name: "Snitch",
252
+ interval: "daily",
253
+ type: { interval: "weekly" },
254
+ })
255
+
256
+ expect(req).to have_been_made
257
+ end
258
+
214
259
  describe "validation errors" do
215
260
  let(:data) do
216
261
  {
@@ -245,7 +290,7 @@ describe Snitcher::API::Client do
245
290
  end
246
291
  end
247
292
 
248
- describe "#edit_snitch" do
293
+ describe "#update_snitch" do
249
294
  let(:token) { "c2354d53d2" }
250
295
  let(:data) {
251
296
  {
@@ -276,13 +321,85 @@ describe Snitcher::API::Client do
276
321
  end
277
322
 
278
323
  it "pings API with the api_key" do
279
- client.edit_snitch(token, data)
324
+ client.update_snitch(token, data)
280
325
 
281
326
  expect(a_request(:patch, url)).to have_been_made.once
282
327
  end
283
328
 
284
329
  it "returns the modified snitch" do
285
- expect(client.edit_snitch(token, data)).to be_a(Snitcher::API::Snitch)
330
+ expect(client.update_snitch(token, data)).to be_a(Snitcher::API::Snitch)
331
+ end
332
+
333
+ it "takes interval as a top level key" do
334
+ req =
335
+ stub_request(:patch, stub_url).with do |request|
336
+ payload = JSON.parse(request.body)
337
+
338
+ expect(payload).to have_key("type")
339
+ expect(payload["type"]["interval"]).to eq("hourly")
340
+ end
341
+ .to_return(:body => body, :status => 200)
342
+
343
+ client.update_snitch("c2354d53d2", interval: "hourly")
344
+
345
+ expect(req).to have_been_made
346
+ end
347
+
348
+ it "puts precedences on type/interval over just interval" do
349
+ # :interval is a helper but the API documentation specifies type/interval.
350
+
351
+ req =
352
+ stub_request(:patch, stub_url).with do |request|
353
+ payload = JSON.parse(request.body)
354
+
355
+ expect(payload).to have_key("type")
356
+ expect(payload["type"]["interval"]).to eq("weekly")
357
+ end
358
+ .to_return(:body => body, :status => 200)
359
+
360
+ client.update_snitch("c2354d53d2", {
361
+ interval: "daily",
362
+ type: { interval: "weekly" },
363
+ })
364
+
365
+ expect(req).to have_been_made
366
+ end
367
+
368
+
369
+ it "can tag using a single string" do
370
+ req =
371
+ stub_request(:patch, stub_url).with do |request|
372
+ payload = JSON.parse(request.body)
373
+ expect(payload["tags"]).to eq(["production"])
374
+ end.
375
+ and_return(body: body)
376
+
377
+ client.update_snitch("c2354d53d2", tags: "production")
378
+ expect(req).to have_been_made
379
+ end
380
+
381
+ it "can remove all tags using `nil`" do
382
+ req =
383
+ stub_request(:patch, stub_url).with do |request|
384
+ payload = JSON.parse(request.body)
385
+ expect(payload["tags"]).to eq([])
386
+ end.
387
+ and_return(body: body)
388
+
389
+ client.update_snitch("c2354d53d2", tags: nil)
390
+ expect(req).to have_been_made
391
+ end
392
+
393
+ it "can remove all tags using an empty hash" do
394
+ req =
395
+ stub_request(:patch, stub_url).with do |request|
396
+ payload = JSON.parse(request.body)
397
+ expect(payload["tags"]).to eq([])
398
+ end.
399
+ and_return(body: body)
400
+
401
+ client.update_snitch("c2354d53d2", tags: [])
402
+ expect(req).to have_been_made
286
403
  end
287
404
  end
288
405
 
@@ -314,10 +431,7 @@ describe Snitcher::API::Client do
314
431
  let(:token) { "c2354d53d2" }
315
432
  let(:tag) { "critical" }
316
433
  let(:url) { "#{snitch_url}/#{token}/tags/#{tag}" }
317
- let(:body) { '[
318
- "critical"
319
- ]'
320
- }
434
+ let(:body) { '[ "critical" ]' }
321
435
 
322
436
  before do
323
437
  stub_request(:delete, stub_url).to_return(:body => body, :status => 200)
@@ -336,82 +450,12 @@ describe Snitcher::API::Client do
336
450
  end
337
451
  end
338
452
 
339
- describe "#replace_tags" do
340
- let(:token) { "c2354d53d2" }
341
- let(:tags) { ["red", "green"] }
342
- let(:url) { "#{snitch_url}/#{token}" }
343
- let(:body) { '{
344
- "token": "c2354d53d2",
345
- "href": "/v1/snitches/c2354d53d2",
346
- "name": "Daily Backups",
347
- "tags": [
348
- "red",
349
- "green"
350
- ],
351
- "status": "pending",
352
- "checked_in_at": "",
353
- "type": {
354
- "interval": "daily"
355
- },
356
- "notes": "Sales data."
357
- }'
358
- }
359
-
360
- before do
361
- stub_request(:patch, stub_url).to_return(:body => body, :status => 200)
362
- end
363
-
364
- it "pings API with the api_key" do
365
- client.replace_tags(token, tags)
366
-
367
- expect(a_request(:patch, url)).to have_been_made.once
368
- end
369
-
370
- it "returns the updated snitch" do
371
- expect(client.replace_tags(token, tags)).to be_a(Snitcher::API::Snitch)
372
- end
373
- end
374
-
375
- describe "#clear_tags" do
376
- let(:token) { "c2354d53d2" }
377
- let(:url) { "#{snitch_url}/#{token}" }
378
- let(:body) { '{
379
- "token": "c2354d53d2",
380
- "href": "/v1/snitches/c2354d53d2",
381
- "name": "Daily Backups",
382
- "tags": [
383
- ],
384
- "status": "pending",
385
- "checked_in_at": "",
386
- "type": {
387
- "interval": "daily"
388
- },
389
- "notes": "Sales data."
390
- }'
391
- }
392
-
393
- before do
394
- stub_request(:patch, stub_url).to_return(:body => body, :status => 200)
395
- end
396
-
397
- it "pings API with the api_key" do
398
- client.clear_tags(token)
399
-
400
- expect(a_request(:patch, url)).to have_been_made.once
401
- end
402
-
403
- it "returns the updated snitch" do
404
- expect(client.clear_tags(token)).to be_a(Snitcher::API::Snitch)
405
- end
406
- end
407
-
408
453
  describe "#pause_snitch" do
409
454
  let(:token) { "c2354d53d2" }
410
455
  let(:url) { "#{snitch_url}/#{token}/pause" }
411
- let(:body) { '{}' }
412
456
 
413
457
  before do
414
- stub_request(:post, stub_url).to_return(:body => body, :status => 200)
458
+ stub_request(:post, stub_url).to_return(:status => 204)
415
459
  end
416
460
 
417
461
  it "pings API with the api_key" do
@@ -422,7 +466,7 @@ describe Snitcher::API::Client do
422
466
 
423
467
  context "when successful" do
424
468
  it "returns an empty response" do
425
- expect(client.pause_snitch(token)).to eq(JSON.parse(body))
469
+ expect(client.pause_snitch(token)).to eq(nil)
426
470
  end
427
471
  end
428
472
  end
@@ -430,10 +474,9 @@ describe Snitcher::API::Client do
430
474
  describe "#delete_snitch" do
431
475
  let(:token) { "c2354d53d2" }
432
476
  let(:url) { "#{snitch_url}/#{token}" }
433
- let(:body) { '{}' }
434
477
 
435
478
  before do
436
- stub_request(:delete, stub_url).to_return(:body => body, :status => 200)
479
+ stub_request(:delete, stub_url).to_return(:status => 204)
437
480
  end
438
481
 
439
482
  it "pings API with the api_key" do
@@ -444,7 +487,7 @@ describe Snitcher::API::Client do
444
487
 
445
488
  context "when successful" do
446
489
  it "returns an empty response" do
447
- expect(client.delete_snitch(token)).to eq(JSON.parse(body))
490
+ expect(client.delete_snitch(token)).to eq(nil)
448
491
  end
449
492
  end
450
493
  end
@@ -11,7 +11,8 @@ describe Snitcher::API do
11
11
  user = "alice@example.com"
12
12
  pass = "password"
13
13
 
14
- request = stub_request(:get, "https://#{user}:#{pass}@api.deadmanssnitch.com/v1/api_key").
14
+ request = stub_request(:get, "https://api.deadmanssnitch.com/v1/api_key").
15
+ with(basic_auth: [user, pass]).
15
16
  to_return({
16
17
  :body => '{"api_key": "_caeEiZXnEyEzXXYVh2NhQ"}',
17
18
  :status => 200
@@ -27,7 +28,8 @@ describe Snitcher::API do
27
28
  user = "lol@notreally.horse"
28
29
  pass = "nope"
29
30
 
30
- request = stub_request(:get, "https://#{user}:#{pass}@api.deadmanssnitch.com/v1/api_key").
31
+ request = stub_request(:get, "https://api.deadmanssnitch.com/v1/api_key").
32
+ with(basic_auth: [user, pass]).
31
33
  to_return({
32
34
  :body => JSON.generate({
33
35
  :type => "sign_in_incorrect",
@@ -60,7 +62,8 @@ describe Snitcher::API do
60
62
  end
61
63
 
62
64
  it "allows the API URI to be provided" do
63
- request = stub_request(:any, "user:pass@dms.dev:4000/v1/api_key").
65
+ request = stub_request(:any, "dms.dev:4000/v1/api_key").
66
+ with(basic_auth: ["user", "pass"]).
64
67
  to_return({
65
68
  :body => '{"api_key": "this_is_an_api_key"}',
66
69
  :status => 200
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snitcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.pre2
4
+ version: 0.4.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Collective Idea
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-25 00:00:00.000000000 Z
11
+ date: 2016-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -102,3 +102,4 @@ test_files:
102
102
  - spec/spec_helper.rb
103
103
  - spec/support/random.rb
104
104
  - spec/support/webmock.rb
105
+ has_rdoc: