kennel 1.18.2 → 1.19.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
  SHA256:
3
- metadata.gz: 734334b788520b60627349b1938a3ff689a7a7f70a73ea2ae89461c0e0ec36e8
4
- data.tar.gz: 72996467fb2c1f1ca7a3af55e0e7a70f28c8db29173dedb5ccb0e9010137ec58
3
+ metadata.gz: ce664560cea8f70dc49a11711f81a38faab96a425439fc0e58afa0e35318ddf6
4
+ data.tar.gz: 761f7741b0787dea3d09bc22b15467f8fa5b3626504a593e93d4edd6728a6088
5
5
  SHA512:
6
- metadata.gz: 2cf10e3bfa2a185ced7fcd831cff8fdac2405a99a053d9c6eb58507fcb06acdf7b73597cd10a77674ce3c57cdd4346ff9651f0b2f56428e690ee2546cbe4cae2
7
- data.tar.gz: e9b6b44dbf0e83613ed4492e21cd521105777286e3e094e917baf02d9ada504971396ca176c22856ed8ac33501f7066c98917e8366752c0bfa0ae27e9a6ec05e
6
+ metadata.gz: d6e9573898edfd15e5fb34f1ab749b6bc5a8f4f70a75d855e229dc9a98af66c30a748b348d4095b7d361bb8f71cda6b75448e08c4cc9f1efda7b6312bf32d791
7
+ data.tar.gz: 0e42c01940e220d1a4fce162419b4c9279ead3a1f751f74b4ae15033c2399773ed2886779189b2ea93411963ae3e87da230a2656d1dcd21a20de6a26291f1a2e
@@ -2,36 +2,44 @@
2
2
 
3
3
  module Kennel
4
4
  class Importer
5
- SORT_ORDER = [:title, :id, :description, :template_variables].freeze
6
-
7
- # TODO: make model diff normalization reusable
8
- IGNORED = Models::Base::READONLY_ATTRIBUTES - [:id] + [:created_by, :read_only]
5
+ SORT_ORDER = [:title, :name, :board_title, :id, :query, :message, :description, :template_variables].freeze
9
6
 
10
7
  def initialize(api)
11
8
  @api = api
12
9
  end
13
10
 
14
11
  def import(resource, id)
15
- data = @api.show(resource, id)
16
- case resource
17
- when "dash"
18
- data = data[:dash]
19
- IGNORED.each { |k| data.delete(k) }
20
- <<~RUBY
21
- Kennel::Models::Dash.new(
22
- self,
23
- #{pretty_print(data).lstrip}
24
- )
25
- RUBY
26
- else
27
- raise ArgumentError, "#{resource} is not supported"
12
+ model =
13
+ begin
14
+ Kennel::Models.const_get(resource.capitalize)
15
+ rescue NameError
16
+ raise ArgumentError, "#{resource} is not supported"
17
+ end
18
+
19
+ data = @api.show(model.api_resource, id)
20
+ data = data[resource.to_sym] || data
21
+ model.normalize({}, data)
22
+ data[:id] = id
23
+
24
+ # flatten monitor options so they are all on the base
25
+ if resource == "monitor"
26
+ data.merge!(data.delete(:options))
27
+ data.merge!(data.delete(:thresholds) || {})
28
+ data = data.slice(*model.instance_methods)
28
29
  end
30
+
31
+ <<~RUBY
32
+ #{model.name}.new(
33
+ self,
34
+ #{pretty_print(data).lstrip}
35
+ )
36
+ RUBY
29
37
  end
30
38
 
31
39
  private
32
40
 
33
41
  def pretty_print(hash)
34
- list = hash.sort_by { |k, _| SORT_ORDER.index(k) || 999 }
42
+ list = hash.sort_by { |k, _| [SORT_ORDER.index(k) || 999, k] } # important to the front and rest deterministic
35
43
  list.map do |k, v|
36
44
  case v
37
45
  when Hash, Array
@@ -53,6 +53,38 @@ module Kennel
53
53
  supported = @set.map(&:inspect)
54
54
  raise ArgumentError, "Unsupported setting #{name.inspect}, supported settings are #{supported.join(", ")}"
55
55
  end
56
+
57
+ private
58
+
59
+ def normalize(_expected, actual)
60
+ self::READONLY_ATTRIBUTES.each { |k| actual.delete k }
61
+ end
62
+
63
+ # discard styles/conditional_formats/aggregator if nothing would change when we applied (both are default or nil)
64
+ def ignore_request_defaults(expected, actual, level1, level2)
65
+ (actual[level1] || []).each_with_index do |a_w, wi|
66
+ a_r = a_w.dig(level2, :requests) || []
67
+ e_r = expected.dig(level1, wi, level2, :requests) || []
68
+ ignore_defaults e_r, a_r, REQUEST_DEFAULTS
69
+ end
70
+ end
71
+
72
+ def ignore_defaults(expected, actual, defaults)
73
+ (expected || []).each_with_index do |e, i|
74
+ a = actual[i] || {}
75
+ ignore_default(e, a, defaults)
76
+ end
77
+ end
78
+
79
+ def ignore_default(expected, actual, defaults)
80
+ definitions = [actual, expected]
81
+ defaults.each do |key, default|
82
+ if definitions.all? { |r| !r.key?(key) || r[key] == default }
83
+ actual.delete(key)
84
+ expected.delete(key)
85
+ end
86
+ end
87
+ end
56
88
  end
