@intentius/chant-lexicon-grafana 0.97.0 → 0.99.0
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.
- package/README.md +15 -5
- package/dist/actions/grafana.d.ts +24 -0
- package/dist/actions/grafana.d.ts.map +1 -0
- package/dist/actions/index.d.ts +2 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/alerting-build.d.ts +128 -0
- package/dist/alerting-build.d.ts.map +1 -0
- package/dist/alerting.d.ts +273 -0
- package/dist/alerting.d.ts.map +1 -0
- package/dist/api/apply.d.ts +156 -0
- package/dist/api/apply.d.ts.map +1 -0
- package/dist/api/bind.d.ts +32 -0
- package/dist/api/bind.d.ts.map +1 -0
- package/dist/api/client.d.ts +76 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/converge.d.ts +33 -0
- package/dist/api/converge.d.ts.map +1 -0
- package/dist/api/dashboards.d.ts +102 -0
- package/dist/api/dashboards.d.ts.map +1 -0
- package/dist/api/datasources.d.ts +26 -0
- package/dist/api/datasources.d.ts.map +1 -0
- package/dist/api/fake-grafana-writes.d.ts +41 -0
- package/dist/api/fake-grafana-writes.d.ts.map +1 -0
- package/dist/api/fake-grafana.d.ts +61 -0
- package/dist/api/fake-grafana.d.ts.map +1 -0
- package/dist/api/folders.d.ts +110 -0
- package/dist/api/folders.d.ts.map +1 -0
- package/dist/api/library-panels.d.ts +52 -0
- package/dist/api/library-panels.d.ts.map +1 -0
- package/dist/build.d.ts +30 -2
- package/dist/build.d.ts.map +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/codegen/schema-types.d.ts +3 -3
- package/dist/codegen/schema-types.d.ts.map +1 -1
- package/dist/composites/agent-dashboard.d.ts.map +1 -1
- package/dist/composites/catalog.d.ts.map +1 -1
- package/dist/composites/index.d.ts +4 -2
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/red-dashboard.d.ts +21 -2
- package/dist/composites/red-dashboard.d.ts.map +1 -1
- package/dist/composites/shared.d.ts +7 -0
- package/dist/composites/shared.d.ts.map +1 -1
- package/dist/composites/slo-alert-rules.d.ts +92 -0
- package/dist/composites/slo-alert-rules.d.ts.map +1 -0
- package/dist/config.d.ts +111 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/contact-point-secrets.d.ts +17 -0
- package/dist/contact-point-secrets.d.ts.map +1 -0
- package/dist/dashboard.d.ts +16 -2
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/datasource-refs.d.ts +95 -0
- package/dist/datasource-refs.d.ts.map +1 -0
- package/dist/datasource.d.ts +29 -0
- package/dist/datasource.d.ts.map +1 -1
- package/dist/deep-observe-hooks.d.ts +64 -0
- package/dist/deep-observe-hooks.d.ts.map +1 -0
- package/dist/deep-observe.d.ts +42 -0
- package/dist/deep-observe.d.ts.map +1 -0
- package/dist/describe-resources.d.ts +49 -0
- package/dist/describe-resources.d.ts.map +1 -0
- package/dist/detect.d.ts +28 -1
- package/dist/detect.d.ts.map +1 -1
- package/dist/export-resources.d.ts +38 -0
- package/dist/export-resources.d.ts.map +1 -0
- package/dist/import/alerting.d.ts +40 -0
- package/dist/import/alerting.d.ts.map +1 -0
- package/dist/import/edits.d.ts +47 -0
- package/dist/import/edits.d.ts.map +1 -0
- package/dist/import/embedded.d.ts +14 -0
- package/dist/import/embedded.d.ts.map +1 -0
- package/dist/import/generator.d.ts +60 -0
- package/dist/import/generator.d.ts.map +1 -0
- package/dist/import/live-export.d.ts +108 -0
- package/dist/import/live-export.d.ts.map +1 -0
- package/dist/import/mappings.d.ts +83 -0
- package/dist/import/mappings.d.ts.map +1 -0
- package/dist/import/model.d.ts +98 -0
- package/dist/import/model.d.ts.map +1 -0
- package/dist/import/normalize-alerting.d.ts +26 -0
- package/dist/import/normalize-alerting.d.ts.map +1 -0
- package/dist/import/normalize.d.ts +74 -0
- package/dist/import/normalize.d.ts.map +1 -0
- package/dist/import/parser.d.ts +110 -0
- package/dist/import/parser.d.ts.map +1 -0
- package/dist/import/report.d.ts +26 -0
- package/dist/import/report.d.ts.map +1 -0
- package/dist/import/testdata/fixtures.d.ts +35 -0
- package/dist/import/testdata/fixtures.d.ts.map +1 -0
- package/dist/import/v2.d.ts +72 -0
- package/dist/import/v2.d.ts.map +1 -0
- package/dist/index.d.ts +26 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +18 -10
- package/dist/k8s.d.ts +107 -0
- package/dist/k8s.d.ts.map +1 -0
- package/dist/lint/audit-catalog.d.ts +2 -1
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/graf101.d.ts +2 -2
- package/dist/lint/post-synth/graf102.d.ts +1 -1
- package/dist/lint/post-synth/graf107.d.ts +1 -1
- package/dist/lint/post-synth/graf108.d.ts +8 -0
- package/dist/lint/post-synth/graf108.d.ts.map +1 -0
- package/dist/lint/post-synth/graf109.d.ts +8 -0
- package/dist/lint/post-synth/graf109.d.ts.map +1 -0
- package/dist/lint/post-synth/graf111.d.ts +8 -0
- package/dist/lint/post-synth/graf111.d.ts.map +1 -0
- package/dist/lint/post-synth/graf112.d.ts +8 -0
- package/dist/lint/post-synth/graf112.d.ts.map +1 -0
- package/dist/lint/post-synth/graf113.d.ts +8 -0
- package/dist/lint/post-synth/graf113.d.ts.map +1 -0
- package/dist/lint/post-synth/graf114.d.ts +8 -0
- package/dist/lint/post-synth/graf114.d.ts.map +1 -0
- package/dist/lint/post-synth/graf115.d.ts +8 -0
- package/dist/lint/post-synth/graf115.d.ts.map +1 -0
- package/dist/lint/post-synth/grafana-helpers.d.ts +7 -5
- package/dist/lint/post-synth/grafana-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/rules/literal-secret.d.ts +7 -3
- package/dist/lint/rules/literal-secret.d.ts.map +1 -1
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/members.d.ts +27 -0
- package/dist/members.d.ts.map +1 -0
- package/dist/meta.json +135 -0
- package/dist/okf/index.md +36 -2
- package/dist/okf/rules/GRAF002.md +3 -2
- package/dist/okf/rules/GRAF101.md +3 -2
- package/dist/okf/rules/GRAF102.md +1 -0
- package/dist/okf/rules/GRAF108.md +11 -0
- package/dist/okf/rules/GRAF109.md +15 -0
- package/dist/okf/rules/GRAF111.md +11 -0
- package/dist/okf/rules/GRAF112.md +16 -0
- package/dist/okf/rules/GRAF113.md +16 -0
- package/dist/okf/rules/GRAF114.md +11 -0
- package/dist/okf/rules/GRAF115.md +11 -0
- package/dist/okf/types/AlertListPanel.md +9 -0
- package/dist/okf/types/AlertQuery.md +9 -0
- package/dist/okf/types/AlertRule.md +9 -0
- package/dist/okf/types/AlertRuleGroup.md +9 -0
- package/dist/okf/types/BarChartPanel.md +9 -0
- package/dist/okf/types/BarGaugePanel.md +9 -0
- package/dist/okf/types/CanvasPanel.md +9 -0
- package/dist/okf/types/ClassicConditionsExpression.md +9 -0
- package/dist/okf/types/ContactPoint.md +14 -0
- package/dist/okf/types/Dashboard.md +1 -0
- package/dist/okf/types/Datasource.md +3 -2
- package/dist/okf/types/ExternalDatasource.md +15 -0
- package/dist/okf/types/FlameGraphPanel.md +9 -0
- package/dist/okf/types/GeomapPanel.md +9 -0
- package/dist/okf/types/HistogramPanel.md +9 -0
- package/dist/okf/types/MathExpression.md +9 -0
- package/dist/okf/types/MuteTiming.md +13 -0
- package/dist/okf/types/NodeGraphPanel.md +9 -0
- package/dist/okf/types/NotificationPolicy.md +9 -0
- package/dist/okf/types/NotificationTemplate.md +9 -0
- package/dist/okf/types/PieChartPanel.md +9 -0
- package/dist/okf/types/ReduceExpression.md +9 -0
- package/dist/okf/types/ResampleExpression.md +9 -0
- package/dist/okf/types/SqlExpression.md +9 -0
- package/dist/okf/types/StateTimelinePanel.md +9 -0
- package/dist/okf/types/StatusHistoryPanel.md +9 -0
- package/dist/okf/types/ThresholdExpression.md +9 -0
- package/dist/okf/types/TrendPanel.md +9 -0
- package/dist/okf/types/XYChartPanel.md +9 -0
- package/dist/op/activities/grafana-apply.d.ts +75 -0
- package/dist/op/activities/grafana-apply.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +9 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/builders.d.ts +24 -0
- package/dist/op/builders.d.ts.map +1 -0
- package/dist/ownership.d.ts +67 -0
- package/dist/ownership.d.ts.map +1 -0
- package/dist/panel-options.d.ts +65 -0
- package/dist/panel-options.d.ts.map +1 -0
- package/dist/panels.d.ts +46 -9
- package/dist/panels.d.ts.map +1 -1
- package/dist/pin.d.ts +29 -7
- package/dist/pin.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/promql-check.d.ts +51 -0
- package/dist/promql-check.d.ts.map +1 -0
- package/dist/query.d.ts +9 -8
- package/dist/query.d.ts.map +1 -1
- package/dist/rules/graf101.ts +3 -3
- package/dist/rules/graf102.ts +1 -1
- package/dist/rules/graf107.ts +1 -1
- package/dist/rules/graf108.ts +17 -0
- package/dist/rules/graf109.ts +17 -0
- package/dist/rules/graf111.ts +17 -0
- package/dist/rules/graf112.ts +17 -0
- package/dist/rules/graf113.ts +17 -0
- package/dist/rules/graf114.ts +17 -0
- package/dist/rules/graf115.ts +17 -0
- package/dist/rules/grafana-helpers.ts +15 -8
- package/dist/rules/literal-secret.ts +60 -6
- package/dist/schema/barchart.gen.d.ts +198 -0
- package/dist/schema/barchart.gen.d.ts.map +1 -0
- package/dist/schema/bargauge.gen.d.ts +97 -0
- package/dist/schema/bargauge.gen.d.ts.map +1 -0
- package/dist/schema/canvas.gen.d.ts +152 -0
- package/dist/schema/canvas.gen.d.ts.map +1 -0
- package/dist/schema/dashboard.gen.d.ts +196 -21
- package/dist/schema/dashboard.gen.d.ts.map +1 -1
- package/dist/schema/expr.gen.d.ts +606 -0
- package/dist/schema/expr.gen.d.ts.map +1 -0
- package/dist/schema/gauge.gen.d.ts.map +1 -1
- package/dist/schema/geomap.gen.d.ts +100 -0
- package/dist/schema/geomap.gen.d.ts.map +1 -0
- package/dist/schema/heatmap.gen.d.ts.map +1 -1
- package/dist/schema/histogram.gen.d.ts +132 -0
- package/dist/schema/histogram.gen.d.ts.map +1 -0
- package/dist/schema/index.d.ts +12 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/logs.gen.d.ts +1 -0
- package/dist/schema/logs.gen.d.ts.map +1 -1
- package/dist/schema/loki.gen.d.ts.map +1 -1
- package/dist/schema/nodegraph.gen.d.ts +49 -0
- package/dist/schema/nodegraph.gen.d.ts.map +1 -0
- package/dist/schema/piechart.gen.d.ts +127 -0
- package/dist/schema/piechart.gen.d.ts.map +1 -0
- package/dist/schema/prometheus.gen.d.ts.map +1 -1
- package/dist/schema/stat.gen.d.ts.map +1 -1
- package/dist/schema/statetimeline.gen.d.ts +124 -0
- package/dist/schema/statetimeline.gen.d.ts.map +1 -0
- package/dist/schema/statushistory.gen.d.ts +114 -0
- package/dist/schema/statushistory.gen.d.ts.map +1 -0
- package/dist/schema/table.gen.d.ts +22 -3
- package/dist/schema/table.gen.d.ts.map +1 -1
- package/dist/schema/tempo.gen.d.ts.map +1 -1
- package/dist/schema/text.gen.d.ts.map +1 -1
- package/dist/schema/timeseries.gen.d.ts +5 -1
- package/dist/schema/timeseries.gen.d.ts.map +1 -1
- package/dist/schema/trend.gen.d.ts +180 -0
- package/dist/schema/trend.gen.d.ts.map +1 -0
- package/dist/schema/xychart.gen.d.ts +145 -0
- package/dist/schema/xychart.gen.d.ts.map +1 -0
- package/dist/schema-validate.d.ts +30 -4
- package/dist/schema-validate.d.ts.map +1 -1
- package/dist/serializer.d.ts +11 -3
- package/dist/serializer.d.ts.map +1 -1
- package/dist/skill-defs.d.ts.map +1 -1
- package/dist/skills/chant-grafana-alerting.md +49 -0
- package/dist/skills/chant-grafana-provisioning.md +3 -3
- package/dist/skills/chant-grafana.md +12 -6
- package/dist/spec/fetch-units-cli.d.ts +3 -0
- package/dist/spec/fetch-units-cli.d.ts.map +1 -0
- package/dist/spec/overlay.d.ts +43 -0
- package/dist/spec/overlay.d.ts.map +1 -0
- package/dist/spec/schemas.d.ts +13 -7
- package/dist/spec/schemas.d.ts.map +1 -1
- package/dist/spec/units.d.ts +35 -0
- package/dist/spec/units.d.ts.map +1 -0
- package/dist/spec/units.gen.d.ts +2 -0
- package/dist/spec/units.gen.d.ts.map +1 -0
- package/dist/transformations.d.ts +459 -0
- package/dist/transformations.d.ts.map +1 -0
- package/dist/util.d.ts +6 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/validate-alerting.d.ts +65 -0
- package/dist/validate-alerting.d.ts.map +1 -0
- package/dist/validate-output.d.ts +49 -9
- package/dist/validate-output.d.ts.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/variables.d.ts +7 -2
- package/dist/variables.d.ts.map +1 -1
- package/package.json +12 -4
- package/src/actions/actions.test.ts +24 -0
- package/src/actions/grafana.ts +40 -0
- package/src/actions/index.ts +1 -0
- package/src/alerting-build.ts +376 -0
- package/src/alerting.e2e.test.ts +212 -0
- package/src/alerting.test.ts +272 -0
- package/src/alerting.ts +435 -0
- package/src/api/apply.test.ts +238 -0
- package/src/api/apply.ts +384 -0
- package/src/api/bind.ts +58 -0
- package/src/api/client.ts +148 -0
- package/src/api/converge.ts +63 -0
- package/src/api/dashboards.ts +247 -0
- package/src/api/datasources.ts +33 -0
- package/src/api/fake-grafana-writes.ts +201 -0
- package/src/api/fake-grafana.ts +186 -0
- package/src/api/folders.ts +265 -0
- package/src/api/library-panels.ts +101 -0
- package/src/build.test.ts +210 -5
- package/src/build.ts +180 -43
- package/src/catalog.ts +86 -2
- package/src/codegen/docs.ts +42 -9
- package/src/codegen/schema-types.ts +16 -6
- package/src/composites/agent-dashboard.ts +6 -3
- package/src/composites/catalog.test.ts +2 -2
- package/src/composites/catalog.ts +82 -0
- package/src/composites/composites.test.ts +73 -9
- package/src/composites/index.ts +4 -2
- package/src/composites/queries.e2e.test.ts +374 -0
- package/src/composites/red-dashboard.ts +83 -12
- package/src/composites/shared.ts +11 -0
- package/src/composites/slo-alert-rules.ts +149 -0
- package/src/config.test.ts +61 -0
- package/src/config.ts +138 -0
- package/src/contact-point-secrets.ts +63 -0
- package/src/dashboard.ts +16 -2
- package/src/datasource-refs.test.ts +56 -0
- package/src/datasource-refs.ts +189 -0
- package/src/datasource.ts +52 -0
- package/src/deep-observe-hooks.ts +252 -0
- package/src/deep-observe.test.ts +265 -0
- package/src/deep-observe.ts +164 -0
- package/src/describe-resources.test.ts +255 -0
- package/src/describe-resources.ts +209 -0
- package/src/detect.ts +79 -2
- package/src/export-resources.test.ts +129 -0
- package/src/export-resources.ts +84 -0
- package/src/generated/lexicon-grafana.json +135 -0
- package/src/import/alerting-roundtrip.test.ts +161 -0
- package/src/import/alerting.ts +500 -0
- package/src/import/edits.ts +95 -0
- package/src/import/embedded.test.ts +45 -0
- package/src/import/embedded.ts +47 -0
- package/src/import/generated-types.e2e.test.ts +118 -0
- package/src/import/generator.test.ts +210 -0
- package/src/import/generator.ts +462 -0
- package/src/import/live-export.ts +264 -0
- package/src/import/mappings.ts +264 -0
- package/src/import/model.ts +110 -0
- package/src/import/normalize-alerting.ts +101 -0
- package/src/import/normalize.test.ts +117 -0
- package/src/import/normalize.ts +364 -0
- package/src/import/parser.test.ts +440 -0
- package/src/import/parser.ts +1236 -0
- package/src/import/report.ts +62 -0
- package/src/import/roundtrip.test.ts +468 -0
- package/src/import/testdata/fixtures.ts +129 -0
- package/src/import/v2.test.ts +292 -0
- package/src/import/v2.ts +803 -0
- package/src/import.e2e.test.ts +31 -84
- package/src/import.test.ts +9 -3
- package/src/index.ts +190 -5
- package/src/k8s.test.ts +98 -0
- package/src/k8s.ts +197 -0
- package/src/lint/audit-catalog.ts +60 -3
- package/src/lint/core-lint.test.ts +43 -0
- package/src/lint/post-synth/graf101.ts +3 -3
- package/src/lint/post-synth/graf102.ts +1 -1
- package/src/lint/post-synth/graf107.ts +1 -1
- package/src/lint/post-synth/graf108.ts +17 -0
- package/src/lint/post-synth/graf109.ts +17 -0
- package/src/lint/post-synth/graf111.ts +17 -0
- package/src/lint/post-synth/graf112.ts +17 -0
- package/src/lint/post-synth/graf113.ts +17 -0
- package/src/lint/post-synth/graf114.ts +17 -0
- package/src/lint/post-synth/graf115.ts +17 -0
- package/src/lint/post-synth/grafana-helpers.ts +15 -8
- package/src/lint/post-synth/index.ts +14 -0
- package/src/lint/post-synth/post-synth.test.ts +235 -11
- package/src/lint/rules/literal-secret.ts +60 -6
- package/src/lint/rules/rules.test.ts +27 -0
- package/src/lsp/completions.test.ts +5 -0
- package/src/lsp/hover.test.ts +7 -0
- package/src/lsp/hover.ts +8 -1
- package/src/members.ts +68 -0
- package/src/observe.e2e.test.ts +255 -0
- package/src/op/activities/grafana-apply.e2e.test.ts +175 -0
- package/src/op/activities/grafana-apply.test.ts +229 -0
- package/src/op/activities/grafana-apply.ts +171 -0
- package/src/op/activities/index.ts +8 -0
- package/src/op/builders.test.ts +40 -0
- package/src/op/builders.ts +34 -0
- package/src/ownership.ts +103 -0
- package/src/panel-options.ts +66 -0
- package/src/panels.test.ts +51 -0
- package/src/panels.ts +148 -10
- package/src/pin.ts +57 -6
- package/src/plugin.test.ts +5 -2
- package/src/plugin.ts +66 -0
- package/src/promql-check.test.ts +108 -0
- package/src/promql-check.ts +189 -0
- package/src/query.ts +13 -8
- package/src/schema/barchart.gen.ts +221 -0
- package/src/schema/bargauge.gen.ts +111 -0
- package/src/schema/canvas.gen.ts +176 -0
- package/src/schema/dashboard.gen.ts +206 -22
- package/src/schema/expr.gen.ts +618 -0
- package/src/schema/gauge.gen.ts +2 -1
- package/src/schema/geomap.gen.ts +112 -0
- package/src/schema/heatmap.gen.ts +2 -1
- package/src/schema/histogram.gen.ts +151 -0
- package/src/schema/index.ts +12 -0
- package/src/schema/logs.gen.ts +3 -1
- package/src/schema/loki.gen.ts +2 -1
- package/src/schema/nodegraph.gen.ts +58 -0
- package/src/schema/piechart.gen.ts +146 -0
- package/src/schema/prometheus.gen.ts +2 -1
- package/src/schema/stat.gen.ts +2 -1
- package/src/schema/statetimeline.gen.ts +143 -0
- package/src/schema/statushistory.gen.ts +132 -0
- package/src/schema/table.gen.ts +27 -4
- package/src/schema/tempo.gen.ts +2 -1
- package/src/schema/text.gen.ts +2 -1
- package/src/schema/timeseries.gen.ts +7 -2
- package/src/schema/trend.gen.ts +208 -0
- package/src/schema/xychart.gen.ts +167 -0
- package/src/schema-overlay.test.ts +282 -0
- package/src/schema-validate.ts +141 -50
- package/src/schema.test.ts +4 -2
- package/src/serializer.test.ts +13 -1
- package/src/serializer.ts +11 -3
- package/src/skill-defs.ts +17 -0
- package/src/skills/chant-grafana-alerting.md +49 -0
- package/src/skills/chant-grafana-provisioning.md +3 -3
- package/src/skills/chant-grafana.md +12 -6
- package/src/spec/fetch-cli.ts +3 -3
- package/src/spec/fetch-units-cli.ts +37 -0
- package/src/spec/overlay/canvas.overlay.json +142 -0
- package/src/spec/overlay/dashboard.overlay.json +378 -0
- package/src/spec/overlay/expr.overlay.json +14 -0
- package/src/spec/overlay/geomap.overlay.json +35 -0
- package/src/spec/overlay/logs.overlay.json +14 -0
- package/src/spec/overlay/nodegraph.overlay.json +31 -0
- package/src/spec/overlay/piechart.overlay.json +17 -0
- package/src/spec/overlay/table.overlay.json +84 -0
- package/src/spec/overlay/timeseries.overlay.json +21 -0
- package/src/spec/overlay/trend.overlay.json +17 -0
- package/src/spec/overlay/xychart.overlay.json +16 -0
- package/src/spec/overlay.ts +105 -0
- package/src/spec/schemas/barchart.jsonschema.json +419 -0
- package/src/spec/schemas/bargauge.jsonschema.json +224 -0
- package/src/spec/schemas/canvas.jsonschema.json +356 -0
- package/src/spec/schemas/dashboardv2.jsonschema.json +3387 -0
- package/src/spec/schemas/expr.jsonschema.json +987 -0
- package/src/spec/schemas/geomap.jsonschema.json +220 -0
- package/src/spec/schemas/histogram.jsonschema.json +308 -0
- package/src/spec/schemas/nodegraph.jsonschema.json +77 -0
- package/src/spec/schemas/piechart.jsonschema.json +275 -0
- package/src/spec/schemas/statetimeline.jsonschema.json +324 -0
- package/src/spec/schemas/statushistory.jsonschema.json +292 -0
- package/src/spec/schemas/trend.jsonschema.json +449 -0
- package/src/spec/schemas/xychart.jsonschema.json +428 -0
- package/src/spec/schemas.ts +22 -10
- package/src/spec/units.gen.ts +281 -0
- package/src/spec/units.ts +77 -0
- package/src/transformations.test.ts +65 -0
- package/src/transformations.ts +574 -0
- package/src/util.ts +8 -0
- package/src/validate-alerting.test.ts +255 -0
- package/src/validate-alerting.ts +428 -0
- package/src/validate-output.ts +332 -101
- package/src/validate.ts +14 -0
- package/src/variables.ts +7 -2
package/src/import.e2e.test.ts
CHANGED
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* "A dashboard builds to JSON that Grafana imports without edits", against
|
|
3
|
-
* Grafana itself.
|
|
3
|
+
* Grafana itself, on every release in `GRAFANA_IMAGES` (12.4 and 13.2).
|
|
4
4
|
*
|
|
5
5
|
* Builds each example (getting-started, and dashboards-from-declarations,
|
|
6
6
|
* whose dashboards the RED, SLO and agent composites build), mounts its
|
|
7
7
|
* provisioning files and dashboards into a pinned `grafana/grafana`
|
|
8
|
-
* container, and asserts that
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* import uses, under
|
|
8
|
+
* container, and asserts that Grafana provisioned every datasource and
|
|
9
|
+
* dashboard, and that each stored dashboard model is the built JSON, key
|
|
10
|
+
* for key, once the keys Grafana adds (`GRAFANA_INJECTED`: `id` and
|
|
11
|
+
* `version`) are taken out. It then imports the same JSON a second time
|
|
12
|
+
* through `POST /api/dashboards/db`, the path the UI's import uses, under
|
|
13
|
+
* another uid, and compares that stored model the same way.
|
|
13
14
|
*
|
|
14
15
|
* Skipped, with the reason in the test name, when Docker is not running.
|
|
15
|
-
* On demand: `npx vitest run --project e2e lexicons/grafana`.
|
|
16
|
+
* On demand: `npx vitest run --project e2e lexicons/grafana/src/import.e2e.test.ts`.
|
|
16
17
|
*/
|
|
17
|
-
import {
|
|
18
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
19
|
-
import { tmpdir } from "node:os";
|
|
18
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
20
19
|
import { dirname, join } from "node:path";
|
|
21
|
-
import { fileURLToPath } from "node:url";
|
|
22
20
|
import { afterAll, describe, expect, it } from "vitest";
|
|
23
21
|
import { build } from "@intentius/chant/build";
|
|
24
22
|
import type { SerializerResult } from "@intentius/chant/serializer";
|
|
@@ -26,23 +24,12 @@ import type { Serializer } from "@intentius/chant/serializer";
|
|
|
26
24
|
import { otelSerializer } from "@intentius/chant-lexicon-otel/serializer";
|
|
27
25
|
import { prometheusSerializer } from "@intentius/chant-lexicon-prometheus/serializer";
|
|
28
26
|
import { grafanaSerializer } from "./serializer";
|
|
27
|
+
import { DockerScope, GRAFANA_IMAGES, dockerAvailable, waitFor } from "../test/e2e/containers";
|
|
28
|
+
import { withoutInjected } from "../test/e2e/stored-model";
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
export const GRAFANA_IMAGE = process.env.CHANT_GRAFANA_IMAGE ?? "grafana/grafana:12.4.11";
|
|
32
|
-
|
|
33
|
-
function available(cmd: string): boolean {
|
|
34
|
-
try {
|
|
35
|
-
execSync(cmd, { stdio: "ignore" });
|
|
36
|
-
return true;
|
|
37
|
-
} catch {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const hasDocker = available("docker info");
|
|
30
|
+
const hasDocker = dockerAvailable();
|
|
43
31
|
const skipReason = hasDocker ? "" : "Docker is not running";
|
|
44
|
-
const
|
|
45
|
-
const examples = join(dirname(dirname(fileURLToPath(import.meta.url))), "examples");
|
|
32
|
+
const examples = join(import.meta.dirname, "..", "examples");
|
|
46
33
|
|
|
47
34
|
/** Each example, and the serializers its build root needs. */
|
|
48
35
|
const EXAMPLES: Array<{ name: string; serializers: Serializer[] }> = [
|
|
@@ -50,98 +37,58 @@ const EXAMPLES: Array<{ name: string; serializers: Serializer[] }> = [
|
|
|
50
37
|
{ name: "dashboards-from-declarations", serializers: [otelSerializer, prometheusSerializer, grafanaSerializer] },
|
|
51
38
|
];
|
|
52
39
|
|
|
53
|
-
|
|
54
|
-
const deadline = Date.now() + timeoutMs;
|
|
55
|
-
let last: unknown;
|
|
56
|
-
while (Date.now() < deadline) {
|
|
57
|
-
try {
|
|
58
|
-
const v = await fn();
|
|
59
|
-
if (v !== undefined) return v;
|
|
60
|
-
} catch (err) {
|
|
61
|
-
last = err;
|
|
62
|
-
}
|
|
63
|
-
await new Promise((r) => setTimeout(r, 1000));
|
|
64
|
-
}
|
|
65
|
-
throw new Error(`timed out waiting for ${what}${last ? `: ${String(last)}` : ""}`);
|
|
66
|
-
}
|
|
40
|
+
const MATRIX = GRAFANA_IMAGES.flatMap((image) => EXAMPLES.map((e) => ({ ...e, image })));
|
|
67
41
|
|
|
68
|
-
describe.skipIf(!hasDocker).each(
|
|
69
|
-
const
|
|
70
|
-
const dir = mkdtempSync(join(tmpdir(), "chant-grafana-import-"));
|
|
42
|
+
describe.skipIf(!hasDocker).each(MATRIX)(`$image imports the $name dashboards without edits${skipReason ? ` (skipped: ${skipReason})` : ""}`, ({ name, serializers, image }) => {
|
|
43
|
+
const scope = new DockerScope(`grafana-import-${name}`);
|
|
71
44
|
|
|
72
|
-
afterAll(() =>
|
|
73
|
-
try {
|
|
74
|
-
execSync(`docker rm -f ${CONTAINER}`, { stdio: "ignore" });
|
|
75
|
-
} catch {
|
|
76
|
-
// already gone
|
|
77
|
-
}
|
|
78
|
-
rmSync(dir, { recursive: true, force: true });
|
|
79
|
-
});
|
|
45
|
+
afterAll(() => scope.cleanup());
|
|
80
46
|
|
|
81
|
-
it("provisions every datasource and dashboard, and accepts the JSON through the import API", { timeout: 300_000 }, async () => {
|
|
47
|
+
it("provisions every datasource and dashboard as built, and accepts the JSON through the import API", { timeout: 300_000 }, async () => {
|
|
82
48
|
const result = await build(join(examples, name, "src"), serializers);
|
|
83
49
|
expect(result.errors).toEqual([]);
|
|
84
50
|
const out = result.outputs.get("grafana") as SerializerResult;
|
|
51
|
+
const dir = scope.tempDir();
|
|
85
52
|
for (const [file, content] of Object.entries(out.files ?? {})) {
|
|
86
53
|
mkdirSync(dirname(join(dir, file)), { recursive: true });
|
|
87
54
|
writeFileSync(join(dir, file), content);
|
|
88
55
|
}
|
|
89
56
|
const index = JSON.parse(out.primary) as { dashboards: Array<{ uid: string; title: string; folder?: string; file: string }>; datasources: Array<{ uid: string; type: string; name: string }> };
|
|
90
57
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"docker run -d",
|
|
94
|
-
`--name ${CONTAINER}`,
|
|
95
|
-
"-p 127.0.0.1::3000",
|
|
96
|
-
"-e GF_SECURITY_ADMIN_PASSWORD=admin",
|
|
97
|
-
"-e GF_ANALYTICS_REPORTING_ENABLED=false",
|
|
98
|
-
"-e GF_ANALYTICS_CHECK_FOR_UPDATES=false",
|
|
99
|
-
`-v ${join(dir, "provisioning")}:/etc/grafana/provisioning:ro`,
|
|
100
|
-
`-v ${join(dir, "dashboards")}:/var/lib/grafana/dashboards:ro`,
|
|
101
|
-
GRAFANA_IMAGE,
|
|
102
|
-
].join(" "),
|
|
103
|
-
{ stdio: "ignore" },
|
|
104
|
-
);
|
|
105
|
-
const port = execSync(`docker port ${CONTAINER} 3000/tcp`).toString().trim().split("\n")[0].split(":").pop();
|
|
106
|
-
const base = `http://127.0.0.1:${port}`;
|
|
107
|
-
const api = async (path: string, init?: RequestInit) => {
|
|
108
|
-
const res = await fetch(`${base}${path}`, { ...init, headers: { authorization: AUTH, "content-type": "application/json", ...(init?.headers ?? {}) } });
|
|
109
|
-
return { status: res.status, body: (await res.json()) as Record<string, unknown> & unknown[] };
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
await waitFor("Grafana to answer", async () => ((await fetch(`${base}/api/health`)).ok ? true : undefined));
|
|
58
|
+
const grafana = await scope.grafana({ image, provisioningDir: join(dir, "provisioning"), dashboardsDir: join(dir, "dashboards") });
|
|
59
|
+
const { api } = grafana;
|
|
113
60
|
|
|
114
61
|
// Datasources: every declared one, with the uid and type chant gave it.
|
|
115
62
|
const datasources = await waitFor("datasources", async () => {
|
|
116
63
|
const { status, body } = await api("/api/datasources");
|
|
117
|
-
return status === 200 && (body as unknown[]).length >= index.datasources.length ? (body as
|
|
64
|
+
return status === 200 && (body as unknown[]).length >= index.datasources.length ? (body as Array<{ uid: string; type: string; name: string }>) : undefined;
|
|
118
65
|
});
|
|
119
66
|
expect(datasources.map((d) => [d.uid, d.type, d.name]).sort()).toEqual(index.datasources.map((d) => [d.uid, d.type, d.name]).sort());
|
|
120
67
|
|
|
121
|
-
// Dashboards: provisioned, in their folder,
|
|
68
|
+
// Dashboards: provisioned, in their folder, and stored exactly as built.
|
|
122
69
|
for (const d of index.dashboards) {
|
|
123
70
|
const { body } = await waitFor(`dashboard ${d.uid}`, async () => {
|
|
124
71
|
const r = await api(`/api/dashboards/uid/${d.uid}`);
|
|
125
72
|
return r.status === 200 ? r : undefined;
|
|
126
73
|
});
|
|
127
74
|
const meta = body.meta as { provisioned: boolean; folderTitle?: string };
|
|
128
|
-
const stored = body.dashboard as
|
|
129
|
-
const built = JSON.parse(out.files![d.file]) as
|
|
75
|
+
const stored = body.dashboard as Record<string, unknown>;
|
|
76
|
+
const built = JSON.parse(out.files![d.file]) as Record<string, unknown>;
|
|
130
77
|
expect(meta.provisioned).toBe(true);
|
|
131
78
|
if (d.folder) expect(meta.folderTitle).toBe(d.folder);
|
|
132
|
-
expect(stored.
|
|
133
|
-
|
|
134
|
-
expect(
|
|
135
|
-
expect(stored.templating.list.length).toBe(built.templating.list.length);
|
|
79
|
+
expect(typeof stored.id, `${d.uid}: Grafana assigns the id`).toBe("number");
|
|
80
|
+
expect(stored.version, `${d.uid}: Grafana's first version`).toBe(1);
|
|
81
|
+
expect(withoutInjected(stored), `${image} stored ${d.uid} differently from the build`).toStrictEqual(built);
|
|
136
82
|
}
|
|
137
83
|
|
|
138
84
|
// The same JSON through the import API, under a new uid.
|
|
139
85
|
const first = index.dashboards[0];
|
|
140
|
-
const copy = { ...JSON.parse(out.files![first.file]), uid: `${first.uid}-api`, title: `${first.title} (API import)` };
|
|
86
|
+
const copy = { ...(JSON.parse(out.files![first.file]) as Record<string, unknown>), uid: `${first.uid}-api`, title: `${first.title} (API import)` };
|
|
141
87
|
const imported = await api("/api/dashboards/db", { method: "POST", body: JSON.stringify({ dashboard: copy, overwrite: false }) });
|
|
142
88
|
expect(imported.status).toBe(200);
|
|
143
89
|
expect(imported.body.status).toBe("success");
|
|
144
90
|
const back = await api(`/api/dashboards/uid/${first.uid}-api`);
|
|
145
|
-
expect(
|
|
91
|
+
expect(back.status).toBe(200);
|
|
92
|
+
expect(withoutInjected(back.body.dashboard as Record<string, unknown>), `${image} stored the API import differently from the JSON sent`).toStrictEqual(copy);
|
|
146
93
|
});
|
|
147
94
|
});
|
package/src/import.test.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Builds every example and validates each dashboard against Grafana's
|
|
5
5
|
* dashboard schema at `GRAFANA_SCHEMA_PIN`, each panel's options and each
|
|
6
|
-
* query against their plugin's schema, and runs
|
|
6
|
+
* query against their plugin's schema, and runs the GRAF1xx checks over the
|
|
7
7
|
* output. `import.e2e.test.ts` does the same against a real Grafana when
|
|
8
8
|
* Docker is available.
|
|
9
9
|
*/
|
|
@@ -18,6 +18,7 @@ import { grafanaSerializer } from "./serializer";
|
|
|
18
18
|
import { validateDashboardSchema } from "./schema-validate";
|
|
19
19
|
import { validateGrafanaOutput } from "./validate-output";
|
|
20
20
|
import type { ProvisionedDatasource } from "./build";
|
|
21
|
+
import { ALERTING_FILE } from "./alerting-build";
|
|
21
22
|
|
|
22
23
|
const examplesDir = join(dirname(dirname(fileURLToPath(import.meta.url))), "examples");
|
|
23
24
|
const examples = readdirSync(examplesDir).filter((e) => {
|
|
@@ -34,12 +35,17 @@ describe.each(examples)("example %s", (example) => {
|
|
|
34
35
|
expect(result.errors).toEqual([]);
|
|
35
36
|
const out = result.outputs.get("grafana") as SerializerResult;
|
|
36
37
|
const dashboards = Object.entries(out.files ?? {}).filter(([f]) => f.startsWith("dashboards/"));
|
|
37
|
-
|
|
38
|
+
const alerting = out.files?.[ALERTING_FILE];
|
|
39
|
+
expect(dashboards.length + (alerting ? 1 : 0)).toBeGreaterThan(0);
|
|
38
40
|
for (const [file, text] of dashboards) {
|
|
39
41
|
expect({ file, problems: validateDashboardSchema(JSON.parse(text)) }).toEqual({ file, problems: [] });
|
|
40
42
|
}
|
|
41
43
|
const ds = load(out.files?.["provisioning/datasources/chant.yaml"] ?? "datasources: []") as { datasources: ProvisionedDatasource[] };
|
|
42
|
-
const issues = validateGrafanaOutput({
|
|
44
|
+
const issues = validateGrafanaOutput({
|
|
45
|
+
dashboards: dashboards.map(([source, t]) => ({ source, json: JSON.parse(t) })),
|
|
46
|
+
datasources: ds.datasources,
|
|
47
|
+
alerting: alerting ? [{ source: ALERTING_FILE, json: load(alerting) as Record<string, unknown> }] : [],
|
|
48
|
+
});
|
|
43
49
|
expect(issues).toEqual([]);
|
|
44
50
|
});
|
|
45
51
|
});
|
package/src/index.ts
CHANGED
|
@@ -8,8 +8,15 @@ export { grafanaSerializer } from "./serializer";
|
|
|
8
8
|
export {
|
|
9
9
|
Datasource,
|
|
10
10
|
DATASOURCE_TYPE,
|
|
11
|
+
ExternalDatasource,
|
|
12
|
+
EXTERNAL_DATASOURCE_TYPE,
|
|
11
13
|
BUILTIN_DATASOURCE_UIDS,
|
|
12
14
|
isDatasourceEntity,
|
|
15
|
+
isExternalDatasource,
|
|
16
|
+
isDatasourceDeclaration,
|
|
17
|
+
type ExternalDatasourceProps,
|
|
18
|
+
type ExternalDatasourceEntity,
|
|
19
|
+
type ExternalDatasourceConstructor,
|
|
13
20
|
type DatasourceProps,
|
|
14
21
|
type DatasourceEntity,
|
|
15
22
|
type DatasourceConstructor,
|
|
@@ -34,6 +41,98 @@ export {
|
|
|
34
41
|
type DashboardProviderEntity,
|
|
35
42
|
} from "./dashboard";
|
|
36
43
|
|
|
44
|
+
// Grafana-managed alerting
|
|
45
|
+
export {
|
|
46
|
+
AlertRuleGroup,
|
|
47
|
+
AlertRule,
|
|
48
|
+
AlertQuery,
|
|
49
|
+
ReduceExpression,
|
|
50
|
+
MathExpression,
|
|
51
|
+
ThresholdExpression,
|
|
52
|
+
ResampleExpression,
|
|
53
|
+
ClassicConditionsExpression,
|
|
54
|
+
SqlExpression,
|
|
55
|
+
ContactPoint,
|
|
56
|
+
NotificationPolicy,
|
|
57
|
+
MuteTiming,
|
|
58
|
+
NotificationTemplate,
|
|
59
|
+
ALERT_RULE_GROUP_TYPE,
|
|
60
|
+
ALERT_RULE_TYPE,
|
|
61
|
+
ALERT_QUERY_TYPE,
|
|
62
|
+
EXPRESSION_TYPE_PREFIX,
|
|
63
|
+
EXPRESSION_DATASOURCE_UID,
|
|
64
|
+
CONTACT_POINT_TYPE,
|
|
65
|
+
NOTIFICATION_POLICY_TYPE,
|
|
66
|
+
MUTE_TIMING_TYPE,
|
|
67
|
+
NOTIFICATION_TEMPLATE_TYPE,
|
|
68
|
+
isAlertRuleGroupEntity,
|
|
69
|
+
isAlertRuleEntity,
|
|
70
|
+
isAlertQueryEntity,
|
|
71
|
+
isExpressionEntity,
|
|
72
|
+
isContactPointEntity,
|
|
73
|
+
isNotificationPolicyEntity,
|
|
74
|
+
isMuteTimingEntity,
|
|
75
|
+
isNotificationTemplateEntity,
|
|
76
|
+
type AlertRuleGroupProps,
|
|
77
|
+
type AlertRuleGroupEntity,
|
|
78
|
+
type AlertRuleProps,
|
|
79
|
+
type AlertRuleEntity,
|
|
80
|
+
type AlertRuleData,
|
|
81
|
+
type AlertRuleNotificationSettings,
|
|
82
|
+
type AlertRuleRecord,
|
|
83
|
+
type AlertQueryProps,
|
|
84
|
+
type AlertQueryEntity,
|
|
85
|
+
type AlertDuration,
|
|
86
|
+
type RelativeTimeRange,
|
|
87
|
+
type ExpressionEntity,
|
|
88
|
+
type ExpressionKind,
|
|
89
|
+
type ReduceExpressionProps,
|
|
90
|
+
type MathExpressionProps,
|
|
91
|
+
type ThresholdExpressionProps,
|
|
92
|
+
type ResampleExpressionProps,
|
|
93
|
+
type ClassicConditionsExpressionProps,
|
|
94
|
+
type SqlExpressionProps,
|
|
95
|
+
type NoDataState,
|
|
96
|
+
type ExecErrState,
|
|
97
|
+
type ContactPointProps,
|
|
98
|
+
type ContactPointEntity,
|
|
99
|
+
type ContactPointReceiver,
|
|
100
|
+
type ContactPointIntegrationType,
|
|
101
|
+
type NotificationPolicyProps,
|
|
102
|
+
type NotificationPolicyEntity,
|
|
103
|
+
type PolicyRoute,
|
|
104
|
+
type ObjectMatcher,
|
|
105
|
+
type MuteTimingProps,
|
|
106
|
+
type MuteTimingEntity,
|
|
107
|
+
type NotificationTemplateProps,
|
|
108
|
+
type NotificationTemplateEntity,
|
|
109
|
+
} from "./alerting";
|
|
110
|
+
export {
|
|
111
|
+
buildAlerting,
|
|
112
|
+
alertingYaml,
|
|
113
|
+
alertRuleJson,
|
|
114
|
+
alertQueryJson,
|
|
115
|
+
ruleGroupJson,
|
|
116
|
+
contactPointJson,
|
|
117
|
+
notificationPolicyJson,
|
|
118
|
+
muteTimingJson,
|
|
119
|
+
notificationTemplateJson,
|
|
120
|
+
durationSeconds,
|
|
121
|
+
ALERTING_FILE,
|
|
122
|
+
ALERTING_FILE_KEYS,
|
|
123
|
+
DEFAULT_RELATIVE_TIME_RANGE,
|
|
124
|
+
DEFAULT_GROUP_INTERVAL,
|
|
125
|
+
type AlertingFile,
|
|
126
|
+
type AlertingIndex,
|
|
127
|
+
type ProvisionedRuleGroup,
|
|
128
|
+
type ProvisionedAlertRule,
|
|
129
|
+
type ProvisionedAlertQuery,
|
|
130
|
+
type ProvisionedContactPoint,
|
|
131
|
+
type ProvisionedMuteTiming,
|
|
132
|
+
type ProvisionedTemplate,
|
|
133
|
+
} from "./alerting-build";
|
|
134
|
+
export { CONTACT_POINT_SECRET_SETTINGS } from "./contact-point-secrets";
|
|
135
|
+
|
|
37
136
|
// Panels and rows, and the extension point for other panel plugins
|
|
38
137
|
export {
|
|
39
138
|
TimeSeriesPanel,
|
|
@@ -44,6 +143,19 @@ export {
|
|
|
44
143
|
TracesPanel,
|
|
45
144
|
HeatmapPanel,
|
|
46
145
|
TextPanel,
|
|
146
|
+
BarChartPanel,
|
|
147
|
+
BarGaugePanel,
|
|
148
|
+
PieChartPanel,
|
|
149
|
+
StateTimelinePanel,
|
|
150
|
+
StatusHistoryPanel,
|
|
151
|
+
HistogramPanel,
|
|
152
|
+
NodeGraphPanel,
|
|
153
|
+
XYChartPanel,
|
|
154
|
+
TrendPanel,
|
|
155
|
+
CanvasPanel,
|
|
156
|
+
GeomapPanel,
|
|
157
|
+
FlameGraphPanel,
|
|
158
|
+
AlertListPanel,
|
|
47
159
|
Row,
|
|
48
160
|
definePanel,
|
|
49
161
|
registeredPanels,
|
|
@@ -112,7 +224,32 @@ export {
|
|
|
112
224
|
// The generated schema types and their pin
|
|
113
225
|
export * as schema from "./schema";
|
|
114
226
|
export { DASHBOARD_SCHEMA_VERSION } from "./schema";
|
|
115
|
-
export {
|
|
227
|
+
export {
|
|
228
|
+
GRAFANA_SCHEMA_PIN,
|
|
229
|
+
SCHEMA_NAMES,
|
|
230
|
+
IMPORT_ONLY_SCHEMA_NAMES,
|
|
231
|
+
VENDORED_SCHEMA_NAMES,
|
|
232
|
+
type GrafanaSchemaPin,
|
|
233
|
+
type SchemaName,
|
|
234
|
+
type ImportOnlySchemaName,
|
|
235
|
+
type VendoredSchemaName,
|
|
236
|
+
} from "./pin";
|
|
237
|
+
// Hand-written options for the built-in panels with no schema
|
|
238
|
+
export type { AlertListOptions, AlertListSortOrder, AlertListStateFilter, FlameGraphOptions } from "./panel-options";
|
|
239
|
+
|
|
240
|
+
// Panel transformations, typed per transformer (Grafana v13.2.2)
|
|
241
|
+
export {
|
|
242
|
+
transformation,
|
|
243
|
+
customTransformation,
|
|
244
|
+
TRANSFORMATION_IDS,
|
|
245
|
+
type Transformation,
|
|
246
|
+
type KnownTransformation,
|
|
247
|
+
type CustomTransformation,
|
|
248
|
+
type TransformationCommon,
|
|
249
|
+
type TransformationId,
|
|
250
|
+
type TransformationOptionsById,
|
|
251
|
+
type ReducerId,
|
|
252
|
+
} from "./transformations";
|
|
116
253
|
|
|
117
254
|
// Plain-data API: render, check and detect without a build
|
|
118
255
|
export {
|
|
@@ -124,8 +261,10 @@ export {
|
|
|
124
261
|
panelsJson,
|
|
125
262
|
targetJson,
|
|
126
263
|
variableModel,
|
|
264
|
+
customVariableOptions,
|
|
127
265
|
datasourceRef,
|
|
128
266
|
provisionedDatasource,
|
|
267
|
+
externalDatasourceRecord,
|
|
129
268
|
provisionedProvider,
|
|
130
269
|
datasourcesYaml,
|
|
131
270
|
dashboardProvidersYaml,
|
|
@@ -137,6 +276,7 @@ export {
|
|
|
137
276
|
type BuiltDashboard,
|
|
138
277
|
type GrafanaIndex,
|
|
139
278
|
type ProvisionedDatasource,
|
|
279
|
+
type ExternalDatasourceRecord,
|
|
140
280
|
type ProvisionedProvider,
|
|
141
281
|
type DashboardJson,
|
|
142
282
|
type PanelJson,
|
|
@@ -147,20 +287,31 @@ export {
|
|
|
147
287
|
export {
|
|
148
288
|
validateGrafanaOutput,
|
|
149
289
|
issuesFor,
|
|
290
|
+
knownDatasourcesOf,
|
|
150
291
|
variableReferences,
|
|
151
292
|
type GrafanaIssue,
|
|
152
293
|
type GrafanaIssueCode,
|
|
153
294
|
type GrafanaArtifacts,
|
|
154
295
|
type DashboardDoc,
|
|
155
296
|
} from "./validate-output";
|
|
156
|
-
export {
|
|
157
|
-
|
|
158
|
-
|
|
297
|
+
export {
|
|
298
|
+
datasourceUses,
|
|
299
|
+
resolveDatasourceRef,
|
|
300
|
+
knownDatasources,
|
|
301
|
+
type DatasourceUse,
|
|
302
|
+
type ResolvedDatasource,
|
|
303
|
+
type KnownDatasource,
|
|
304
|
+
type DatasourceRefJson,
|
|
305
|
+
} from "./datasource-refs";
|
|
306
|
+
export { validateDashboardSchema, validateExpressionSchema, type SchemaProblem } from "./schema-validate";
|
|
307
|
+
export { looksLikeDashboard, looksLikeDatasourceProvisioning, looksLikeDashboardProvisioning, looksLikeAlertingProvisioning } from "./detect";
|
|
308
|
+
export { slugUid, isValidUid, UID_PATTERN, type DeepPartial, type PropsOf } from "./util";
|
|
159
309
|
|
|
160
|
-
// Composites: dashboards built from a spanmetrics connector, an Slo and the GenAI preset
|
|
310
|
+
// Composites: dashboards built from a spanmetrics connector, an Slo and the GenAI preset, and an Slo's burn-rate alerts as Grafana rules
|
|
161
311
|
export {
|
|
162
312
|
RedDashboard,
|
|
163
313
|
redQueries,
|
|
314
|
+
RED_DEFAULT_SPAN_KINDS,
|
|
164
315
|
SloDashboard,
|
|
165
316
|
sloQueries,
|
|
166
317
|
AgentDashboard,
|
|
@@ -168,6 +319,7 @@ export {
|
|
|
168
319
|
type RedDashboardProps,
|
|
169
320
|
type RedDashboardMembers,
|
|
170
321
|
type RedDashboardInstance,
|
|
322
|
+
type SpanKind,
|
|
171
323
|
type SloDashboardProps,
|
|
172
324
|
type SloDashboardMembers,
|
|
173
325
|
type SloDashboardInstance,
|
|
@@ -175,4 +327,37 @@ export {
|
|
|
175
327
|
type AgentDashboardMembers,
|
|
176
328
|
type AgentDashboardInstance,
|
|
177
329
|
type DashboardOptions,
|
|
330
|
+
SloAlertRules,
|
|
331
|
+
sloAlertQueries,
|
|
332
|
+
type SloAlertRulesProps,
|
|
333
|
+
type SloAlertRulesMembers,
|
|
334
|
+
type SloAlertRulesInstance,
|
|
178
335
|
} from "./composites";
|
|
336
|
+
|
|
337
|
+
// Config namespace (#2946): `grafana.profiles.<env>` in chant.config.ts, the
|
|
338
|
+
// Grafana each environment is observed in and exported from.
|
|
339
|
+
export { grafanaConfigSchema, resolveGrafanaTarget } from "./config";
|
|
340
|
+
export type { GrafanaConfig, GrafanaProfile } from "./config";
|
|
341
|
+
|
|
342
|
+
// Ownership (#2946): chant's marker on a dashboard.grafana.app resource.
|
|
343
|
+
export {
|
|
344
|
+
GRAFANA_OWNERSHIP_KEYS,
|
|
345
|
+
DEFAULT_PROVIDER_NAME,
|
|
346
|
+
grafanaOwnershipLabels,
|
|
347
|
+
dashboardOwnership,
|
|
348
|
+
} from "./ownership";
|
|
349
|
+
|
|
350
|
+
// The HTTP client observe and export share, for the API applier (#2948).
|
|
351
|
+
export { GrafanaClient, GrafanaApiError, grafanaHttp, namespaceOf, statusVerdict } from "./api/client";
|
|
352
|
+
export type { GrafanaAuth, GrafanaHttp, GrafanaResponse, GrafanaTarget, StatusVerdict } from "./api/client";
|
|
353
|
+
export { bindGrafana, classifyGrafanaFailure, GrafanaBindingError } from "./api/bind";
|
|
354
|
+
|
|
355
|
+
// The API applier (#2948): the typed Op step, and the pieces an embedding
|
|
356
|
+
// caller composes (the activity itself is `./op/activities`).
|
|
357
|
+
export { grafanaApply } from "./op/builders";
|
|
358
|
+
export { applyGrafana, planFromDashboards, GRAFANA_APPLY_KINDS } from "./api/apply";
|
|
359
|
+
export type { GrafanaApplyPlan, GrafanaApplyOutcome, DashboardPlan, BuiltDashboardInput } from "./api/apply";
|
|
360
|
+
export { folderUidFor, foldersForDashboards, type FolderPlan } from "./api/folders";
|
|
361
|
+
|
|
362
|
+
// The Grafana RBAC actions a service account needs to observe, apply and prune.
|
|
363
|
+
export { GrafanaActions, grafanaActionsFor, type GrafanaAccessLevel } from "./actions/index";
|
package/src/k8s.test.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { expandComposite } from "@intentius/chant/composite";
|
|
3
|
+
import { k8sSerializer } from "@intentius/chant-lexicon-k8s";
|
|
4
|
+
import { loadAll } from "js-yaml";
|
|
5
|
+
import { Dashboard } from "./dashboard";
|
|
6
|
+
import { Datasource } from "./datasource";
|
|
7
|
+
import { StatPanel } from "./panels";
|
|
8
|
+
import { PromQuery } from "./query";
|
|
9
|
+
import { dashboardJson } from "./build";
|
|
10
|
+
import { GrafanaConfigMaps, grafanaConfigMapLayout, grafanaVolumes } from "./k8s";
|
|
11
|
+
|
|
12
|
+
const prometheus = new Datasource({ name: "Prometheus", type: "prometheus", url: "http://prometheus:9090" });
|
|
13
|
+
const stat = () => new StatPanel({ title: "Up", datasource: prometheus, targets: [new PromQuery({ expr: "sum(up)" })] });
|
|
14
|
+
const top = new Dashboard({ title: "Top", uid: "Top_Level", panels: [stat()] });
|
|
15
|
+
const red = new Dashboard({ title: "RED", uid: "red", folder: "Services", panels: [stat()] });
|
|
16
|
+
const slo = new Dashboard({ title: "SLO", uid: "slo", folder: "Services", panels: [stat()] });
|
|
17
|
+
const entities = [prometheus, top, red, slo];
|
|
18
|
+
|
|
19
|
+
type Manifest = { kind: string; metadata: { name: string; namespace?: string; labels?: Record<string, string>; annotations?: Record<string, string> }; data: Record<string, string> };
|
|
20
|
+
|
|
21
|
+
function manifests(instance: ReturnType<typeof GrafanaConfigMaps>): Manifest[] {
|
|
22
|
+
const out = k8sSerializer.serialize(expandComposite("grafana", instance));
|
|
23
|
+
return (loadAll(typeof out === "string" ? out : out.primary) as Manifest[]).filter(Boolean);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("GrafanaConfigMaps", () => {
|
|
27
|
+
test("one ConfigMap per dashboard, labelled for the sidecar, holding dashboardJson(dashboard)", () => {
|
|
28
|
+
const docs = manifests(GrafanaConfigMaps({ entities, namespace: "obs", labels: { team: "sre" } }));
|
|
29
|
+
expect(docs.map((d) => d.metadata.name)).toEqual([
|
|
30
|
+
"grafana-dashboard-top-level",
|
|
31
|
+
"grafana-dashboard-red",
|
|
32
|
+
"grafana-dashboard-slo",
|
|
33
|
+
"grafana-datasources",
|
|
34
|
+
"grafana-dashboard-providers",
|
|
35
|
+
]);
|
|
36
|
+
const [topCm, redCm] = docs;
|
|
37
|
+
expect(topCm.metadata).toEqual({ name: "grafana-dashboard-top-level", namespace: "obs", labels: { team: "sre", grafana_dashboard: "1" } });
|
|
38
|
+
expect(topCm.data).toEqual({ "Top_Level.json": dashboardJson(top) });
|
|
39
|
+
expect(redCm.metadata.annotations).toEqual({ "k8s-sidecar-target-directory": "Services" });
|
|
40
|
+
expect(docs[3].metadata.labels).toEqual({ team: "sre", grafana_datasource: "1" });
|
|
41
|
+
expect(Object.keys(docs[3].data)).toEqual(["chant.yaml"]);
|
|
42
|
+
expect(docs[3].data["chant.yaml"]).toContain("url: http://prometheus:9090");
|
|
43
|
+
expect(docs[4].metadata.labels).toEqual({ team: "sre" });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("labels and the folder annotation can be changed or left off", () => {
|
|
47
|
+
const docs = manifests(GrafanaConfigMaps({ entities: [red], name: "Obs", dashboardLabel: ["dashboards", "obs"], folderAnnotation: false }));
|
|
48
|
+
expect(docs[0].metadata).toEqual({ name: "obs-dashboard-red", labels: { dashboards: "obs" } });
|
|
49
|
+
const bare = manifests(GrafanaConfigMaps({ entities: [prometheus], datasourceLabel: false }));
|
|
50
|
+
expect(bare.map((d) => [d.metadata.name, d.metadata.labels])).toEqual([["grafana-datasources", {}]]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("names stay unique and DNS-1123 when uids collide after lower-casing", () => {
|
|
54
|
+
const a = new Dashboard({ title: "A", uid: "Same" });
|
|
55
|
+
const b = new Dashboard({ title: "B", uid: "same" });
|
|
56
|
+
expect(grafanaConfigMapLayout({ entities: [a, b] }).dashboards.map((d) => d.configMap)).toEqual(["grafana-dashboard-same", "grafana-dashboard-same-2"]);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe("grafanaVolumes", () => {
|
|
61
|
+
test("provisioning under /etc/grafana/provisioning, each dashboard folder a projected volume of its own", () => {
|
|
62
|
+
const { volumes, volumeMounts } = grafanaVolumes({ entities });
|
|
63
|
+
expect(volumeMounts).toEqual([
|
|
64
|
+
{ name: "grafana-provisioning", mountPath: "/etc/grafana/provisioning", readOnly: true },
|
|
65
|
+
{ name: "grafana-dashboards-0", mountPath: "/var/lib/grafana/dashboards", readOnly: true },
|
|
66
|
+
{ name: "grafana-dashboards-1", mountPath: "/var/lib/grafana/dashboards/Services", readOnly: true },
|
|
67
|
+
]);
|
|
68
|
+
expect(volumes).toEqual([
|
|
69
|
+
{
|
|
70
|
+
name: "grafana-provisioning",
|
|
71
|
+
projected: {
|
|
72
|
+
sources: [
|
|
73
|
+
{ configMap: { name: "grafana-datasources", items: [{ key: "chant.yaml", path: "datasources/chant.yaml" }] } },
|
|
74
|
+
{ configMap: { name: "grafana-dashboard-providers", items: [{ key: "chant.yaml", path: "dashboards/chant.yaml" }] } },
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{ name: "grafana-dashboards-0", projected: { sources: [{ configMap: { name: "grafana-dashboard-top-level", items: [{ key: "Top_Level.json", path: "Top_Level.json" }] } }] } },
|
|
79
|
+
{
|
|
80
|
+
name: "grafana-dashboards-1",
|
|
81
|
+
projected: {
|
|
82
|
+
sources: [
|
|
83
|
+
{ configMap: { name: "grafana-dashboard-red", items: [{ key: "red.json", path: "red.json" }] } },
|
|
84
|
+
{ configMap: { name: "grafana-dashboard-slo", items: [{ key: "slo.json", path: "slo.json" }] } },
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("a different dashboards path or volume name", () => {
|
|
92
|
+
const { volumeMounts } = grafanaVolumes({ entities: [red] }, { dashboardsPath: "/dash/", volumeName: "g" });
|
|
93
|
+
expect(volumeMounts.map((m) => [m.name, m.mountPath])).toEqual([
|
|
94
|
+
["g-provisioning", "/etc/grafana/provisioning"],
|
|
95
|
+
["g-dashboards-0", "/dash/Services"],
|
|
96
|
+
]);
|
|
97
|
+
});
|
|
98
|
+
});
|