doggy 2.1.1 → 3.0.0.pre.beta1

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
  SHA256:
3
- metadata.gz: 782b3d86af1a0b64f7ddd7816230e1a159e95ab32e22912e9e4aadbdefde5c82
4
- data.tar.gz: 7e61f95d945bbd721e2f2ca2ee6070f84940a922dfbf0ec7298c4e77f247cd94
3
+ metadata.gz: af6510f8934d8d58b5f5cf9a318c7c4fd66893651cc1fcf9c24db4ebfb46e56b
4
+ data.tar.gz: 264f30ed2bd2ea394a29cc780c266f5345c092dc485ea7eca742cf00d9f6505f
5
5
  SHA512:
6
- metadata.gz: 05f92c7090313cfb21727e5159a6232532cd44f57ef565c837662f6aa3ed8e6a75a49ce86bda5609acfcb7c3e6384228b05d112dc5ab975894a658ea0508d433
7
- data.tar.gz: 7bf88190e67e97e33cfee61a57d83f7f14e15e2889b3384eea86b2d1fd92780307a7e4adafe49d32ee6579446f24d53cc51fc877906ece9b8604cf0b59da0a5a
6
+ metadata.gz: a7e116d5a61c47f44639695c245d3377c501a826935b33c39fa1b6d5ac487fef6f26ad6bc6395f572311d8101d129c544bac3366b08953fe48dbfeee897f551d
7
+ data.tar.gz: 55d8c1a9a3bb4797817d6ab012309e45a68855959c3bab9c47081e1ee85f354d0309dd1fbbbdfef2a7321fdbe9985bbd1eb020c4d4538945a10014b88e21f964
data/Gemfile.lock CHANGED
@@ -1,12 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- doggy (2.1.1)
4
+ doggy (3.0.0.pre.beta1)
5
5
  activesupport
6
6
  parallel
7
7
  rugged
8
8
  thor
9
- virtus
10
9
 
11
10
  GEM
12
11
  remote: https://rubygems.org/
@@ -19,23 +18,13 @@ GEM
19
18
  addressable (2.6.0)
20
19
  public_suffix (>= 2.0.2, < 4.0)
21
20
  ast (2.4.0)
22
- axiom-types (0.1.1)
23
- descendants_tracker (~> 0.0.4)
24
- ice_nine (~> 0.11.0)
25
- thread_safe (~> 0.3, >= 0.3.1)
26
21
  coderay (1.1.2)
27
- coercible (1.0.0)
28
- descendants_tracker (~> 0.0.1)
29
22
  concurrent-ruby (1.1.5)
30
23
  crack (0.4.3)
31
24
  safe_yaml (~> 1.0.0)
32
- descendants_tracker (0.0.4)
33
- thread_safe (~> 0.3, >= 0.3.1)
34
- equalizer (0.0.11)
35
- hashdiff (0.3.8)
25
+ hashdiff (0.3.9)
36
26
  i18n (1.6.0)
37
27
  concurrent-ruby (~> 1.0)
38
- ice_nine (0.11.2)
39
28
  jaro_winkler (1.5.2)
40
29
  metaclass (0.0.4)
41
30
  method_source (0.9.2)
@@ -43,7 +32,7 @@ GEM
43
32
  mocha (1.8.0)
44
33
  metaclass (~> 0.0.1)
45
34
  parallel (1.17.0)
46
- parser (2.6.2.1)
35
+ parser (2.6.3.0)
47
36
  ast (~> 2.4.0)
48
37
  pry (0.12.2)
49
38
  coderay (~> 1.1.0)
@@ -68,11 +57,6 @@ GEM
68
57
  tzinfo (1.2.5)
69
58
  thread_safe (~> 0.1)
70
59
  unicode-display_width (1.5.0)
71
- virtus (1.0.5)
72
- axiom-types (~> 0.1)
73
- coercible (~> 1.0)
74
- descendants_tracker (~> 0.0, >= 0.0.3)
75
- equalizer (~> 0.0, >= 0.0.9)
76
60
  webmock (3.5.1)
77
61
  addressable (>= 2.3.6)
78
62
  crack (>= 0.3.2)
data/README.md CHANGED
@@ -30,10 +30,6 @@ Export `DATADOG_API_KEY` and `DATADOG_APP_KEY` environment variables and `doggy`
30
30
 
31
31
  Optional: You can set `DATADOG_BASE_HUMAN_URL` environment variable if your organization uses a custom domain. This will change the urls given to users.
32
32
 
33
- #### ejson
34
-
35
- Set up `ejson` by putting `secrets.ejson` in your root object store.
36
-
37
33
  #### json (plaintext)
38
34
 
39
35
  If you're feeling adventurous, just put plaintext `secrets.json` in your root object store like this:
data/dev.yml CHANGED
@@ -4,7 +4,7 @@ up:
4
4
  - homebrew:
5
5
  - cmake
6
6
  - ruby:
7
- version: 2.6.2
7
+ version: 2.6.3
8
8
  - bundler
9
9
  commands:
10
10
  console:
data/doggy.gemspec CHANGED
@@ -1,13 +1,8 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
- lib = File.expand_path('../lib', __FILE__)
5
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
- require 'doggy/version'
7
-
8
3
  Gem::Specification.new do |spec|
9
4
  spec.name = "doggy"
10
- spec.version = Doggy::VERSION
5
+ spec.version = "3.0.0-beta1"
11
6
  spec.authors = ["Vlad Gorodetsky", "Andre Medeiros"]
12
7
  spec.email = ["v@gor.io", "me@andremedeiros.info"]
13
8
 
@@ -25,13 +20,12 @@ Gem::Specification.new do |spec|
25
20
 
26
21
  spec.add_runtime_dependency("parallel")
27
22
  spec.add_runtime_dependency("thor")
28
- spec.add_runtime_dependency("virtus")
29
23
  spec.add_runtime_dependency("rugged")
30
- spec.add_runtime_dependency('activesupport')
24
+ spec.add_runtime_dependency("activesupport")
31
25
 
32
26
  spec.add_development_dependency("bundler")
33
27
  spec.add_development_dependency("rake")
34
28
  spec.add_development_dependency("minitest")
35
- spec.add_development_dependency('pry')
36
- spec.add_development_dependency('rubocop')
29
+ spec.add_development_dependency("pry")
30
+ spec.add_development_dependency("rubocop")
37
31
  end
data/lib/doggy.rb CHANGED
@@ -1,10 +1,10 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require "pathname"
5
4
  require "net/http"
6
5
  require "rugged"
7
6
 
7
+ require "doggy/hash_sort"
8
8
  require "doggy/cli"
9
9
  require "doggy/cli/edit"
10
10
  require "doggy/cli/mute"
@@ -15,12 +15,10 @@ require "doggy/cli/delete"
15
15
  require "doggy/model"
16
16
  require "doggy/models/dashboard"
17
17
  require "doggy/models/monitor"
18
- require "doggy/models/screen"
19
- require "doggy/version"
20
18
 
21
19
  module Doggy
22
- DOG_SKIP_REGEX = /\xF0\x9F\x98\xB1|:scream:/i.freeze
23
- MANAGED_BY_DOGGY_REGEX = /\xF0\x9F\x90\xB6|:dog:/i.freeze
20
+ DOG_SKIP_REGEX = /😱|:scream:/i.freeze
21
+ MANAGED_BY_DOGGY_REGEX = /🐶|:dog:/i.freeze
24
22
 
25
23
  class DoggyError < StandardError; end
26
24
 
data/lib/doggy/cli.rb CHANGED
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require "thor"
@@ -7,13 +6,6 @@ module Doggy
7
6
  class CLI < Thor
8
7
  include Thor::Actions
9
8
 
10
- map %w(--version -v) => :__print_version
11
-
12
- desc '--version, -v', 'print the version'
13
- def __print_version
14
- puts Doggy::VERSION
15
- end
16
-
17
9
  desc "pull [IDs]", "Pulls objects from Datadog"
18
10
 
19
11
  def pull(*ids)
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Doggy
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Doggy
@@ -23,8 +22,6 @@ module Doggy
23
22
  new_resource.description = resource.description
24
23
  elsif new_resource.is_a?(Doggy::Models::Monitor)
25
24
  new_resource.name = resource.name
26
- elsif new_resource.is_a?(Doggy::Models::Screen)
27
- new_resource.board_title = resource.board_title
28
25
  end
29
26
  new_resource.path = resource.path
30
27
  new_resource.save_local
@@ -39,20 +36,18 @@ module Doggy
39
36
  end
40
37
 
41
38
  def fork(resource)
42
- salt = Doggy.random_word
43
- forked_resource = resource.dup
44
- forked_resource.id = nil
39
+ forked_resource = resource.class.new(resource.attributes.except("id")) # TODO: Except "url" too
40
+ forked_resource.path = resource.path # TODO: should not be forked
45
41
  forked_resource.refute_read_only!
42
+
46
43
  if /dashboard/.match?(resource.class.to_s.downcase)
47
- forked_resource.title = "[#{salt}] " + forked_resource.title
48
- forked_resource.description = "[fork of #{resource.id}] " + forked_resource.title
49
- elsif /screen/.match?(resource.class.to_s.downcase)
50
- forked_resource.board_title = "[#{salt}] " + forked_resource.board_title
44
+ forked_resource.title = "[#{Doggy.random_word}] #{resource.title}"
51
45
  elsif /monitor/.match?(resource.class.to_s.downcase)
52
- forked_resource.name = "[#{salt}] " + forked_resource.name
46
+ forked_resource.name = "[#{Doggy.random_word}] #{resource.name}"
53
47
  else
54
48
  raise StandardError, 'Unknown resource type, cannot edit.'
55
49
  end
50
+
56
51
  forked_resource.save
57
52
  forked_resource
58
53
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'doggy/duration'
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'parallel'
@@ -12,9 +11,20 @@ module Doggy
12
11
 
13
12
  def run
14
13
  @local_resources = Doggy::Model.all_local_resources
14
+ id_migration_mapping = {}
15
+
15
16
  if @ids.empty?
16
17
  Parallel.each(@local_resources) do |local_resource|
17
- if remote_resource = local_resource.class.find(local_resource.id)
18
+ remote_resource = local_resource.class.find(local_resource.id)
19
+ if (new_id = remote_resource&.attributes&.dig("dash", "new_id")) || (new_id = remote_resource&.attributes&.dig("new_id"))
20
+ id_migration_mapping[local_resource.id.to_s] = local_resource.class.find(new_id)
21
+ end
22
+
23
+ if remote_resource
24
+ if id_migration_mapping.key?(local_resource.id)
25
+ remote_resource.attributes = id_migration_mapping[local_resource.id].attributes
26
+ end
27
+
18
28
  remote_resource.path = local_resource.path
19
29
  remote_resource.save_local
20
30
  else
@@ -22,29 +32,34 @@ module Doggy
22
32
  end
23
33
  end
24
34
  else
25
- @ids.each { |id| pull_by_id(id.to_i) }
35
+ @ids.each { |id| pull_by_id(id.to_s) }
26
36
  end
27
37
  end
28
38
 
29
39
  private
30
40
 
31
41
  def pull_by_id(id)
32
- local_resources = @local_resources.find_all { |l| l.id == id }
42
+ local_resources = @local_resources.find_all { |l| l.id.to_s == id.to_s }
43
+ id_migration_mapping = {}
33
44
 
34
- remote_resources = [Models::Dashboard, Models::Monitor, Models::Screen].map do |klass|
35
- klass.find(id)
45
+ remote_resources = [Models::Dashboard, Models::Monitor].map do |klass|
46
+ result = klass.find(id.to_s)
47
+ if (new_id = result&.attributes&.dig("dash", "new_id")) || (new_id = result&.attributes&.dig("new_id"))
48
+ id_migration_mapping[id.to_s] = klass.find(new_id)
49
+ end
50
+ result
36
51
  end.compact
37
52
 
38
53
  if local_resources.size != remote_resources.size
39
- normalized_remote_resources = remote_resources.map { |remote_resource| [remote_resource.class.name, remote_resource.id] }
40
- normalized_local_resources = local_resources.map { |local_resource| [local_resource.class.name, local_resource.id] }
54
+ normalized_remote_resources = remote_resources.map { |remote_resource| [remote_resource.class.name, remote_resource.id.to_s] }
55
+ normalized_local_resources = local_resources.map { |local_resource| [local_resource.class.name, local_resource.id.to_s] }
41
56
  normalized_resource_diff = Hash[normalized_remote_resources - normalized_local_resources]
42
57
 
43
58
  # Here we traverse `remote_resources` to find remote resource with matching class name and id.
44
59
  # We cannot subtract `local_resources` from `remote_resources` because those are different kind of objects.
45
60
  remote_resources_to_be_saved = normalized_resource_diff.map do |klass, normalized_resource_id|
46
61
  remote_resources.find do |rr|
47
- rr.class.name == klass && rr.id == normalized_resource_id
62
+ rr.class.name == klass && rr.id.to_s == normalized_resource_id.to_s
48
63
  end
49
64
  end
50
65
 
@@ -52,6 +67,11 @@ module Doggy
52
67
  else
53
68
  local_resources.each do |local_resource|
54
69
  remote_resource = local_resource.class.find(local_resource.id)
70
+
71
+ if id_migration_mapping.key?(local_resource.id)
72
+ remote_resource.attributes = id_migration_mapping[local_resource.id].attributes
73
+ end
74
+
55
75
  remote_resource.path = local_resource.path
56
76
  remote_resource.save_local
57
77
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Doggy
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Doggy
@@ -23,7 +23,7 @@ module Duration
23
23
  }
24
24
 
25
25
  def self.parse(value)
26
- unless match = DURATION_FORMAT.match(value)
26
+ unless (match = DURATION_FORMAT.match(value))
27
27
  raise ArgumentError, "not a duration: #{value.inspect}, "\
28
28
  "use digits followed by a unit (#{DURATION_UNITS.map { |k, v| "#{k} for #{v}" }.join(', ')})"
29
29
  end
@@ -0,0 +1,13 @@
1
+ class Hash
2
+ def sort_by_key(&block)
3
+ self.keys.sort(&block).reduce({}) do |seed, key|
4
+ seed[key] = self[key]
5
+ if seed[key].is_a?(Hash)
6
+ seed[key] = seed[key].sort_by_key(&block)
7
+ elsif seed[key].is_a?(Array)
8
+ seed[key] = seed[key].map { |i| i.sort_by_key(&block) }
9
+ end
10
+ seed
11
+ end
12
+ end
13
+ end
data/lib/doggy/model.rb CHANGED
@@ -1,30 +1,32 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require "json"
5
4
  require "parallel"
6
5
  require "uri"
7
- require "virtus"
6
+ require "active_support/core_ext/hash/keys"
8
7
 
9
8
  module Doggy
10
9
  class Model
11
- include Virtus.model
10
+ # Denormalized object attributes.
11
+ attr_accessor :attributes
12
12
 
13
13
  # This stores the path on disk. We don't define it as a model attribute so
14
14
  # it doesn't get serialized.
15
15
  attr_accessor :path
16
16
 
17
- # indicates whether an object locally deleted
17
+ # Indicates whether an object locally deleted
18
18
  attr_accessor :is_deleted
19
19
 
20
20
  # This stores whether the resource has been loaded locally or remotely.
21
21
  attr_accessor :loading_source
22
22
 
23
23
  class << self
24
- attr_accessor :root
25
-
26
24
  def find(id)
27
- attributes = request(:get, resource_url(id), nil, [404])
25
+ attributes = request(:get, resource_url(id), nil, [404, 400])
26
+ if self == Doggy::Models::Dashboard
27
+ attributes = request(:get, resource_url(id, "dash"), nil, [404, 400]) if attributes['errors']
28
+ attributes = request(:get, resource_url(id, "screen"), nil, [404, 400]) if attributes['errors']
29
+ end
28
30
  return if attributes['errors']
29
31
  resource = new(attributes)
30
32
 
@@ -34,11 +36,13 @@ module Doggy
34
36
 
35
37
  def find_local(param)
36
38
  resources = Doggy::Model.all_local_resources
37
- if (id = param).is_a?(Integer) || (param =~ /^[0-9]+$/ && id = Integer(param))
38
- return resources.find { |res| res.id == id }
39
+ param = param.to_s
40
+ if (param =~ /^[0-9]+$/) || (param =~ /^[a-z0-9]+-[a-z0-9]+-[a-z0-9]+$/)
41
+ id = param
42
+ return resources.find { |res| res.id == id.to_s || res.id == id.to_i }
39
43
  end
40
- if id = param[%r{(dash/|screen/|monitors#)(\d+)}i, 2]
41
- return resources.find { |res| res.id == Integer(id) }
44
+ if (id = param[%r{(dashboard/|monitors#)(\d+)}i, 2])
45
+ return resources.find { |res| res.id == id.to_s || res.id == id.to_i }
42
46
  end
43
47
  full_path = File.expand_path(param.gsub('objects/', ''), Doggy.object_root)
44
48
  resources.find { |res| res.path == full_path }
@@ -84,10 +88,7 @@ module Doggy
84
88
  end
85
89
 
86
90
  def infer_type(attributes)
87
- has_key = ->(key) { attributes.key?(key.to_s) || attributes.key?(key.to_sym) }
88
- return Models::Dashboard if has_key.call('graphs')
89
- return Models::Monitor if has_key.call('message')
90
- return Models::Screen if has_key.call('board_title')
91
+ attributes.key?("message") ? Models::Monitor : Models::Dashboard
91
92
  end
92
93
 
93
94
  def request(method, url, body = nil, accepted_errors = nil)
@@ -103,11 +104,11 @@ module Doggy
103
104
  http.use_ssl = (uri.scheme == 'https')
104
105
 
105
106
  request = case method
106
- when :get then Net::HTTP::Get.new(uri.request_uri)
107
- when :post then Net::HTTP::Post.new(uri.request_uri)
108
- when :put then Net::HTTP::Put.new(uri.request_uri)
109
- when :delete then Net::HTTP::Delete.new(uri.request_uri)
110
- end
107
+ when :get then Net::HTTP::Get.new(uri.request_uri)
108
+ when :post then Net::HTTP::Post.new(uri.request_uri)
109
+ when :put then Net::HTTP::Put.new(uri.request_uri)
110
+ when :delete then Net::HTTP::Delete.new(uri.request_uri)
111
+ end
111
112
 
112
113
  request.content_type = 'application/json'
113
114
  request.body = body if body
@@ -149,15 +150,8 @@ module Doggy
149
150
  }.to_json)
150
151
  end
151
152
 
152
- def sort_by_key(hash, &block)
153
- hash.keys.sort(&block).each_with_object({}) do |key, seed|
154
- seed[key] = hash[key]
155
- if seed[key].is_a?(Hash)
156
- seed[key] = Doggy::Model.sort_by_key(seed[key], &block)
157
- elsif seed[key].is_a?(Array)
158
- seed[key].each_with_index { |e, i| seed[key][i] = sort_by_key(e, &block) if e.is_a?(Hash) }
159
- end
160
- end
153
+ def sort_by_key(hash)
154
+ hash
161
155
  end
162
156
 
163
157
  protected
@@ -167,18 +161,15 @@ module Doggy
167
161
  end
168
162
  end # class << self
169
163
 
170
- def ==(another_model)
171
- to_h == another_model.to_h
164
+ def ==(other)
165
+ to_h == other.to_h
172
166
  end
173
167
 
174
- def initialize(attributes = nil)
175
- root_key = self.class.root
176
-
177
- return super unless attributes && root_key
178
- return super unless attributes[root_key].is_a?(Hash)
168
+ def initialize(attributes = {})
169
+ @attributes = attributes.deep_stringify_keys
179
170
 
180
- attributes = attributes[root_key]
181
- super(attributes)
171
+ @attributes["id"] = @attributes["id"].to_s if @attributes["id"]
172
+ @attributes["options"] ||= {} if self.class == Doggy::Models::Monitor
182
173
  end
183
174
 
184
175
  def save_local
@@ -188,7 +179,7 @@ module Doggy
188
179
  end
189
180
 
190
181
  def to_h
191
- Doggy::Model.sort_by_key(super)
182
+ Doggy::Model.sort_by_key(attributes)
192
183
  end
193
184
 
194
185
  def validate
@@ -212,7 +203,7 @@ module Doggy
212
203
  end
213
204
 
214
205
  def destroy
215
- self.class.request(:delete, resource_url(id), nil, [404])
206
+ self.class.request(:delete, resource_url(id), nil, [404, 400])
216
207
  end
217
208
 
218
209
  def destroy_local
@@ -1,21 +1,50 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Doggy
5
4
  module Models
6
5
  class Dashboard < Doggy::Model
7
- self.root = 'dash'
6
+ def id
7
+ attributes["id"]
8
+ end
9
+
10
+ def id=(v)
11
+ attributes["id"] = v
12
+ end
8
13
 
9
- attribute :id, Integer
10
- attribute :title, String
11
- attribute :description, String
14
+ def title
15
+ attributes["title"]
16
+ end
12
17
 
13
- attribute :graphs, Array[Hash]
14
- attribute :template_variables, Array[Hash]
15
- attribute :read_only, Boolean
18
+ def title=(v)
19
+ attributes["title"] = v
20
+ end
21
+
22
+ def description
23
+ attributes["description"]
24
+ end
25
+
26
+ def description=(v)
27
+ attributes["description"] = v
28
+ end
29
+
30
+ def read_only
31
+ if attributes["widgets"]
32
+ attributes["is_read_only"]
33
+ else
34
+ attributes["read_only"]
35
+ end
36
+ end
37
+
38
+ def read_only=(v)
39
+ if attributes["widgets"]
40
+ attributes["is_read_only"] = v
41
+ else
42
+ attributes["read_only"] = v
43
+ end
44
+ end
16
45
 
17
46
  def prefix
18
- 'dash'
47
+ 'dashboard'
19
48
  end
20
49
 
21
50
  def ensure_read_only!
@@ -26,22 +55,22 @@ module Doggy
26
55
  self.read_only = false
27
56
  end
28
57
 
29
- def self.resource_url(id = nil)
30
- ["https://app.datadoghq.com/api/v1/dash", id].compact.join("/")
58
+ def self.resource_url(id = nil, kind = "dashboard")
59
+ ["https://app.datadoghq.com/api/v1/#{kind}", id].compact.join("/")
31
60
  end
32
61
 
33
62
  def managed?
34
- !(title =~ Doggy::DOG_SKIP_REGEX)
63
+ title !~ Doggy::DOG_SKIP_REGEX
35
64
  end
36
65
 
37
66
  def ensure_managed_emoji!
38
67
  return unless managed?
39
- return if title =~ /\xF0\x9F\x90\xB6/
40
- self.title += " \xF0\x9F\x90\xB6"
68
+ return if title =~ /🐶/
69
+ self.title = "#{title} 🐶"
41
70
  end
42
71
 
43
72
  def human_url
44
- "https://#{Doggy.base_human_url}/dash/#{id}"
73
+ "https://#{Doggy.base_human_url}/dashboard/#{id}"
45
74
  end
46
75
 
47
76
  # Dashboards don't have a direct edit URL
@@ -1,70 +1,64 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Doggy
5
4
  module Models
6
5
  class Monitor < Doggy::Model
7
- class Options
8
- include Virtus.model
9
-
10
- attribute :escalation_message, String
11
- attribute :evaluation_delay, Integer
12
- attribute :include_tags, Boolean
13
- attribute :locked, Boolean
14
- attribute :new_host_delay, Integer
15
- attribute :no_data_timeframe, Integer
16
- attribute :notify_audit, Boolean
17
- attribute :notify_no_data, Boolean
18
- attribute :renotify_interval, Integer
19
- attribute :require_full_window, Boolean
20
- attribute :silenced, Hash
21
- attribute :thresholds, Hash
22
- attribute :timeout_h, Integer
23
- end
24
-
25
- attribute :id, Integer
26
- attribute :org_id, Integer
27
- attribute :name, String
28
-
29
- attribute :message, String
30
- attribute :query, String
31
- attribute :options, Options
32
- attribute :tags, Array[String]
33
- attribute :type, String
34
- attribute :multi, Boolean
6
+ def id
7
+ attributes["id"]
8
+ end
9
+
10
+ def id=(v)
11
+ attributes["id"] = v
12
+ end
13
+
14
+ def name
15
+ attributes["name"]
16
+ end
17
+
18
+ def name=(v)
19
+ attributes["name"] = v
20
+ end
21
+
22
+ def locked
23
+ attributes["options"]["locked"]
24
+ end
25
+
26
+ def locked=(v)
27
+ attributes["options"]["locked"] = v
28
+ end
29
+
30
+ def silenced
31
+ attributes["options"]["silenced"]
32
+ end
33
+
34
+ def silenced=(v)
35
+ attributes["options"]["silenced"] = v
36
+ end
35
37
 
36
38
  def prefix
37
39
  'monitor'
38
40
  end
39
41
 
40
42
  def ensure_read_only!
41
- if options
42
- options.locked = true
43
- else
44
- self.options = Options.new(locked: true)
45
- end
43
+ attributes["options"]["locked"] = true
46
44
  end
47
45
 
48
46
  def refute_read_only!
49
- if options
50
- options.locked = false
51
- else
52
- self.options = Options.new(locked: false)
53
- end
47
+ attributes["options"]["locked"] = false
54
48
  end
55
49
 
56
- def self.resource_url(id = nil)
57
- ["https://app.datadoghq.com/api/v1/monitor", id].compact.join("/")
50
+ def self.resource_url(id = nil, kind = "monitor")
51
+ ["https://app.datadoghq.com/api/v1/#{kind}", id].compact.join("/")
58
52
  end
59
53
 
60
54
  def managed?
61
- !(name =~ Doggy::DOG_SKIP_REGEX)
55
+ name !~ Doggy::DOG_SKIP_REGEX
62
56
  end
63
57
 
64
58
  def ensure_managed_emoji!
65
59
  return unless managed?
66
- return if name =~ /\xF0\x9F\x90\xB6/
67
- self.name += " \xF0\x9F\x90\xB6"
60
+ return if name =~ /🐶/
61
+ self.name += " 🐶"
68
62
  end
69
63
 
70
64
  def validate
@@ -74,11 +68,11 @@ module Doggy
74
68
  def toggle_mute!(action, body = nil)
75
69
  return unless %w[mute unmute].include?(action) && id
76
70
  attributes = request(:post, "#{resource_url(id)}/#{action}", body)
77
- if message = attributes['errors']
71
+ if (message = attributes['errors'])
78
72
  Doggy.ui.error(message)
79
73
  else
80
74
  self.attributes = attributes
81
- if local_version = Doggy::Model.find_local(id)
75
+ if (local_version = Doggy::Model.find_local(id))
82
76
  self.path = local_version.path
83
77
  end
84
78
  save_local
@@ -93,19 +87,15 @@ module Doggy
93
87
  "https://#{Doggy.base_human_url}/monitors##{id}/edit"
94
88
  end
95
89
 
96
- def to_h
97
- Doggy::Model.sort_by_key(super.merge(options: options.to_h))
98
- end
99
-
100
90
  private
101
91
 
102
92
  def ensure_renotify_interval_valid
103
- return unless options&.renotify_interval && options.renotify_interval.to_i > 0
93
+ return unless attributes.dig("options", "renotify_interval") && attributes.dig("options", "renotify_interval").to_i > 0
104
94
 
105
95
  allowed_renotify_intervals = [10, 20, 30, 40, 50, 60, 90, 120, 180, 240, 300, 360, 720, 1440] # minutes
106
- best_matching_interval = allowed_renotify_intervals.min_by { |x| (x.to_f - options.renotify_interval).abs }
107
- puts "WARN: Monitor #{id} uses invalid escalation interval (renotify_interval) #{options.renotify_interval}, using #{best_matching_interval} instead"
108
- options.renotify_interval = best_matching_interval
96
+ best_matching_interval = allowed_renotify_intervals.min_by { |x| (x.to_f - attributes["options"]["renotify_interval"]).abs }
97
+ puts "WARN: Monitor #{id} uses invalid escalation interval (renotify_interval) #{attributes["options"]["renotify_interval"]}, using #{best_matching_interval} instead"
98
+ attributes["options"]["renotify_interval"] = best_matching_interval
109
99
  end
110
100
  end # Monitor
111
101
  end # Models
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doggy
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 3.0.0.pre.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vlad Gorodetsky
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-04-16 00:00:00.000000000 Z
12
+ date: 2019-05-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parallel
@@ -39,20 +39,6 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
- - !ruby/object:Gem::Dependency
43
- name: virtus
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- version: '0'
49
- type: :runtime
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: '0'
56
42
  - !ruby/object:Gem::Dependency
57
43
  name: rugged
58
44
  requirement: !ruby/object:Gem::Requirement
@@ -184,11 +170,10 @@ files:
184
170
  - lib/doggy/cli/push.rb
185
171
  - lib/doggy/cli/unmute.rb
186
172
  - lib/doggy/duration.rb
173
+ - lib/doggy/hash_sort.rb
187
174
  - lib/doggy/model.rb
188
175
  - lib/doggy/models/dashboard.rb
189
176
  - lib/doggy/models/monitor.rb
190
- - lib/doggy/models/screen.rb
191
- - lib/doggy/version.rb
192
177
  homepage: http://github.com/shopify/doggy
193
178
  licenses:
194
179
  - MIT
@@ -204,9 +189,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
204
189
  version: '2.5'
205
190
  required_rubygems_version: !ruby/object:Gem::Requirement
206
191
  requirements:
207
- - - ">="
192
+ - - ">"
208
193
  - !ruby/object:Gem::Version
209
- version: '0'
194
+ version: 1.3.1
210
195
  requirements: []
211
196
  rubyforge_project:
212
197
  rubygems_version: 2.7.6
@@ -1,52 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
-
4
- module Doggy
5
- module Models
6
- class Screen < Doggy::Model
7
- attribute :id, Integer
8
- attribute :board_title, String
9
-
10
- attribute :board_bgtype, String
11
- attribute :templated, Boolean
12
- attribute :template_variables, Array[Hash]
13
- attribute :widgets, Array[Hash]
14
- attribute :height, String
15
- attribute :width, String
16
- attribute :read_only, Boolean
17
-
18
- def prefix
19
- 'screen'
20
- end
21
-
22
- def ensure_read_only!
23
- self.read_only = true
24
- end
25
-
26
- def refute_read_only!
27
- self.read_only = false
28
- end
29
-
30
- def self.resource_url(id = nil)
31
- ["https://app.datadoghq.com/api/v1/screen", id].compact.join("/")
32
- end
33
-
34
- def managed?
35
- !(board_title =~ Doggy::DOG_SKIP_REGEX)
36
- end
37
-
38
- def ensure_managed_emoji!
39
- return unless managed?
40
- return if board_title =~ /\xF0\x9F\x90\xB6/
41
- self.board_title += " \xF0\x9F\x90\xB6"
42
- end
43
-
44
- def human_url
45
- "https://#{Doggy.base_human_url}/screen/#{id}"
46
- end
47
-
48
- # Screens don't have a direct edit URL
49
- alias_method :human_edit_url, :human_url
50
- end # Screen
51
- end # Models
52
- end # Doggy
data/lib/doggy/version.rb DELETED
@@ -1,6 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: true
3
-
4
- module Doggy
5
- VERSION = '2.1.1'
6
- end