dogwatch 1.0.5 → 1.1.0

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: 3573cefa87a87733badaa188e4138bcf946598c1
4
- data.tar.gz: 7f160b2d047845120932ad57be4e9f851c94df49
3
+ metadata.gz: 224be9842797fe4c2fc9c0cf3d88a9972759d54f
4
+ data.tar.gz: 5b14f7af6a5a64146640832cf53aa16fe350d0bc
5
5
  SHA512:
6
- metadata.gz: 69453b6cbf2dc5dfc75be7d2a4e762a9d1d18a806a9b9a907e018bd01616602eb6a31dfb847c90f0dacb21ce70ce1db93b02a609e30a692ba6b727d1032bcd4e
7
- data.tar.gz: 7a9e862dc1736e0a0147b721851492332c1ada38428882b9c6c393c1f94e0f00a799bb0e2ac4e3a4cc0898cddcfc52fcd238d44946ad80bf49f88ee304a214e3
6
+ metadata.gz: f98c42c081bbf044495be9c26272e03699a74d581e9653cf5b6a21c8a3103c45d3d06b27b2c7faf8714b8033a928e5bdee2bffa8c95cb7b14e82ba452b6981d8
7
+ data.tar.gz: 026bf75a19af2a701511e8d7222dc176bf856fc4bac7ddee1cda6458eb09de0a46ea357836749a0cc015e054a0a3a84ef0438e03aeb7d12fdf069e6378c379ae
@@ -10,6 +10,7 @@ module DogWatch
10
10
  class_option :dogfile, :type => :string, :default => 'Dogfile'
11
11
  class_option :api_key, :type => :string, :default => nil
12
12
  class_option :app_key, :type => :string, :default => nil
13
+ class_option :timeout, :type => :numeric, :default => 5
13
14
  def initialize(*args)
14
15
  super
15
16
  @cwd = Dir.getwd
@@ -19,7 +20,8 @@ module DogWatch
19
20
  desc 'create', 'Create a monitor from a Dogfile'
20
21
  def create
21
22
  @dogfile.configure(File.absolute_path(options['dogfile'], @cwd),
22
- options['api_key'], options['app_key'])
23
+ options['api_key'], options['app_key'],
24
+ options['timeout'])
23
25
  @dogfile.create { |c| say_status(*c.to_thor) }
24
26
  end
25
27
  end
@@ -20,6 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = '>= 2.2'
22
22
 
23
- spec.add_runtime_dependency 'dogapi', '~> 1.21'
23
+ spec.add_runtime_dependency 'dogapi', '~> 1.27'
24
24
  spec.add_runtime_dependency 'thor', '~> 0.19'
25
25
  end
@@ -4,6 +4,26 @@
4
4
  #
5
5
  DogWatch.monitor do
6
6
  monitor 'test_alert' do
7
+ type :metric_alert
8
+ query 'avg(last_1dm):avg:system.cpu.user{region:us-east-1} > 20'
9
+ message 'A message to include with notifications for this monitor.'\
10
+ 'Email notifications can be sent to specific users by '\
11
+ 'using the same \'@username\' notation as events.'
12
+
13
+ tags %w(A list of tags to associate with your monitor)
14
+
15
+ options do
16
+ silenced '*': nil
17
+ notify_no_data false
18
+ no_data_timeframe 3
19
+ timeout_h 99
20
+ renotify_interval 60
21
+ escalation_message 'oh snap'
22
+ include_tags true
23
+ end
24
+ end
25
+
26
+ monitor 'test_alert2' do
7
27
  type :metric_alert
8
28
  query 'avg(last_1m):avg:system.cpu.user{region:us-east-1} > 20'
9
29
  message 'A message to include with notifications for this monitor.'\
@@ -3,6 +3,9 @@
3
3
  ##
4
4
  module DogWatch
5
5
  class << self
6
+ # @param [Hash] args
7
+ # @param [Proc] block
8
+ # @return [DogWatch::Monitor]
6
9
  def monitor(*args, &block)
7
10
  DogWatch::Monitor.new(*args, &block)
8
11
  end
@@ -9,9 +9,10 @@ module DogWatch
9
9
  # @param [String] dogfile
10
10
  # @param [String|Object] api_key
11
11
  # @param [String|Object] app_key