57
89
 
58
90
  def initialize(options = {})
@@ -86,7 +118,7 @@ module Kennel
86
118
  expected = as_json
87
119
  expected.delete(:id)
88
120
 
89
- READONLY_ATTRIBUTES.each { |k| actual.delete k }
121
+ self.class.send(:normalize, expected, actual)
90
122
 
91
123
  HashDiff.diff(actual, expected, use_lcs: false)
92
124
  end
@@ -101,27 +133,6 @@ module Kennel
101
133
 
102
134
  private
103
135
 
104
- # discard styles/conditional_formats/aggregator if nothing would change when we applied (both are default or nil)
105
- def ignore_request_defaults(expected, actual, level1, level2)
106
- expected[level1].each_with_index do |e_w, wi|
107
- e_r = e_w.dig(level2, :requests) || []
108
- a_r = actual.dig(level1, wi, level2, :requests) || []
109
- ignore_defaults e_r, a_r, REQUEST_DEFAULTS
110
- end
111
- end
112
-
113
- def ignore_defaults(expected, actual, defaults)
114
- expected.each_with_index do |e, i|
115
- next unless a = actual[i] # skip newly added
116
- defaults.each do |key, default|
117
- if [a, e].all? { |r| r[key].nil? || r[key] == default }
118
- a.delete(key)
119
- e.delete(key)
120
- end
121
- end
122
- end
123
- end
124
-
125
136
  # let users know which project/resource failed when something happens during diffing where the backtrace is hidden
126
137
  def invalid!(message)
127
138
  raise ValidationError, "#{tracking_id} #{message}"
@@ -7,6 +7,10 @@ module Kennel
7
7
 
8
8
  API_LIST_INCOMPLETE = true
9
9
  SUPPORTED_GRAPH_OPTIONS = [:events, :markers].freeze
10
+ READONLY_ATTRIBUTES = (Base::READONLY_ATTRIBUTES + [:resource, :created_by, :read_only]).freeze
11
+ DEFINITION_DEFAULTS = { autoscale: true }.freeze
12
+ DASH_DEFAULTS = { template_variables: [] }.freeze
13
+
10
14
  settings :id, :title, :description, :graphs, :kennel_id, :graphs, :definitions
11
15
 
12
16
  defaults(
@@ -34,7 +38,6 @@ module Kennel
34
38
  id: id,
35
39
  title: "#{title}#{LOCK}",
36
40
  description: description,
37
- read_only: false, # TODO: delete it instead
38
41
  template_variables: render_template_variables,
39
42
  graphs: render_graphs
40
43
  }
@@ -44,15 +47,20 @@ module Kennel
44
47
  @json
45
48
  end
46
49
 
47
- def diff(actual)
48
- actual.delete :resource
49
- actual.delete :created_by
50
- actual[:template_variables] ||= []
51
- actual[:graphs].each do |g|
50
+ def self.normalize(expected, actual)
51
+ super
52
+
53
+ ignore_default expected, actual, DASH_DEFAULTS
54
+ (actual[:graphs] || {}).each do |g|
52
55
  g[:definition].delete(:status)
53
56
  end
54
- ignore_request_defaults as_json, actual, :graphs, :definition
55
- super
57
+ ignore_request_defaults expected, actual, :graphs, :definition
58
+
59
+ (actual[:graphs] || []).each_with_index do |a_g, i|
60
+ a_d = a_g[:definition] || {}
61
+ e_d = expected.dig(:graphs, i, :definition) || {}
62
+ ignore_default e_d, a_d, DEFINITION_DEFAULTS
63
+ end
56
64
  end
57
65
 
58
66
  def url(id)
@@ -64,7 +72,7 @@ module Kennel
64
72
  def validate_json(data)
65
73
  # check for bad variables
66
74
  # TODO: do the same check for apm_query and their group_by
67
- variables = data.fetch(:template_variables).map { |v| "$#{v.fetch(:name)}" }
75
+ variables = (data[:template_variables] || []).map { |v| "$#{v.fetch(:name)}" }
68
76
  queries = data[:graphs].flat_map { |g| g[:definition][:requests].map { |r| r[:q] }.compact }
69
77
  bad = queries.grep_v(/(#{variables.map { |v| Regexp.escape(v) }.join("|")})\b/)
70
78
  if bad.any?
@@ -86,7 +94,7 @@ module Kennel
86
94
  end
87
95
 
88
96
  def render_graphs
89
- all = definitions.map do |title, viz, type, queries, options = {}, ignored = nil|
97
+ definitions.map do |title, viz, type, queries, options = {}, ignored = nil|
90
98
  if ignored || (!title || !viz || !type || !queries || !options.is_a?(Hash))
91
99
  raise ArgumentError, "Expected exactly 5 arguments for each definition (title, viz, type, queries, options)"
92
100
  end
@@ -101,11 +109,6 @@ module Kennel
101
109
  end
102
110
  graph
103
111
  end + graphs
104
-
105
- # TODO: solve this via ignore-defaults
106
- all.each do |g|
107
- g[:definition][:autoscale] = true unless g[:definition].key?(:autoscale)
108
- end
109
112
  end
110
113
  end
111
114
  end
@@ -100,7 +100,8 @@ module Kennel
100
100
  Utils.path_to_url "/monitors##{id}/edit"
101
101
  end
102
102
 
103
- def diff(actual)
103
+ def self.normalize(_expected, actual)
104
+ super
104
105
  options = actual.fetch(:options)
105
106
  options.delete(:silenced) # we do not manage silenced, so ignore it when diffing
106
107
  options[:escalation_message] ||= nil # unset field is not returned and would break the diff
@@ -125,8 +126,6 @@ module Kennel
125
126
 
126
127
  # nil or "" are not returned from the api
127
128
  options[:evaluation_delay] ||= nil
128
-
129
- super
130
129
  end
131
130
 
132
131
  private
@@ -11,6 +11,23 @@ module Kennel
11
11
  time: {},
12
12
  timeframe: "1h"
13
13
  }.freeze
14
+ READONLY_ATTRIBUTES = (Base::READONLY_ATTRIBUTES + [
15
+ :disableCog,
16
+ :disableEditing,
17
+ :isIntegration,
18
+ :isShared,
19
+ :original_title,
20
+ :read_only,
21
+ :resource,
22
+ :title,
23
+ :title_edited,
24
+ :created_by,
25
+ :board_bgtype,
26
+ :height,
27
+ :width,
28
+ :showGlobalTimeOnboarding
29
+ ]).freeze
30
+ SCREEN_DEFAULTS = { template_variables: [] }.freeze
14
31
 
15
32
  settings :id, :board_title, :description, :widgets, :kennel_id
16
33
 
@@ -46,22 +63,9 @@ module Kennel
46
63
  @json
47
64
  end
48
65
 
49
- def diff(actual)
50
- actual.delete(:disableCog)
51
- actual.delete(:disableEditing)
52
- actual.delete(:isIntegration)
53
- actual.delete(:isShared)
54
- actual.delete(:original_title)
55
- actual.delete(:read_only)
56
- actual.delete(:resource)
57
- actual.delete(:title)
58
- actual.delete(:title_edited)
59
- actual.delete(:created_by)
60
- actual.delete(:board_bgtype)
61
- actual.delete(:height)
62
- actual.delete(:width)
63
- actual.delete(:showGlobalTimeOnboarding)
64
- actual[:template_variables] ||= []
66
+ def self.normalize(expected, actual)
67
+ super
68
+
65
69
  (actual[:widgets] || []).each do |w|
66
70
  # api randomly returns time.live_span or timeframe or empty time hash
67
71
  if w.dig(:time, :live_span)
@@ -71,10 +75,9 @@ module Kennel
71
75
  COPIED_WIDGET_VALUES.each { |v| w.delete v }
72
76
  end
73
77
 
74
- ignore_defaults as_json[:widgets], actual[:widgets], WIDGET_DEFAULTS
75
- ignore_request_defaults as_json, actual, :widgets, :tile_def
76
-
77
- super
78
+ ignore_default expected, actual, SCREEN_DEFAULTS
79
+ ignore_defaults expected[:widgets], actual[:widgets], WIDGET_DEFAULTS
80
+ ignore_request_defaults expected, actual, :widgets, :tile_def
78
81
  end
79
82
 
80
83
  def url(id)
@@ -98,7 +101,7 @@ module Kennel
98
101
  widgets.map do |widget|
99
102
  widget = widget_defaults(widget[:type]).merge(widget)
100
103
  if tile = widget[:tile_def]
101
- tile[:autoscale] = true unless widget[:tile_def].key?(:autoscale)
104
+ tile[:autoscale] = true unless widget[:tile_def].key?(:autoscale) # TODO: use ignore_default
102
105
  end
103
106
  widget
104
107
  end
@@ -7,7 +7,8 @@ module Kennel
7
7
  COLORS = {
8
8
  "Alert" => :red,
9
9
  "Warn" => :yellow,
10
- "No Data" => :cyan
10
+ "No Data" => :cyan,
11
+ "Ignored" => :magenta # resolved but still broken
11
12
  }.freeze
12
13
 
13
14
  class << self
data/lib/kennel/utils.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
3
  module Utils
4
- COLORS = { red: 31, green: 32, yellow: 33, cyan: 36, default: 0 }.freeze
4
+ COLORS = { red: 31, green: 32, yellow: 33, cyan: 36, magenta: 35, default: 0 }.freeze
5
5
 
6
6
  class TeeIO < IO
7
7
  def initialize(ios)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Kennel
3
- VERSION = "1.18.2"
3
+ VERSION = "1.19.0"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kennel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.18.2
4
+ version: 1.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-12 00:00:00.000000000 Z
11
+ date: 2018-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday