From df1b122b0849e515b53f0fbaf8c5ea9d75ba3039 Mon Sep 17 00:00:00 2001 From: Jason Field Date: Tue, 17 Oct 2023 11:54:14 +0800 Subject: [PATCH 1/2] feat(uneditable): Adds linting for editable dashboards Today this linter tests a number of settings, but it does not validate that the dashboard cannot be edited after it is deployed in the UI. If this linter is to ensure the source of truth for linted dashboards are a json code object, we should ensure they are not editable by default after deployment. Signed-off-by: Jason Field --- docs/rules/template-uneditable-rule.md | 3 ++ lint/rule_uneditable.go | 19 ++++++++ lint/rule_uneditable_test.go | 64 ++++++++++++++++++++++++++ lint/testdata/dashboard.json | 1 + 4 files changed, 87 insertions(+) create mode 100644 docs/rules/template-uneditable-rule.md create mode 100644 lint/rule_uneditable.go create mode 100644 lint/rule_uneditable_test.go diff --git a/docs/rules/template-uneditable-rule.md b/docs/rules/template-uneditable-rule.md new file mode 100644 index 0000000..ae84926 --- /dev/null +++ b/docs/rules/template-uneditable-rule.md @@ -0,0 +1,3 @@ +# template-uneditable-rule +Checks that dashboard is not able to be edited in the ui. This is due to the fact dashboards are declared as code +and therefore that code should be the accurate source of truth for the dashboard diff --git a/lint/rule_uneditable.go b/lint/rule_uneditable.go new file mode 100644 index 0000000..ac5f410 --- /dev/null +++ b/lint/rule_uneditable.go @@ -0,0 +1,19 @@ +package lint + +func NewUneditableRule() *DashboardRuleFunc { + return &DashboardRuleFunc{ + name: "uneditable-dashboard", + description: "Checks that the dashboard is not editable.", + fn: func(d Dashboard) DashboardRuleResults { + r := DashboardRuleResults{} + if d.Editable { + r.AddFixableError(d, "is editable, it should be set to 'editable: false'", FixUneditableRule) + } + return r + }, + } +} + +func FixUneditableRule(d *Dashboard) { + d.Editable = false +} diff --git a/lint/rule_uneditable_test.go b/lint/rule_uneditable_test.go new file mode 100644 index 0000000..18959e3 --- /dev/null +++ b/lint/rule_uneditable_test.go @@ -0,0 +1,64 @@ +package lint + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNewUneditableRule(t *testing.T) { + linter := NewUneditableRule() + + for _, tc := range []struct { + name string + result Result + dashboard Dashboard + fixed *Dashboard + }{ + { + name: "OK", + result: ResultSuccess, + dashboard: Dashboard{ + Title: "test", + Editable: false, + }, + }, + { + name: "error", + result: Result{ + Severity: Error, + Message: `Dashboard 'test' is editable, it should be set to 'editable: false'`, + }, + dashboard: Dashboard{ + Title: "test", + Editable: true, + }, + }, + { + name: "autofix", + result: Result{ + Severity: Fixed, + Message: `Dashboard 'test' is editable, it should be set to 'editable: false'`, + }, + dashboard: Dashboard{ + Title: "test", + Editable: true, + }, + fixed: &Dashboard{ + Title: "test", + Editable: false, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + autofix := tc.fixed != nil + testRuleWithAutofix(t, linter, &tc.dashboard, []Result{tc.result}, autofix) + if autofix { + expected, _ := json.Marshal(tc.fixed) + actual, _ := json.Marshal(tc.dashboard) + require.Equal(t, string(expected), string(actual)) + } + }) + } +} diff --git a/lint/testdata/dashboard.json b/lint/testdata/dashboard.json index 28bdc28..d89440a 100644 --- a/lint/testdata/dashboard.json +++ b/lint/testdata/dashboard.json @@ -1,4 +1,5 @@ { + "editable": true, "rows": [ { "panels": [ From 9dfd84395233e1744add1271aa22c34609012c57 Mon Sep 17 00:00:00 2001 From: Jason Field Date: Thu, 16 Nov 2023 12:50:01 +0800 Subject: [PATCH 2/2] fix(uneditable): Add rule to list & update struct Rule was missing from the `rules.go` which would mean this rule would not function as expected, this will resolve that error Additionally during development I missed committing the dashboard struct change so this brings that in as well Signed-off-by: Jason Field --- lint/lint.go | 5 +++-- lint/rules.go | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lint/lint.go b/lint/lint.go index c5fffce..88ff514 100644 --- a/lint/lint.go +++ b/lint/lint.go @@ -246,8 +246,9 @@ type Dashboard struct { Templating struct { List []Template `json:"list"` } `json:"templating"` - Rows []Row `json:"rows,omitempty"` - Panels []Panel `json:"panels,omitempty"` + Rows []Row `json:"rows,omitempty"` + Panels []Panel `json:"panels,omitempty"` + Editable bool `json:"editable,omitempty"` } // GetPanels returns the all panels whether they are nested in the (now deprecated) "rows" property or diff --git a/lint/rules.go b/lint/rules.go index cb031fc..0ffbe4b 100644 --- a/lint/rules.go +++ b/lint/rules.go @@ -186,6 +186,7 @@ func NewRuleSet() RuleSet { NewTargetJobRule(), NewTargetInstanceRule(), NewTargetCounterAggRule(), + NewUneditableRule(), }, } }