12
- def configure(dogfile, api_key = nil, app_key = nil)
12
+ # @param [Integer] timeout
13
+ def configure(dogfile, api_key, app_key, timeout)
13
14
  @dogfile = dogfile
14
- @config = DogWatch::Model::Config.new(api_key, app_key)
15
+ @config = DogWatch::Model::Config.new(api_key, app_key, timeout)
15
16
  end
16
17
 
17
18
  # @param [Proc] block
@@ -15,11 +15,13 @@ module DogWatch
15
15
  # @param [DogWatch::Model::Config] config
16
16
  def initialize(config)
17
17
  @config = config
18
- @client = Dogapi::Client.new(@config.api_key, @config.app_key)
18
+ @client = Dogapi::Client.new(@config.api_key, @config.app_key,
19
+ nil, nil, true, @config.timeout)
19
20
  @all_monitors = all_monitors
20
21
  end
21
22
 
22
23
  # @param [DogWatch::Model::Monitor] monitor
24
+ # @return [DogWatch::Model::Response]
23
25
  def execute(monitor)
24
26
  if monitor_exists?(monitor.name)
25
27
  update_monitor(monitor)
@@ -37,7 +39,7 @@ module DogWatch
37
39
  monitor.attributes.query,
38
40
  options)
39
41
  updated = %w(200 202).include?(response[0])
40
- @response = DogWatch::Model::Response.new(response, updated)
42
+ DogWatch::Model::Response.new(response, options[:name], updated)
41
43
  end
42
44
 
43
45
  # @param [DogWatch::Model::Monitor] monitor
@@ -47,7 +49,17 @@ module DogWatch
47
49
  response = @client.monitor(monitor.attributes.type,
48
50
  monitor.attributes.query,
49
51
  options)
50
- @response = DogWatch::Model::Response.new(response)
52
+ DogWatch::Model::Response.new(response, options[:name])
53
+ end
54
+
55
+ # @param [Dogwatch::Model::Monitor] monitor
56
+ # @return [Dogwatch::Model::Response]
57
+ def validate(monitor)
58
+ validation = monitor.validate
59
+ return validation if validation.status == :error
60
+
61
+ # If no validation errors return a valid Response
62
+ DogWatch::Model::Response.new(['200', {}], 'valid')
51
63
  end
52
64
 
53
65
  private
@@ -9,12 +9,15 @@ module DogWatch
9
9
  class Config
10
10
  attr_accessor :api_key
11
11
  attr_accessor :app_key
12
+ attr_accessor :timeout
12
13
 
13
14
  # @param [String] api_key
14
15
  # @param [String] app_key
15
- def initialize(api_key = nil, app_key = nil)
16
+ # @param [Integer] timeout
17
+ def initialize(api_key = nil, app_key = nil, timeout = 5)
16
18
  @api_key = api_key unless api_key.nil?
17
19
  @app_key = app_key unless app_key.nil?
20
+ @timeout = timeout
18
21
  return unless app_key.nil? || api_key.nil?
19
22
 
20
23
  from_file
@@ -5,6 +5,9 @@ module DogWatch
5
5
  # Provides a colorize() mixin that handles shell output coloring
6
6
  ##
7
7
  module Colorize
8
+ # @param [Symbol] param
9
+ # @param [Hash] options
10
+ # @return [Symbol]
8
11
  def colorize(param, options = {})
9
12
  define_method(:color) do
10
13
  case instance_variable_get("@#{ param }")
@@ -56,13 +56,44 @@ module DogWatch
56
56
  @attributes.options = opts.render
57
57
  end
58
58
 
59
- # @return [TrueClass|FalseClass]
59
+ # @return [DogWatch::Model::Response]
60
60
  def validate
61
- return false unless TYPE_MAP.value?(@attributes.type)
62
- return true unless @attributes.type.nil? || @attributes.type.empty? ||
63
- @attributes.query.nil? || @attributes.query.empty?
61
+ return DogWatch::Model::Response.new(invalid_type_response, 'invalid') \
62
+ unless TYPE_MAP.key?(@monitor_type)
64
63
 
65
- false
64
+ errors = []
65
+ errors.push('Missing monitor type') if missing_type?
66
+ errors.push('Missing monitor query') if missing_query?
67
+
68
+ if errors.empty?
69
+ DogWatch::Model::Response.new(['200', { :message => 'valid' }], 'valid')
70
+ else
71
+ DogWatch::Model::Response.new(['400', { 'errors' => errors }], 'invalid')
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def valid_types
78
+ TYPE_MAP.keys.map { |k| ":#{k}" }.join(', ')
79
+ end
80
+
81
+ def missing_type?
82
+ @attributes.type.nil? || @attributes.type.empty?
83
+ end
84
+
85
+ def missing_query?
86
+ @attributes.query.nil? || @attributes.query.empty?
87
+ end
88
+
89
+ def invalid_type_response
90
+ [
91
+ '400',
92
+ { 'errors' => [
93
+ "Monitor type '#{@monitor_type}' is not valid. " \
94
+ "Valid monitor types are: #{valid_types}"
95
+ ] }
96
+ ]
66
97
  end
67
98
  end
68
99
  end
@@ -21,6 +21,7 @@ module DogWatch
21
21
  @monitor_type = monitor_type
22
22
  end
23
23
 
24
+ # @return [Hash]
24
25
  def render
25
26
  @attributes.each_pair.to_h
26
27
  end
@@ -11,6 +11,7 @@ module DogWatch
11
11
  ERROR = '400'.freeze
12
12
  CREATED = '200'.freeze
13
13
  ACCEPTED = '202'.freeze
14
+
14
15
  colorize(:action,
15
16
  :green => [:created, :accepted, :updated],
16
17
  :yellow => [],
@@ -18,11 +19,21 @@ module DogWatch
18
19
 
19
20
  attr_accessor :response
20
21
 
21
- def initialize(response, updated = false)
22
+ # @param [Array] response
23
+ # @param [String] name
24
+ # @param [Boolean] updated
25
+ # @return [DogWatch::Model::Response]
26
+ def initialize(response, name, updated = false)
22
27
  @response = response
23
28
  @updated = updated
29
+ @name = if response[1]['name'].nil?
30
+ name
31
+ else
32
+ response[1]['name']
33
+ end
24
34
  end
25
35
 
36
+ # @return [Symbol]
26
37
  def status
27
38
  return :updated if @updated == true
28
39
  return :created if created?
@@ -30,13 +41,12 @@ module DogWatch
30
41
  return :accepted if accepted?
31
42
  end
32
43
 
44
+ # @return [String]
33
45
  def message
34
- attrs = @response[1]
35
- return attrs['errors'] if attrs.key?('errors')
36
- "#{status.to_s.capitalize} monitor #{attrs['name']}"\
37
- " with message #{attrs['message']}"
46
+ send(status, @response[1])
38
47
  end
39
48
 
49
+ # @return [Array]
40
50
  def to_thor
41
51
  action = status
42
52
  text = message
@@ -45,16 +55,35 @@ module DogWatch
45
55
 
46
56
  private
47
57
 
58
+ def error(attrs)
59
+ err = attrs['errors'].join(', ')
60
+ "The following errors occurred when creating monitor #{@name}: #{err}"
61
+ end
62
+
63
+ def created(attrs)
64
+ "Created monitor #{@name} with message #{attrs['message']}"
65
+ end
66
+
67
+ def updated(attrs)
68
+ # TODO: Use some kind of statefile to determine diffs between
69
+ # previously saved model and new version
70
+ "Updated monitor #{@name} with message #{attrs['message']}"
71
+ end
72
+
73
+ def accepted(attrs)
74
+ "Accepted monitor #{@name} with message #{attrs['message']}"
75
+ end
76
+
48
77
  def accepted?
49
- @response[0] == ACCEPTED ? true : false
78
+ @response[0] == ACCEPTED
50
79
  end
51
80
 
52
81
  def created?
53
- @response[0] == CREATED ? true : false
82
+ @response[0] == CREATED
54
83
  end
55
84
 
56
85
  def failed?
57
- @response[0] == ERROR ? true : false
86
+ @response[0] == ERROR
58
87
  end
59
88
  end
60
89
  end
@@ -32,20 +32,22 @@ module DogWatch
32
32
  # @return [Array]
33
33
  def get
34
34
  @responses = @monitors.map do |m|
35
- if m.validate
36
- @client.execute(m)
35
+ validate = @client.validate(m)
36
+ if validate.status == :error
37
+ validate
37
38
  else
38
- # Need somewhere to inject local errors such as if the request
39
- # was never sent because the type or query wasn't supplied.
40
- res = ['400', { 'errors' => ['The DogWatch monitor is invalid.'] }]
41
- DogWatch::Model::Response.new(res)
39
+ @client.execute(m)
42
40
  end
43
41
  end
44
42
  end
45
43
 
46
44
  # @return [DogWatch::Model::Client]
47
45
  def client(client = nil)
48
- @client = client.nil? ? DogWatch::Model::Client.new(@config) : client
46
+ @client = if client.nil?
47
+ DogWatch::Model::Client.new(@config)
48
+ else
49
+ client
50
+ end
49
51
  end
50
52
  end
51
53
  end
@@ -8,20 +8,20 @@ require 'json'
8
8
  class TestClient < Minitest::Test
9
9
  TEST_RESPONSE = [
10
10
  '200',
11
- [
11
+ {
12
12
  name: 'test monitor',
13
13
  type: 'metric alert',
14
14
  query: 'test query'
15
- ]
15
+ }
16
16
  ].freeze
17
17
 
18
18
  UPDATED_RESPONSE = [
19
19
  '200',
20
- [
20
+ {
21
21
  name: 'Monitor name',
22
22
  type: :metric_alert,
23
23
  query: 'scheduled maintenance query'
24
- ]
24
+ }
25
25
  ].freeze
26
26
 
27
27
  def setup
@@ -48,8 +48,8 @@ class TestClient < Minitest::Test
48
48
  new_monitor.query('test query')
49
49
 
50
50
  @client.client.stub :monitor, TEST_RESPONSE do
51
- @client.execute(new_monitor)
52
- assert_equal @client.response.status, :created
51
+ response = @client.execute(new_monitor)
52
+ assert_equal response.status, :created
53
53
  end
54
54
  end
55
55
 
@@ -59,8 +59,8 @@ class TestClient < Minitest::Test
59
59
  update_monitor.query('scheduled maintenance query')
60
60
 
61
61
  @client.client.stub :update_monitor, UPDATED_RESPONSE do
62
- @client.execute(update_monitor)
63
- assert_equal @client.response.status, :updated
62
+ response = @client.execute(update_monitor)
63
+ assert_equal response.status, :updated
64
64
  end
65
65
  end
66
66
  end
@@ -45,9 +45,16 @@ class TestMonitorModel < Minitest::Test
45
45
  end
46
46
 
47
47
  def test_validate
48
- assert_equal true, @monitor.validate
48
+ validation = @monitor.validate
49
+ assert_kind_of DogWatch::Model::Response, validation
50
+ assert_equal :created, validation.status
49
51
 
50
52
  @monitor.attributes.query = nil
51
- assert_equal false, @monitor.validate
53
+
54
+ failed_validation = @monitor.validate
55
+ assert_kind_of DogWatch::Model::Response, failed_validation
56
+ assert_equal :error, failed_validation.status
57
+ assert_equal 'The following errors occurred when creating monitor ' \
58
+ 'invalid: Missing monitor query', failed_validation.message
52
59
  end
53
60
  end
@@ -3,9 +3,9 @@ require_relative '../../lib/dogwatch/model/response'
3
3
 
4
4
  class TestResponse < MiniTest::Test
5
5
  def setup
6
- @error_res = DogWatch::Model::Response.new(ERROR_RES)
7
- @valid_res = DogWatch::Model::Response.new(VALID_RES)
8
- @accepted_res = DogWatch::Model::Response.new(ACCEPTED_RES)
6
+ @error_res = DogWatch::Model::Response.new(ERROR_RES, 'error')
7
+ @valid_res = DogWatch::Model::Response.new(VALID_RES, 'foobar')
8
+ @accepted_res = DogWatch::Model::Response.new(ACCEPTED_RES, 'foobar')
9
9
  end
10
10
 
11
11
  def test_status_is_error
@@ -17,7 +17,8 @@ class TestResponse < MiniTest::Test
17
17
  end
18
18
 
19
19
  def test_status_message
20
- assert_equal ["The value provided for parameter 'query' is invalid"], \
20
+ assert_equal 'The following errors occurred when creating monitor error: ' \
21
+ "The value provided for parameter 'query' is invalid", \
21
22
  @error_res.message
22
23
  end
23
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dogwatch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Greene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-13 00:00:00.000000000 Z
11
+ date: 2017-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dogapi
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.21'
19
+ version: '1.27'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.21'
26
+ version: '1.27'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: thor
29
29
  requirement: !ruby/object:Gem::Requirement