From 10e1eb03f03281ea5afffd189bb1f8cd0f3940e1 Mon Sep 17 00:00:00 2001 From: Karol Chrapek Date: Thu, 23 May 2024 08:44:16 +0200 Subject: [PATCH 1/5] Add support for time_slice slo --- lib/kennel/models/slo.rb | 6 ++++-- test/kennel/models/slo_test.rb | 37 +++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/kennel/models/slo.rb b/lib/kennel/models/slo.rb index 9f645989..f9902fdc 100644 --- a/lib/kennel/models/slo.rb +++ b/lib/kennel/models/slo.rb @@ -14,7 +14,7 @@ class Slo < Record thresholds: [] }.freeze - settings :type, :description, :thresholds, :query, :tags, :monitor_ids, :monitor_tags, :name, :groups + settings :type, :description, :thresholds, :query, :tags, :monitor_ids, :monitor_tags, :name, :groups, :sliSpecification defaults( tags: -> { @project.tags }, @@ -35,7 +35,9 @@ def build_json type: type ) - if v = query + if v = sliSpecification + data[:sliSpecification] = v + elsif v = query data[:query] = v end diff --git a/test/kennel/models/slo_test.rb b/test/kennel/models/slo_test.rb index f28f9586..d37c9313 100644 --- a/test/kennel/models/slo_test.rb +++ b/test/kennel/models/slo_test.rb @@ -11,12 +11,17 @@ class TestSlo < Kennel::Models::Slo def slo(options = {}) Kennel::Models::Slo.new( + # Determine the type from options or default to "metric" + type = options[:type] || "metric" options.delete(:project) || project, - { - type: -> { "metric" }, + slo_options ={ + type: -> { type }, name: -> { "Foo" }, kennel_id: -> { "m1" } - }.merge(options) + } + # Conditionally include sliSpecification if type is "time_slice" + slo_options[:sliSpecification] = -> { options[:sliSpecification] } if type == "time_slice" + Kennel::Models::Slo.new(project, slo_options.merge(options)) ) end @@ -59,6 +64,32 @@ def slo(options = {}) ) end + it "includes sliSpecification for time slices" do + sli_spec = { + timeSlice: { + query: { + formula: { + formulaExpression: "query1" + }, + queries: [{ + metricQuery: { + name: "query1", + query: "ewma_7(avg:system_cpu{} by {env})" + } + }] + }, + comparator: "<=", + threshold: 40 + } + } + + expected_basic_json[:sliSpecification] = sli_spec + assert_json_equal( + slo(type: "time_slice", sliSpecification: sli_spec).build_json, + expected_basic_json + ) + end + it "sets id when updating by id" do expected_basic_json[:id] = 123 assert_json_equal( From 2725886d9a389a5dbd80753e5045333db45e1642 Mon Sep 17 00:00:00 2001 From: Karol Chrapek Date: Thu, 23 May 2024 10:46:58 +0200 Subject: [PATCH 2/5] Add SLO type verification --- lib/kennel/models/slo.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/kennel/models/slo.rb b/lib/kennel/models/slo.rb index f9902fdc..c6aabe33 100644 --- a/lib/kennel/models/slo.rb +++ b/lib/kennel/models/slo.rb @@ -35,7 +35,7 @@ def build_json type: type ) - if v = sliSpecification + if type == 'time_slice' && v = sliSpecification data[:sliSpecification] = v elsif v = query data[:query] = v From 24f007d6409239fe8965c9e4a91009edde0e0b0f Mon Sep 17 00:00:00 2001 From: Karol Chrapek Date: Thu, 23 May 2024 13:32:44 +0200 Subject: [PATCH 3/5] Correct naming and remove spare comment --- lib/kennel/models/slo.rb | 6 +++--- test/kennel/models/slo_test.rb | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/kennel/models/slo.rb b/lib/kennel/models/slo.rb index c6aabe33..cf27aee3 100644 --- a/lib/kennel/models/slo.rb +++ b/lib/kennel/models/slo.rb @@ -14,7 +14,7 @@ class Slo < Record thresholds: [] }.freeze - settings :type, :description, :thresholds, :query, :tags, :monitor_ids, :monitor_tags, :name, :groups, :sliSpecification + settings :type, :description, :thresholds, :query, :tags, :monitor_ids, :monitor_tags, :name, :groups, :sli_specification defaults( tags: -> { @project.tags }, @@ -35,8 +35,8 @@ def build_json type: type ) - if type == 'time_slice' && v = sliSpecification - data[:sliSpecification] = v + if type == 'time_slice' + data[:sliSpecification] = :sli_specification elsif v = query data[:query] = v end diff --git a/test/kennel/models/slo_test.rb b/test/kennel/models/slo_test.rb index d37c9313..1292da49 100644 --- a/test/kennel/models/slo_test.rb +++ b/test/kennel/models/slo_test.rb @@ -11,7 +11,6 @@ class TestSlo < Kennel::Models::Slo def slo(options = {}) Kennel::Models::Slo.new( - # Determine the type from options or default to "metric" type = options[:type] || "metric" options.delete(:project) || project, slo_options ={ @@ -19,7 +18,6 @@ def slo(options = {}) name: -> { "Foo" }, kennel_id: -> { "m1" } } - # Conditionally include sliSpecification if type is "time_slice" slo_options[:sliSpecification] = -> { options[:sliSpecification] } if type == "time_slice" Kennel::Models::Slo.new(project, slo_options.merge(options)) ) @@ -85,7 +83,7 @@ def slo(options = {}) expected_basic_json[:sliSpecification] = sli_spec assert_json_equal( - slo(type: "time_slice", sliSpecification: sli_spec).build_json, + slo(type: "time_slice", sli_specification: sli_spec).build_json, expected_basic_json ) end From 3a00b85b1e288423574e410b13b118405a5da9a3 Mon Sep 17 00:00:00 2001 From: Karol Chrapek Date: Fri, 24 May 2024 15:59:51 +0200 Subject: [PATCH 4/5] Update importer to support sli_specification --- lib/kennel/importer.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/kennel/importer.rb b/lib/kennel/importer.rb index ff7d63ac..8cf55aa2 100644 --- a/lib/kennel/importer.rb +++ b/lib/kennel/importer.rb @@ -3,7 +3,7 @@ module Kennel class Importer TITLES = [:name, :title].freeze - SORT_ORDER = [*TITLES, :id, :kennel_id, :type, :tags, :query, *Models::Record.subclasses.map { |k| k::TRACKING_FIELDS }, :template_variables].freeze + SORT_ORDER = [*TITLES, :id, :kennel_id, :type, :tags, :query, :sli_specification, *Models::Record.subclasses.map { |k| k::TRACKING_FIELDS }, :template_variables].freeze def initialize(api) @api = api @@ -19,10 +19,15 @@ def import(resource, id) raise(ArgumentError, "#{resource} is not supported") data = @api.show(model.api_resource, id) + # get sli specification before normalization. + sli_specification = data[:sli_specification] || data.dig(:sli_specification, :time_slice) + id = data.fetch(:id) # keep native value model.normalize({}, data) # removes id data[:id] = id + data[:sli_specification] = sli_specification if sli_specification + title_field = TITLES.detect { |f| data[f] } title = data.fetch(title_field) title.tr!(Kennel::Models::Record::LOCK, "") # avoid double lock icon From a8f7c5a312088570e0eff81dd378d0f15ea698b8 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 25 May 2024 07:34:54 +0200 Subject: [PATCH 5/5] fixes --- lib/kennel/importer.rb | 13 +++++--- lib/kennel/models/slo.rb | 9 +++-- test/kennel/models/slo_test.rb | 61 +++++++++++++++++----------------- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/lib/kennel/importer.rb b/lib/kennel/importer.rb index 8cf55aa2..73545468 100644 --- a/lib/kennel/importer.rb +++ b/lib/kennel/importer.rb @@ -2,8 +2,15 @@ module Kennel class Importer + # title will have the lock symbol we need to remove when re-importing TITLES = [:name, :title].freeze - SORT_ORDER = [*TITLES, :id, :kennel_id, :type, :tags, :query, :sli_specification, *Models::Record.subclasses.map { |k| k::TRACKING_FIELDS }, :template_variables].freeze + + # bring important fields to the top + SORT_ORDER = [ + *TITLES, :id, :kennel_id, :type, :tags, :query, :sli_specification, + *Models::Record.subclasses.flat_map { |k| k::TRACKING_FIELDS }, + :template_variables + ].freeze def initialize(api) @api = api @@ -19,15 +26,11 @@ def import(resource, id) raise(ArgumentError, "#{resource} is not supported") data = @api.show(model.api_resource, id) - # get sli specification before normalization. - sli_specification = data[:sli_specification] || data.dig(:sli_specification, :time_slice) id = data.fetch(:id) # keep native value model.normalize({}, data) # removes id data[:id] = id - data[:sli_specification] = sli_specification if sli_specification - title_field = TITLES.detect { |f| data[f] } title = data.fetch(title_field) title.tr!(Kennel::Models::Record::LOCK, "") # avoid double lock icon diff --git a/lib/kennel/models/slo.rb b/lib/kennel/models/slo.rb index cf27aee3..ae0a2797 100644 --- a/lib/kennel/models/slo.rb +++ b/lib/kennel/models/slo.rb @@ -4,7 +4,10 @@ module Models class Slo < Record include TagsValidation - READONLY_ATTRIBUTES = superclass::READONLY_ATTRIBUTES + [:type_id, :monitor_tags, :target_threshold, :timeframe, :warning_threshold] + READONLY_ATTRIBUTES = [ + *superclass::READONLY_ATTRIBUTES, + :type_id, :monitor_tags, :target_threshold, :timeframe, :warning_threshold + ].freeze TRACKING_FIELD = :description DEFAULTS = { description: nil, @@ -35,8 +38,8 @@ def build_json type: type ) - if type == 'time_slice' - data[:sliSpecification] = :sli_specification + if type == "time_slice" + data[:sli_specification] = sli_specification elsif v = query data[:query] = v end diff --git a/test/kennel/models/slo_test.rb b/test/kennel/models/slo_test.rb index 1292da49..17c93909 100644 --- a/test/kennel/models/slo_test.rb +++ b/test/kennel/models/slo_test.rb @@ -11,15 +11,12 @@ class TestSlo < Kennel::Models::Slo def slo(options = {}) Kennel::Models::Slo.new( - type = options[:type] || "metric" options.delete(:project) || project, - slo_options ={ - type: -> { type }, + { + type: -> { "metric" }, name: -> { "Foo" }, kennel_id: -> { "m1" } - } - slo_options[:sliSpecification] = -> { options[:sliSpecification] } if type == "time_slice" - Kennel::Models::Slo.new(project, slo_options.merge(options)) + }.merge(options) ) end @@ -62,47 +59,49 @@ def slo(options = {}) ) end + it "sets id when updating by id" do + expected_basic_json[:id] = 123 + assert_json_equal( + slo(id: -> { 123 }).build_json, + expected_basic_json + ) + end + + it "sets groups when given" do + expected_basic_json[:groups] = ["foo"] + assert_json_equal( + slo(groups: -> { ["foo"] }).build_json, + expected_basic_json + ) + end + it "includes sliSpecification for time slices" do sli_spec = { - timeSlice: { + time_slice: { query: { - formula: { - formulaExpression: "query1" - }, - queries: [{ - metricQuery: { + formulas: [{ formula: "query1" }], + queries: [ + { + data_source: "metrics", name: "query1", query: "ewma_7(avg:system_cpu{} by {env})" } - }] + ] }, + query_interval_seconds: 300, comparator: "<=", - threshold: 40 + threshold: 0.1, + no_data_strategy: "COUNT_AS_UPTIME" } } - expected_basic_json[:sliSpecification] = sli_spec + expected_basic_json[:sli_specification] = sli_spec + expected_basic_json[:type] = "time_slice" assert_json_equal( slo(type: "time_slice", sli_specification: sli_spec).build_json, expected_basic_json ) end - - it "sets id when updating by id" do - expected_basic_json[:id] = 123 - assert_json_equal( - slo(id: -> { 123 }).build_json, - expected_basic_json - ) - end - - it "sets groups when given" do - expected_basic_json[:groups] = ["foo"] - assert_json_equal( - slo(groups: -> { ["foo"] }).build_json, - expected_basic_json - ) - end end describe "#resolve_linked_tracking_ids!" do