snitcher 0.4.0.pre2 → 0.4.0.rc1

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 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: