├── .github ├── CODEOWNERS ├── dependabot.yml ├── workflows │ ├── release.yml │ └── test.yml └── CODE_OF_CONDUCT.md ├── .gitmodules ├── terraform-registry-manifest.json ├── gen ├── README.md ├── internal │ ├── tmpl │ │ └── gen_header.tmpl │ ├── tmpl.go │ ├── jenny_major.go │ ├── all.go │ └── jenny_eachmajorcomposable.go ├── terraform │ ├── terraform.go │ ├── cuetf │ │ ├── templates │ │ │ ├── schema_attribute.tmpl │ │ │ └── datasource.tmpl │ │ ├── types │ │ │ ├── mappings.go │ │ │ ├── node.go │ │ │ └── model.go │ │ ├── internal │ │ │ ├── utils │ │ │ │ └── utils.go │ │ │ └── nodes.go │ │ ├── tmpl.go │ │ └── datasource_generator.go │ ├── jenny_datasource.go │ └── jenny_datasource_registry.go └── gen.go ├── tools └── tools.go ├── CODEOWNERS ├── GNUmakefile ├── catalog-info.yaml ├── .golangci.yml ├── .gitignore ├── .vscode └── launch.json ├── CHANGELOG.md ├── internal └── provider │ ├── provider_test.go │ ├── registry_gen.go │ ├── provider.go │ ├── datasource_query_parca_gen.go │ ├── datasource_query_grafana_pyroscope_gen.go │ ├── datasource_query_loki_gen.go │ └── datasource_query_prometheus_gen.go ├── docs ├── data-sources │ ├── query_parca.md │ ├── query_grafana_pyroscope.md │ ├── query_loki.md │ ├── query_prometheus.md │ ├── query_test_data.md │ ├── core_dashboard.md │ ├── panel_alert_groups.md │ ├── panel_annotations_list.md │ └── panel_text.md └── index.md ├── examples └── schemas_core_dashboard │ ├── simple │ └── dashboard.tf │ └── prometheus │ └── dashboard.tf ├── main.go ├── .goreleaser.yml ├── templates └── index.md.tmpl ├── README.md ├── go.mod └── LICENSE /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @grafana/grafana-as-code 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tools/grok"] 2 | path = tools/grok 3 | url = https://github.com/grafana/grok 4 | -------------------------------------------------------------------------------- /terraform-registry-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "metadata": { 4 | "protocol_versions": ["6.0"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /gen/README.md: -------------------------------------------------------------------------------- 1 | This code should end in Grok and Thema but will stay here to ease the development workflow as this is still in an experimental state. -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | 3 | package tools 4 | 5 | import ( 6 | // Documentation generation 7 | _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs" 8 | ) 9 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Docs on CODEOWNERS: 2 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 3 | # 4 | # Later codeowner matches take precedence over earlier ones. 5 | 6 | # Default owner 7 | * @grafana/platform-cat 8 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | default: testacc 2 | 3 | # Run acceptance tests 4 | .PHONY: testacc 5 | testacc: 6 | TF_ACC=1 go test ./... -v $(TESTARGS) -timeout 120m 7 | 8 | .PHONY: generate 9 | generate: 10 | rm -rf ./internal/provider/*_gen.go 11 | cd ./gen && MIN_MATURITY=merged go generate ./ 12 | go generate ./ 13 | -------------------------------------------------------------------------------- /gen/internal/tmpl/gen_header.tmpl: -------------------------------------------------------------------------------- 1 | // Code generated - EDITING IS FUTILE. DO NOT EDIT. 2 | // 3 | // Generated by pipeline: 4 | // {{ .MainGenerator }} 5 | // Using jennies: 6 | {{- range .Using }} 7 | // {{ .JennyName }} 8 | {{- end }} 9 | // 10 | // Run 'go generate ./' from repository root to regenerate. 11 | 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See GitHub's documentation for more information on this file: 2 | # https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates 3 | version: 2 4 | updates: 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "daily" 9 | - package-ecosystem: "gomod" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | -------------------------------------------------------------------------------- /gen/terraform/terraform.go: -------------------------------------------------------------------------------- 1 | package terraform 2 | 3 | import ( 4 | jen "github.com/grafana/terraform-provider-schemas/gen/internal" 5 | ) 6 | 7 | func JenniesForTerraform() jen.TargetJennies { 8 | tgt := jen.NewTargetJennies() 9 | 10 | tgt.Core.Append( 11 | jen.LatestJenny("", TerraformDataSourceJenny{}), 12 | &TerraformCoreRegistryJenny{}, 13 | ) 14 | 15 | tgt.Composable.Append( 16 | jen.ComposableLatestMajorsOrXJenny("", true, TerraformDataSourceJenny{}), 17 | &TerraformComposableRegistryJenny{}, 18 | ) 19 | 20 | return tgt 21 | } 22 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: terraform-provider-schemas 5 | title: Grafana Schemas Terraform Provider 6 | annotations: 7 | github.com/project-slug: grafana/terraform-provider-schemas 8 | links: 9 | - title: Slack Channel 10 | url: https://raintank-corp.slack.com/archives/C018SLDD5MW 11 | description: | 12 | Generated Terraform provider to manage Grafana dashboards 13 | spec: 14 | type: library 15 | owner: group:default/platform-monitoring 16 | lifecycle: experimental 17 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | # Visit https://golangci-lint.run/ for usage documentation 2 | # and information on other useful linters 3 | run: 4 | timeout: 2m 5 | 6 | issues: 7 | max-per-linter: 0 8 | max-same-issues: 0 9 | 10 | linters: 11 | disable-all: true 12 | enable: 13 | - durationcheck 14 | - errcheck 15 | - exportloopref 16 | - forcetypeassert 17 | - godot 18 | - gofmt 19 | - gosimple 20 | - ineffassign 21 | - makezero 22 | - misspell 23 | - nilerr 24 | - predeclared 25 | - staticcheck 26 | - tenv 27 | - unconvert 28 | - unparam 29 | - unused 30 | - vet -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.exe 3 | .DS_Store 4 | example.tf 5 | terraform.tfplan 6 | terraform.tfstate 7 | .terraform.lock.hcl 8 | bin/ 9 | dist/ 10 | modules-dev/ 11 | /pkg/ 12 | website/.vagrant 13 | website/.bundle 14 | website/build 15 | website/node_modules 16 | .vagrant/ 17 | *.backup 18 | ./*.tfstate 19 | .terraform/ 20 | *.log 21 | *.bak 22 | *~ 23 | .*.swp 24 | .idea 25 | *.iml 26 | *.test 27 | *.iml 28 | 29 | website/vendor 30 | 31 | # Test exclusions 32 | !command/test-fixtures/**/*.tfstate 33 | !command/test-fixtures/**/.terraform/ 34 | 35 | # Keep windows files with windows line endings 36 | *.winfile eol=crlf 37 | 38 | terraform-provider-schemas 39 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Run provider", 6 | "type": "go", 7 | "request": "launch", 8 | "mode": "auto", 9 | "program": "${workspaceFolder}/main.go", 10 | "args": ["--debug"], 11 | }, 12 | { 13 | "name": "Run generate", 14 | "type": "go", 15 | "request": "launch", 16 | "mode": "auto", 17 | "program": "${workspaceFolder}/gen/gen.go", 18 | "env": { 19 | "MIN_MATURITY": "merged", 20 | }, 21 | "cwd": "${workspaceFolder}" 22 | }, 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.0 2 | 3 | Provides data sources to help build a dashboard JSON object. 4 | Contains a data source for the dashboard object and for the following plugins: 5 | 6 | *Panels:* 7 | - Alert groups 8 | - Annotations list 9 | - Bar chart 10 | - Bar gauge 11 | - Dashboard list 12 | - Data grid 13 | - Debug 14 | - Gauge 15 | - Geomap 16 | - Heatmap 17 | - Histogram 18 | - Logs 19 | - News 20 | - Node graph 21 | - Pie chart 22 | - Stat 23 | - State timeline 24 | - Table 25 | - Text 26 | - Time series 27 | - Trend 28 | - XY chart 29 | 30 | *Data sources:* 31 | - Elasticsearch 32 | - Pyroscope 33 | - Loki 34 | - Parca 35 | - Prometheus 36 | - Testdata 37 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/templates/schema_attribute.tmpl: -------------------------------------------------------------------------------- 1 | "{{.Name}}": schema.{{.AttributeType}}Attribute{ 2 | MarkdownDescription: `{{.Description}}`, 3 | Computed: {{.Computed}}, 4 | Optional: {{.Optional}}, 5 | Required: {{not .Optional}}, 6 | {{ if .ElementType }}ElementType: {{.ElementType}},{{ end }} 7 | {{- if .DeprecationMessage }}DeprecationMessage: `{{.DeprecationMessage}}`,{{ end }} 8 | {{- if .NestedAttributes }}Attributes: map[string]schema.Attribute{ 9 | {{.NestedAttributes}} 10 | },{{ end }} 11 | {{- if .NestedObjectAttributes }}NestedObject: schema.NestedAttributeObject{ 12 | Attributes: map[string]schema.Attribute{ 13 | {{.NestedObjectAttributes}} 14 | }, 15 | },{{ end }} 16 | }, 17 | -------------------------------------------------------------------------------- /internal/provider/provider_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | // testAccProtoV6ProviderFactories are used to instantiate a provider during 4 | // acceptance testing. The factory function will be invoked for every Terraform 5 | // CLI command executed to create a provider server to which the CLI can 6 | // reattach. 7 | // var testAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServer, error){ 8 | // "schemas": providerserver.NewProtocol6WithError(New("schemas")()), 9 | // } 10 | 11 | // func testAccPreCheck(t *testing.T) { 12 | // // You can add code here to run prior to any test case execution, for example assertions 13 | // // about the appropriate environment variables being set are common to see in a pre-check 14 | // // function. 15 | // } 16 | -------------------------------------------------------------------------------- /gen/internal/tmpl.go: -------------------------------------------------------------------------------- 1 | package jen 2 | 3 | import ( 4 | "embed" 5 | "text/template" 6 | "time" 7 | 8 | "github.com/grafana/codejen" 9 | ) 10 | 11 | // All the parsed templates in the tmpl subdirectory. 12 | var tmpls *template.Template 13 | 14 | func init() { 15 | base := template.New("codegen").Funcs(template.FuncMap{ 16 | "now": time.Now, 17 | }) 18 | tmpls = template.Must(base.ParseFS(tmplFS, "tmpl/*.tmpl")) 19 | } 20 | 21 | //go:embed tmpl/*.tmpl 22 | var tmplFS embed.FS 23 | 24 | // The following group of types, beginning with tvars_*, all contain the set 25 | // of variables expected by the corresponding named template file under "tmpl/". 26 | type ( 27 | tvars_gen_header struct { 28 | MainGenerator string 29 | Using []codejen.NamedJenny 30 | From string 31 | } 32 | ) 33 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/types/mappings.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import "cuelang.org/go/cue" 4 | 5 | type kindMapping struct { 6 | terraformType string 7 | golangType string 8 | terraformFunc string 9 | } 10 | 11 | var kindMappings = map[cue.Kind]*kindMapping{ 12 | cue.BoolKind: { 13 | terraformType: "Bool", 14 | golangType: "bool", 15 | terraformFunc: "ValueBool", 16 | }, 17 | cue.IntKind: { 18 | terraformType: "Int64", 19 | golangType: "int64", 20 | terraformFunc: "ValueInt64", 21 | }, 22 | cue.FloatKind: { 23 | terraformType: "Float64", 24 | golangType: "float64", 25 | terraformFunc: "ValueFloat64", 26 | }, 27 | cue.NumberKind: { 28 | terraformType: "Float64", 29 | golangType: "float64", 30 | terraformFunc: "ValueFloat64", 31 | }, 32 | cue.StringKind: { 33 | terraformType: "String", 34 | golangType: "string", 35 | terraformFunc: "ValueString", 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /gen/terraform/jenny_datasource.go: -------------------------------------------------------------------------------- 1 | package terraform 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/grafana/codejen" 7 | "github.com/grafana/grafana/pkg/codegen" 8 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf" 9 | "golang.org/x/tools/imports" 10 | ) 11 | 12 | type TerraformDataSourceJenny struct{} 13 | 14 | func (j TerraformDataSourceJenny) JennyName() string { 15 | return "TerraformDataSourceJenny" 16 | } 17 | 18 | func (j TerraformDataSourceJenny) Generate(sfg codegen.SchemaForGen) (*codejen.File, error) { 19 | bytes, err := cuetf.GenerateDataSource(sfg.Schema) 20 | if err != nil { 21 | return nil, err 22 | } 23 | 24 | name := cuetf.GetResourceName(sfg.Schema.Lineage().Name()) 25 | fname := "datasource_" + name + "_gen.go" 26 | 27 | bytes, err = imports.Process(fname, bytes, nil) 28 | if err != nil { 29 | return nil, fmt.Errorf("goimports processing of generated file failed: %w", err) 30 | } 31 | 32 | return codejen.NewFile(fname, bytes, j), nil 33 | } 34 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/internal/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | 7 | "golang.org/x/text/cases" 8 | "golang.org/x/text/language" 9 | ) 10 | 11 | var matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)") 12 | var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") 13 | 14 | func Title(str string) string { 15 | var caser = cases.Title(language.English, cases.NoLower) 16 | return caser.String(str) 17 | } 18 | 19 | func ToSnakeCase(str string) string { 20 | snake := matchFirstCap.ReplaceAllString(str, "${1}_${2}") 21 | snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}") 22 | return strings.ToLower(snake) 23 | } 24 | 25 | func ToCamelCase(str string) string { 26 | words := strings.Split(str, "_") 27 | camelCase := "" 28 | for _, s := range words { 29 | camelCase += Title(s) 30 | } 31 | return camelCase 32 | } 33 | 34 | func CapitalizeFirstLetter(str string) string { 35 | sep := " " 36 | parts := strings.SplitN(str, sep, 2) 37 | if len(parts) != 2 { 38 | return Title(str) 39 | } 40 | return Title(parts[0]) + sep + parts[1] 41 | } 42 | -------------------------------------------------------------------------------- /docs/data-sources/query_parca.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_query_parca Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_query_parca (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - `profile_type_id` (String) Specifies the type of profile to query. 21 | - `ref_id` (String) A unique identifier for the query within the list of targets. 22 | In server side expressions, the refId is used as a variable name to identify results. 23 | By default, the UI will assign A->Z; however setting meaningful names may be useful. 24 | 25 | ### Optional 26 | 27 | - `hide` (Boolean) true if query is disabled (ie should not be returned to the dashboard) 28 | Note this does not always imply that the query should not be executed since 29 | the results from a hidden query may be used as the input to other queries (SSE etc) 30 | - `label_selector` (String) Specifies the query label selectors. Defaults to "{}". 31 | - `query_type` (String) Specify the query flavor 32 | TODO make this required and give it a default 33 | 34 | ### Read-Only 35 | 36 | - `rendered_json` (String) This datasource rendered as JSON 37 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/tmpl.go: -------------------------------------------------------------------------------- 1 | package cuetf 2 | 3 | import ( 4 | "embed" 5 | "strings" 6 | "text/template" 7 | ) 8 | 9 | // All the parsed templates in the tmpl subdirectory. 10 | var tmpls *template.Template 11 | 12 | func init() { 13 | base := template.New("cuetf").Funcs(template.FuncMap{ 14 | "lowerCase": strings.ToLower, 15 | "startsWith": strings.HasPrefix, 16 | }) 17 | tmpls = template.Must(base.ParseFS(tmplFS, "templates/*.tmpl")) 18 | } 19 | 20 | //go:embed templates/*.tmpl 21 | var tmplFS embed.FS 22 | 23 | // The following group of types, beginning with tvars_*, all contain the set 24 | // of variables expected by the corresponding named template file under "templates/". 25 | type ( 26 | TVarsDataSource struct { 27 | Name string 28 | StructName string 29 | Description string 30 | Models string 31 | SchemaAttributes string 32 | } 33 | 34 | TVarsSchemaAttribute struct { 35 | Name string 36 | Description string 37 | AttributeType string 38 | DeprecationMessage string 39 | Computed bool 40 | Optional bool 41 | ElementType string // Used for simple lists 42 | NestedAttributes string // Used for objects 43 | NestedObjectAttributes string // Used for complex lists 44 | } 45 | ) 46 | -------------------------------------------------------------------------------- /docs/data-sources/query_grafana_pyroscope.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_query_grafana_pyroscope Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_query_grafana_pyroscope (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - `profile_type_id` (String) Specifies the type of profile to query. 21 | - `ref_id` (String) A unique identifier for the query within the list of targets. 22 | In server side expressions, the refId is used as a variable name to identify results. 23 | By default, the UI will assign A->Z; however setting meaningful names may be useful. 24 | 25 | ### Optional 26 | 27 | - `group_by` (List of String) Allows to group the results. 28 | - `hide` (Boolean) true if query is disabled (ie should not be returned to the dashboard) 29 | Note this does not always imply that the query should not be executed since 30 | the results from a hidden query may be used as the input to other queries (SSE etc) 31 | - `label_selector` (String) Specifies the query label selectors. Defaults to "{}". 32 | - `max_nodes` (Number) Sets the maximum number of nodes in the flamegraph. 33 | - `query_type` (String) Specify the query flavor 34 | TODO make this required and give it a default 35 | 36 | ### Read-Only 37 | 38 | - `rendered_json` (String) This datasource rendered as JSON 39 | -------------------------------------------------------------------------------- /examples/schemas_core_dashboard/simple/dashboard.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | schemas = { 4 | source = "grafana/schemas" 5 | version = "0.1.0" 6 | } 7 | grafana = { 8 | source = "grafana/grafana" 9 | version = "1.36.1" 10 | } 11 | } 12 | } 13 | 14 | provider "grafana" { 15 | url = "http://localhost:3000" 16 | auth = "admin:admin" 17 | } 18 | 19 | resource "grafana_dashboard" "example" { 20 | config_json = data.schemas_core_dashboard.dashboard.rendered_json 21 | } 22 | 23 | data "schemas_core_dashboard" "dashboard" { 24 | title = "Faro dashboard" 25 | uid = "faro-terraform-demo" 26 | description = "Dashboard for Faro" 27 | graph_tooltip = 1 28 | 29 | panels = [ 30 | data.schemas_panel_time_series.requests.rendered_json, 31 | ] 32 | } 33 | 34 | data "schemas_panel_time_series" "requests" { 35 | title = "Requests / sec" 36 | 37 | datasource = { 38 | uid = "ops-cortex" 39 | type = "prometheus" 40 | } 41 | 42 | targets = [ 43 | data.schemas_query_prometheus.requests_target.rendered_json 44 | ] 45 | 46 | field_config = { 47 | defaults = { 48 | unit = "reqps" 49 | } 50 | } 51 | 52 | grid_pos = { 53 | h = 8 54 | w = 24 55 | } 56 | } 57 | 58 | data "schemas_query_prometheus" "requests_target" { 59 | expr = "sum by (status_code) (rate(request_duration_seconds_count{job=~\".*/faro-api\"}[$__rate_interval]))" 60 | format = "time_series" 61 | ref_id = "A" 62 | } 63 | -------------------------------------------------------------------------------- /internal/provider/registry_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated - EDITING IS FUTILE. DO NOT EDIT. 2 | // 3 | // Generated by pipeline: 4 | // terraform 5 | // Using jennies: 6 | // TerraformComposableRegistryJenny 7 | // 8 | // Run 'go generate ./' from repository root to regenerate. 9 | 10 | package provider 11 | 12 | import ( 13 | "github.com/hashicorp/terraform-plugin-framework/datasource" 14 | ) 15 | 16 | var datasources = []func() datasource.DataSource{ 17 | NewCoreDashboardDataSource, 18 | NewQueryElasticsearchDataSource, 19 | NewQueryGrafanaPyroscopeDataSource, 20 | NewQueryLokiDataSource, 21 | NewQueryParcaDataSource, 22 | NewQueryPrometheusDataSource, 23 | NewQueryTestDataDataSource, 24 | NewPanelAlertGroupsDataSource, 25 | NewPanelAnnotationsListDataSource, 26 | NewPanelBarChartDataSource, 27 | NewPanelBarGaugeDataSource, 28 | NewPanelCandlestickDataSource, 29 | NewPanelCanvasDataSource, 30 | NewPanelDashboardListDataSource, 31 | NewPanelDatagridDataSource, 32 | NewPanelDebugDataSource, 33 | NewPanelGaugeDataSource, 34 | NewPanelGeomapDataSource, 35 | NewPanelHeatmapDataSource, 36 | NewPanelHistogramDataSource, 37 | NewPanelLogsDataSource, 38 | NewPanelNewsDataSource, 39 | NewPanelNodeGraphDataSource, 40 | NewPanelPieChartDataSource, 41 | NewPanelStatDataSource, 42 | NewPanelStateTimelineDataSource, 43 | NewPanelStatusHistoryDataSource, 44 | NewPanelTableDataSource, 45 | NewPanelTextDataSource, 46 | NewPanelTimeSeriesDataSource, 47 | NewPanelTrendDataSource, 48 | NewPanelXYChartDataSource, 49 | } 50 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "log" 7 | 8 | "github.com/grafana/terraform-provider-schemas/internal/provider" 9 | "github.com/hashicorp/terraform-plugin-framework/providerserver" 10 | ) 11 | 12 | // Run "go generate" to format example terraform files and generate the docs for the registry/website. 13 | 14 | // If you do not have terraform installed, you can remove the formatting command, but its suggested to 15 | // ensure the documentation is formatted properly. 16 | //go:generate terraform fmt -recursive ./examples/ 17 | 18 | // Run the docs generation tool, check its repository for more information on how it works and how docs 19 | // can be customized. 20 | //go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs 21 | 22 | var ( 23 | // these will be set by the goreleaser configuration 24 | // to appropriate values for the compiled binary. 25 | version string = "dev" 26 | 27 | // goreleaser can pass other information to the main package, such as the specific commit 28 | // https://goreleaser.com/cookbooks/using-main.version/ 29 | ) 30 | 31 | func main() { 32 | var debug bool 33 | 34 | flag.BoolVar(&debug, "debug", false, "set to true to run the provider with support for debuggers like delve") 35 | flag.Parse() 36 | 37 | opts := providerserver.ServeOpts{ 38 | Address: "registry.terraform.io/grafana/schemas", 39 | Debug: debug, 40 | } 41 | 42 | err := providerserver.Serve(context.Background(), provider.New(version), opts) 43 | 44 | if err != nil { 45 | log.Fatal(err.Error()) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docs/data-sources/query_loki.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_query_loki Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_query_loki (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - `expr` (String) The LogQL query. 21 | - `ref_id` (String) A unique identifier for the query within the list of targets. 22 | In server side expressions, the refId is used as a variable name to identify results. 23 | By default, the UI will assign A->Z; however setting meaningful names may be useful. 24 | 25 | ### Optional 26 | 27 | - `editor_mode` (String) 28 | - `hide` (Boolean) true if query is disabled (ie should not be returned to the dashboard) 29 | Note this does not always imply that the query should not be executed since 30 | the results from a hidden query may be used as the input to other queries (SSE etc) 31 | - `instant` (Boolean, Deprecated) @deprecated, now use queryType. 32 | - `legend_format` (String) Used to override the name of the series. 33 | - `max_lines` (Number) Used to limit the number of log rows returned. 34 | - `query_type` (String) Specify the query flavor 35 | TODO make this required and give it a default 36 | - `range` (Boolean, Deprecated) @deprecated, now use queryType. 37 | - `resolution` (Number, Deprecated) @deprecated, now use step. 38 | - `step` (String) Used to set step value for range queries. 39 | 40 | ### Read-Only 41 | 42 | - `rendered_json` (String) This datasource rendered as JSON 43 | -------------------------------------------------------------------------------- /gen/internal/jenny_major.go: -------------------------------------------------------------------------------- 1 | package jen 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | 7 | "github.com/grafana/codejen" 8 | "github.com/grafana/grafana/pkg/codegen" 9 | "github.com/grafana/kindsys" 10 | ) 11 | 12 | // LatestJenny returns a jenny that runs another jenny for only the latest 13 | // schema in a DefForGen, and prefixes the resulting file with the provided 14 | // parentdir (e.g. "pkg/kinds/"). 15 | // TODO remove this once there's a standard jenny for this...somewhere in core. 16 | func LatestJenny(parentdir string, inner codejen.OneToOne[codegen.SchemaForGen]) codegen.OneToOne { 17 | if inner == nil { 18 | panic("inner jenny must not be nil") 19 | } 20 | 21 | return &latestj{ 22 | parentdir: parentdir, 23 | inner: inner, 24 | } 25 | } 26 | 27 | type latestj struct { 28 | parentdir string 29 | inner codejen.OneToOne[codegen.SchemaForGen] 30 | } 31 | 32 | func (j *latestj) JennyName() string { 33 | return "LatestJenny" 34 | } 35 | 36 | func (j *latestj) Generate(kind kindsys.Kind) (*codejen.File, error) { 37 | comm := kind.Props().Common() 38 | sfg := codegen.SchemaForGen{ 39 | Name: comm.Name, 40 | Schema: kind.Lineage().Latest(), 41 | IsGroup: comm.LineageIsGroup, 42 | } 43 | 44 | f, err := j.inner.Generate(sfg) 45 | if err != nil { 46 | return nil, fmt.Errorf("%s jenny failed on %s schema for %s: %w", j.inner.JennyName(), sfg.Schema.Version(), kind.Props().Common().Name, err) 47 | } 48 | if f == nil || !f.Exists() { 49 | return nil, nil 50 | } 51 | 52 | f.RelativePath = filepath.Join(j.parentdir, f.RelativePath) 53 | f.From = append(f.From, j) 54 | return f, nil 55 | } 56 | -------------------------------------------------------------------------------- /gen/terraform/jenny_datasource_registry.go: -------------------------------------------------------------------------------- 1 | package terraform 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/grafana/codejen" 8 | "github.com/grafana/kindsys" 9 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf" 10 | ) 11 | 12 | var datasources []string 13 | 14 | type TerraformCoreRegistryJenny struct { 15 | } 16 | 17 | func (j TerraformCoreRegistryJenny) JennyName() string { 18 | return "TerraformCoreRegistryJenny" 19 | } 20 | 21 | func (j TerraformCoreRegistryJenny) Generate(k ...kindsys.Kind) (*codejen.File, error) { 22 | for _, k := range k { 23 | datasources = append(datasources, cuetf.GetStructName(k.Lineage().Name())) 24 | } 25 | 26 | return nil, nil 27 | } 28 | 29 | type TerraformComposableRegistryJenny struct { 30 | } 31 | 32 | func (j TerraformComposableRegistryJenny) JennyName() string { 33 | return "TerraformComposableRegistryJenny" 34 | } 35 | 36 | func (j TerraformComposableRegistryJenny) Generate(k ...kindsys.Composable) (*codejen.File, error) { 37 | for _, k := range k { 38 | datasources = append(datasources, cuetf.GetStructName(k.Lineage().Name())) 39 | } 40 | 41 | datasourceConstructors := []string{} 42 | for _, datasource := range datasources { 43 | datasourceConstructors = append(datasourceConstructors, "New"+datasource) 44 | } 45 | 46 | bytes := []byte(fmt.Sprintf(`package provider 47 | 48 | import ( 49 | "github.com/hashicorp/terraform-plugin-framework/datasource" 50 | ) 51 | 52 | var datasources = []func() datasource.DataSource{ 53 | %s, 54 | } 55 | `, strings.Join(datasourceConstructors, ",\n "))) 56 | 57 | return codejen.NewFile("registry_gen.go", bytes, j), nil 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # Terraform Provider release workflow. 2 | name: Release 3 | 4 | # This GitHub action creates a release when a tag that matches the pattern 5 | # "v*" (e.g. v0.1.0) is created. 6 | on: 7 | push: 8 | tags: 9 | - 'v*' 10 | 11 | # Releases need permissions to read and write the repository contents. 12 | # GitHub considers creating releases and uploading assets as writing contents. 13 | permissions: 14 | contents: write 15 | 16 | jobs: 17 | goreleaser: 18 | runs-on: ubuntu-latest 19 | environment: release 20 | steps: 21 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 22 | with: 23 | # Allow goreleaser to access older tag information. 24 | fetch-depth: 0 25 | persist-credentials: false 26 | - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 27 | with: 28 | go-version-file: 'go.mod' 29 | # Disable cache to prevent cache poisoning attack 30 | cache: false 31 | 32 | - name: Import GPG key 33 | uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0 34 | id: import_gpg 35 | with: 36 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} 37 | passphrase: ${{ secrets.PASSPHRASE }} 38 | - name: Run GoReleaser 39 | uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0 40 | with: 41 | args: release --clean 42 | env: 43 | # GitHub sets the GITHUB_TOKEN secret automatically. 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} 46 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # Visit https://goreleaser.com for documentation on how to customize this 2 | # behavior. 3 | before: 4 | hooks: 5 | # this is just an example and not a requirement for provider building/publishing 6 | - go mod tidy 7 | builds: 8 | - env: 9 | # goreleaser does not work with CGO, it could also complicate 10 | # usage by users in CI/CD systems like Terraform Cloud where 11 | # they are unable to install libraries. 12 | - CGO_ENABLED=0 13 | mod_timestamp: '{{ .CommitTimestamp }}' 14 | flags: 15 | - -trimpath 16 | ldflags: 17 | - '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}' 18 | goos: 19 | - freebsd 20 | - windows 21 | - linux 22 | - darwin 23 | goarch: 24 | - amd64 25 | - '386' 26 | - arm 27 | - arm64 28 | ignore: 29 | - goos: darwin 30 | goarch: '386' 31 | binary: '{{ .ProjectName }}_v{{ .Version }}' 32 | archives: 33 | - format: zip 34 | name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}' 35 | checksum: 36 | extra_files: 37 | - glob: 'terraform-registry-manifest.json' 38 | name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json' 39 | name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS' 40 | algorithm: sha256 41 | signs: 42 | - artifacts: checksum 43 | args: 44 | # if you are using this in a GitHub action or some other automated pipeline, you 45 | # need to pass the batch flag to indicate its not interactive. 46 | - "--batch" 47 | - "--local-user" 48 | - "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key 49 | - "--output" 50 | - "${signature}" 51 | - "--detach-sign" 52 | - "${artifact}" 53 | release: 54 | extra_files: 55 | - glob: 'terraform-registry-manifest.json' 56 | name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json' 57 | # If you want to manually examine the release before its live, uncomment this line: 58 | # draft: true 59 | changelog: 60 | skip: true 61 | -------------------------------------------------------------------------------- /docs/data-sources/query_prometheus.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_query_prometheus Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_query_prometheus (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - `expr` (String) The actual expression/query that will be evaluated by Prometheus 21 | - `ref_id` (String) A unique identifier for the query within the list of targets. 22 | In server side expressions, the refId is used as a variable name to identify results. 23 | By default, the UI will assign A->Z; however setting meaningful names may be useful. 24 | 25 | ### Optional 26 | 27 | - `editor_mode` (String) Specifies which editor is being used to prepare the query. It can be "code" or "builder" 28 | - `exemplar` (Boolean) Execute an additional query to identify interesting raw samples relevant for the given expr 29 | - `format` (String) Query format to determine how to display data points in panel. It can be "time_series", "table", "heatmap" 30 | - `hide` (Boolean) true if query is disabled (ie should not be returned to the dashboard) 31 | Note this does not always imply that the query should not be executed since 32 | the results from a hidden query may be used as the input to other queries (SSE etc) 33 | - `instant` (Boolean) Returns only the latest value that Prometheus has scraped for the requested time series 34 | - `interval_factor` (Number, Deprecated) @deprecated Used to specify how many times to divide max data points by. We use max data points under query options 35 | See https://github.com/grafana/grafana/issues/48081 36 | - `legend_format` (String) Series name override or template. Ex. {{hostname}} will be replaced with label value for hostname 37 | - `query_type` (String) Specify the query flavor 38 | TODO make this required and give it a default 39 | - `range` (Boolean) Returns a Range vector, comprised of a set of time series containing a range of data points over time for each time series 40 | 41 | ### Read-Only 42 | 43 | - `rendered_json` (String) This datasource rendered as JSON 44 | -------------------------------------------------------------------------------- /gen/internal/all.go: -------------------------------------------------------------------------------- 1 | package jen 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "path/filepath" 7 | 8 | "github.com/grafana/codejen" 9 | "github.com/grafana/kindsys" 10 | ) 11 | 12 | // TargetJennies is a set of jennies for a particular target language or 13 | // tool that perform all necessary code generation steps. 14 | type TargetJennies struct { 15 | Core *codejen.JennyList[kindsys.Kind] 16 | Composable *codejen.JennyList[kindsys.Composable] 17 | } 18 | 19 | // NewTargetJennies initializes a new TargetJennies with appropriate namers for 20 | // each JennyList. 21 | func NewTargetJennies() TargetJennies { 22 | return TargetJennies{ 23 | Core: codejen.JennyListWithNamer[kindsys.Kind](func(k kindsys.Kind) string { 24 | return k.Props().Common().MachineName 25 | }), 26 | Composable: codejen.JennyListWithNamer[kindsys.Composable](func(k kindsys.Composable) string { 27 | return k.Name() 28 | }), 29 | } 30 | } 31 | 32 | // Prefixer returns a FileMapper that injects the provided path prefix to files 33 | // passed through it. 34 | func Prefixer(prefix string) codejen.FileMapper { 35 | return func(f codejen.File) (codejen.File, error) { 36 | f.RelativePath = filepath.Join(prefix, f.RelativePath) 37 | return f, nil 38 | } 39 | } 40 | 41 | // SlashHeaderMapper produces a FileMapper that injects a comment header onto 42 | // a [codejen.File] indicating the main generator that produced it (via the provided 43 | // maingen, which should be a path) and the jenny or jennies that constructed the 44 | // file. 45 | func SlashHeaderMapper(maingen string) codejen.FileMapper { 46 | return func(f codejen.File) (codejen.File, error) { 47 | // Never inject on certain filetypes, it's never valid 48 | switch filepath.Ext(f.RelativePath) { 49 | case ".json", ".yml", ".yaml", ".md": 50 | return f, nil 51 | default: 52 | buf := new(bytes.Buffer) 53 | if err := tmpls.Lookup("gen_header.tmpl").Execute(buf, tvars_gen_header{ 54 | MainGenerator: maingen, 55 | Using: f.From, 56 | }); err != nil { 57 | return codejen.File{}, fmt.Errorf("failed executing gen header template: %w", err) 58 | } 59 | fmt.Fprint(buf, string(f.Data)) 60 | f.Data = buf.Bytes() 61 | } 62 | return f, nil 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /internal/provider/provider.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "github.com/hashicorp/terraform-plugin-framework/datasource" 8 | "github.com/hashicorp/terraform-plugin-framework/provider" 9 | "github.com/hashicorp/terraform-plugin-framework/provider/schema" 10 | "github.com/hashicorp/terraform-plugin-framework/resource" 11 | ) 12 | 13 | // Ensure schemasProvider satisfies various provider interfaces. 14 | var _ provider.Provider = &schemasProvider{} 15 | 16 | // schemasProvider defines the provider implementation. 17 | type schemasProvider struct { 18 | // version is set to the provider version on release, "dev" when the 19 | // provider is built and ran locally, and "test" when running acceptance 20 | // testing. 21 | version string 22 | } 23 | 24 | // schemasProviderModel describes the provider data model. 25 | type schemasProviderModel struct { 26 | } 27 | 28 | func (p *schemasProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { 29 | resp.TypeName = "schemas" 30 | resp.Version = p.version 31 | } 32 | 33 | func (p *schemasProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { 34 | resp.Schema = schema.Schema{ 35 | Attributes: map[string]schema.Attribute{}, 36 | } 37 | } 38 | 39 | func (p *schemasProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { 40 | var data schemasProviderModel 41 | 42 | resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) 43 | 44 | if resp.Diagnostics.HasError() { 45 | return 46 | } 47 | 48 | // Configuration values are now available. 49 | // if data.Endpoint.IsNull() { /* ... */ } 50 | 51 | // Example client configuration for data sources and resources 52 | client := http.DefaultClient 53 | resp.DataSourceData = client 54 | resp.ResourceData = client 55 | } 56 | 57 | func (p *schemasProvider) Resources(ctx context.Context) []func() resource.Resource { 58 | return []func() resource.Resource{} 59 | } 60 | 61 | func (p *schemasProvider) DataSources(ctx context.Context) []func() datasource.DataSource { 62 | return datasources 63 | } 64 | 65 | func New(version string) func() provider.Provider { 66 | return func() provider.Provider { 67 | return &schemasProvider{ 68 | version: version, 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /gen/internal/jenny_eachmajorcomposable.go: -------------------------------------------------------------------------------- 1 | package jen 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "strings" 7 | 8 | "github.com/grafana/codejen" 9 | "github.com/grafana/grafana/pkg/codegen" 10 | "github.com/grafana/kindsys" 11 | ) 12 | 13 | // TODO remove this once there's a standard jenny for this...somewhere in core. 14 | func ComposableLatestMajorsOrXJenny(parentdir string, useParentDirOnly bool, inner codejen.OneToOne[codegen.SchemaForGen]) codejen.OneToMany[kindsys.Composable] { 15 | if inner == nil { 16 | panic("inner jenny must not be nil") 17 | } 18 | 19 | return &clmox{ 20 | parentdir: parentdir, 21 | useParentDirOnly: useParentDirOnly, 22 | inner: inner, 23 | } 24 | } 25 | 26 | type clmox struct { 27 | parentdir string 28 | useParentDirOnly bool // Do not create sub folders in parentdir. 29 | inner codejen.OneToOne[codegen.SchemaForGen] 30 | } 31 | 32 | func (j *clmox) JennyName() string { 33 | return "ComposableLatestMajorsOrXJenny" 34 | } 35 | 36 | func (j *clmox) Generate(k kindsys.Composable) (codejen.Files, error) { 37 | si, err := kindsys.FindSchemaInterface(k.Def().Properties.SchemaInterface) 38 | if err != nil { 39 | panic(err) 40 | } 41 | sfg := codegen.SchemaForGen{ 42 | Name: k.Lineage().Name(), 43 | IsGroup: si.IsGroup(), 44 | } 45 | 46 | // TODO adapt this once we figure out consistent naming 47 | // nam := fmt.Sprintf("%s-%s", strings.ToLower(decl.Info.Meta().Id), strings.ToLower(sfg.Name)) 48 | nam := strings.ToLower(sfg.Name) 49 | 50 | do := func(sfg codegen.SchemaForGen, infix string) (codejen.Files, error) { 51 | f, err := j.inner.Generate(sfg) 52 | if err != nil { 53 | return nil, fmt.Errorf("%s jenny failed on %s schema for %s: %w", j.inner.JennyName(), sfg.Schema.Version(), nam, err) 54 | } 55 | if f == nil || !f.Exists() { 56 | return nil, nil 57 | } 58 | 59 | if j.useParentDirOnly { 60 | f.RelativePath = filepath.Join(j.parentdir, strings.ToLower(f.RelativePath)) 61 | } else { 62 | f.RelativePath = filepath.Join(j.parentdir, strings.ToLower(strings.TrimSuffix(sfg.Name, si.Name())), strings.ToLower(si.Name()), infix, strings.ToLower(f.RelativePath)) 63 | } 64 | f.From = append(f.From, j) 65 | return codejen.Files{*f}, nil 66 | } 67 | 68 | // TODO uncomment this latter half once plugins are fully converted to new system 69 | // if comm.Maturity.Less(kindsys.MaturityStable) { 70 | sfg.Schema = k.Lineage().Latest() 71 | return do(sfg, "x") 72 | // } 73 | 74 | // var fl codejen.Files 75 | // for sch := decl.Lineage.First(); sch != nil; sch = sch.Successor() { 76 | // sfg.Schema = sch.LatestInMajor() 77 | // files, err := do(sfg, fmt.Sprintf("v%v", sch.Version()[0])) 78 | // if err != nil { 79 | // return nil, err 80 | // } 81 | // fl = append(fl, files...) 82 | // } 83 | // if fl.Validate() != nil { 84 | // return nil, fl.Validate() 85 | // } 86 | // return fl, nil 87 | } 88 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # Terraform Provider testing workflow. 2 | name: Tests 3 | 4 | # This GitHub action runs your tests for each pull request and push. 5 | # Optionally, you can turn it on using a schedule for regular testing. 6 | on: 7 | pull_request: 8 | paths-ignore: 9 | - 'README.md' 10 | push: 11 | paths-ignore: 12 | - 'README.md' 13 | 14 | # Testing only needs permissions to read the repository contents. 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | # Ensure project builds before running testing matrix 20 | build: 21 | name: Build 22 | runs-on: ubuntu-latest 23 | timeout-minutes: 5 24 | steps: 25 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 26 | with: 27 | persist-credentials: false 28 | - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 29 | with: 30 | go-version-file: 'go.mod' 31 | cache: true 32 | - run: go mod download 33 | - run: go build -v . 34 | - name: Run linters 35 | uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 36 | with: 37 | version: v1.52.2 38 | 39 | generate: 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 43 | with: 44 | persist-credentials: false 45 | - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 46 | with: 47 | go-version-file: 'go.mod' 48 | cache: true 49 | - run: rm -rf ./internal/provider/*_gen.go 50 | - run: cd ./gen && MIN_MATURITY=merged go generate ./ 51 | - run: go generate ./ 52 | - name: git diff 53 | run: | 54 | git diff --compact-summary --exit-code || \ 55 | (echo; echo "Unexpected difference in directories after code generation. Run 'go generate ./...' command and commit."; exit 1) 56 | 57 | # Run acceptance tests in a matrix with Terraform CLI versions 58 | test: 59 | name: Terraform Provider Acceptance Tests 60 | needs: build 61 | runs-on: ubuntu-latest 62 | timeout-minutes: 15 63 | strategy: 64 | fail-fast: false 65 | matrix: 66 | # list whatever Terraform versions here you would like to support 67 | terraform: 68 | - '1.0.*' 69 | - '1.1.*' 70 | - '1.2.*' 71 | steps: 72 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 73 | with: 74 | persist-credentials: false 75 | - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 76 | with: 77 | go-version-file: 'go.mod' 78 | cache: true 79 | - uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3 80 | with: 81 | terraform_version: ${{ matrix.terraform }} 82 | terraform_wrapper: false 83 | - run: go mod download 84 | - env: 85 | TF_ACC: "1" 86 | run: go test -v -cover ./internal/provider/ 87 | timeout-minutes: 10 88 | -------------------------------------------------------------------------------- /gen/gen.go: -------------------------------------------------------------------------------- 1 | //go:generate go run gen.go 2 | 3 | package main 4 | 5 | import ( 6 | "context" 7 | "fmt" 8 | "os" 9 | 10 | "github.com/grafana/codejen" 11 | "github.com/grafana/grafana/pkg/plugins/pfs/corelist" 12 | "github.com/grafana/grafana/pkg/registry/corekind" 13 | "github.com/grafana/kindsys" 14 | jen "github.com/grafana/terraform-provider-schemas/gen/internal" 15 | "github.com/grafana/terraform-provider-schemas/gen/terraform" 16 | ) 17 | 18 | func main() { 19 | // Load all core and composable kinds. 20 | var corek []kindsys.Kind 21 | var compok []kindsys.Composable 22 | 23 | minMaturity := 24 | func() kindsys.Maturity { 25 | switch os.Getenv("MIN_MATURITY") { 26 | case "merged": 27 | return kindsys.MaturityMerged 28 | case "experimental": 29 | return kindsys.MaturityExperimental 30 | case "stable": 31 | return kindsys.MaturityStable 32 | case "mature": 33 | return kindsys.MaturityMature 34 | default: 35 | return kindsys.MaturityExperimental 36 | } 37 | }() 38 | 39 | for _, kind := range corekind.NewBase(nil).All() { 40 | // This provider should only generate dashboard-related datasources for now 41 | if kind.Name() != "Dashboard" { 42 | continue 43 | } 44 | if kind.Maturity().Less(minMaturity) { 45 | continue 46 | } 47 | corek = append(corek, kind) 48 | } 49 | 50 | // Skip data sources that only have definitions 51 | skippedPlugins := map[string]bool{ 52 | "AzureMonitorDataQuery": true, 53 | "CloudWatchDataQuery": true, 54 | "GoogleCloudMonitoringDataQuery": true, 55 | "TempoDataQuery": true, 56 | } 57 | for _, pp := range corelist.New(nil) { 58 | for _, kind := range pp.ComposableKinds { 59 | _, skipped := skippedPlugins[kind.Lineage().Name()] 60 | if kind.Maturity().Less(minMaturity) || skipped { 61 | continue 62 | } 63 | compok = append(compok, kind) 64 | } 65 | } 66 | 67 | // Add all jennies. 68 | jfs := codejen.NewFS() 69 | tj := getJennies() 70 | 71 | ckfs, err := tj.Core.GenerateFS(corek...) 72 | die(err) 73 | die(jfs.Merge(ckfs)) 74 | ckfs, err = tj.Composable.GenerateFS(compok...) 75 | die(err) 76 | die(jfs.Merge(ckfs)) 77 | 78 | if _, set := os.LookupEnv("CODEGEN_VERIFY"); set { 79 | if err = jfs.Verify(context.Background(), ""); err != nil { 80 | die(fmt.Errorf("generated code is out of sync with inputs:\n%s\nrun `make gen-cue` to regenerate", err)) 81 | } 82 | } else if err = jfs.Write(context.Background(), ""); err != nil { 83 | die(fmt.Errorf("error while writing generated code to disk:\n%s", err)) 84 | } 85 | } 86 | 87 | // Get all jennies for Terraform. 88 | func getJennies() jen.TargetJennies { 89 | header := "terraform" 90 | path := "../internal/provider" 91 | tj := terraform.JenniesForTerraform() 92 | 93 | tj.Core.AddPostprocessors(jen.Prefixer(path), jen.SlashHeaderMapper(header)) 94 | tj.Composable.AddPostprocessors(jen.Prefixer(path), jen.SlashHeaderMapper(header)) 95 | 96 | return tj 97 | } 98 | 99 | func die(err error) { 100 | if err != nil { 101 | fmt.Fprint(os.Stderr, err, "\n") 102 | os.Exit(1) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "Schemas Provider" 3 | description: |- 4 | Generated provider to manage Grafana dashboards. 5 | --- 6 | 7 | # Schemas Provider 8 | 9 | This provider provides data sources to manage Grafana [dashboards](https://grafana.com/docs/grafana/latest/dashboards/). You should use it with the [Grafana Terraform Provider](https://registry.terraform.io/providers/grafana/grafana/latest). It is generated from the [CUE schemas](https://github.com/grafana/grafana/blob/main/kinds/dashboard/dashboard_kind.cue) defined in the Grafana repository to ensure it stays up-to-date. 10 | 11 | The code in this repository should be considered experimental. It comes with no support, but we are keen to receive feedback on the product and suggestions on how to improve it, though we cannot commit to resolution of any particular issue. No SLAs are available. It is not meant to be used in production environments, and the risks are unknown/high. 12 | 13 | Our goal is for these generated data sources to become a part of our official Grafana provider once this project becomes more mature. At this time, we are not planning to create a migration path for data sources created with the `schemas` provider when they are merged into the `grafana` provider. Also, this work is subject to signficant changes as we iterate towards that level of quality. 14 | 15 | ## Maturity 16 | 17 | Grafana Labs defines experimental features as follows: 18 | 19 | > Projects and features in the Experimental stage are supported only by the Engineering 20 | teams; on-call support is not available. Documentation is either limited or not provided 21 | outside of code comments. No SLA is provided. 22 | > 23 | > Experimental projects or features are primarily intended for open source engineers who 24 | want to participate in ensuring systems stability, and to gain consensus and approval 25 | for open source governance projects. 26 | > 27 | > Projects and features in the Experimental phase are not meant to be used in production 28 | environments, and the risks are unknown/high. 29 | 30 | ## Example usage 31 | 32 | Configure the [Grafana Terraform Provider](https://registry.terraform.io/providers/grafana/grafana/latest) to access your Grafana instance (see [documentation](https://grafana.com/docs/grafana-cloud/infrastructure-as-code/terraform/)). Then use this Grafana Schemas Terraform provider to create your dashboards. 33 | 34 | ``` 35 | terraform { 36 | required_providers { 37 | schemas = { 38 | source = "grafana/schemas" 39 | version = "0.1.0" 40 | } 41 | grafana = { 42 | source = "grafana/grafana" 43 | version = "1.36.1" 44 | } 45 | } 46 | } 47 | provider "grafana" { 48 | url = "http://localhost:3000" 49 | auth = "admin:admin" 50 | } 51 | resource "grafana_dashboard" "example" { 52 | config_json = data.schemas_core_dashboard.my_dashboard.rendered_json 53 | } 54 | data "schemas_core_dashboard" "my_dashboard" { 55 | title = "My Dashboard" 56 | time = { 57 | from = "now-1h" 58 | } 59 | panels = [ 60 | data.schemas_panel_stat.my_panel.rendered_json, 61 | ] 62 | } 63 | data "schemas_panel_stat" "my_panel" { 64 | title = "My Panel" 65 | grid_pos = { 66 | h = 4 67 | w = 6 68 | x = 0 69 | y = 0 70 | } 71 | } 72 | ``` -------------------------------------------------------------------------------- /templates/index.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | page_title: "Schemas Provider" 3 | description: |- 4 | Generated provider to manage Grafana dashboards. 5 | --- 6 | 7 | # Schemas Provider 8 | 9 | This provider provides data sources to manage Grafana [dashboards](https://grafana.com/docs/grafana/latest/dashboards/). You should use it with the [Grafana Terraform Provider](https://registry.terraform.io/providers/grafana/grafana/latest). It is generated from the [CUE schemas](https://github.com/grafana/grafana/blob/main/kinds/dashboard/dashboard_kind.cue) defined in the Grafana repository to ensure it stays up-to-date. 10 | 11 | The code in this repository should be considered experimental. It comes with no support, but we are keen to receive feedback on the product and suggestions on how to improve it, though we cannot commit to resolution of any particular issue. No SLAs are available. It is not meant to be used in production environments, and the risks are unknown/high. 12 | 13 | Our goal is for these generated data sources to become a part of our official Grafana provider once this project becomes more mature. At this time, we are not planning to create a migration path for data sources created with the `schemas` provider when they are merged into the `grafana` provider. Also, this work is subject to signficant changes as we iterate towards that level of quality. 14 | 15 | ## Maturity 16 | 17 | Grafana Labs defines experimental features as follows: 18 | 19 | > Projects and features in the Experimental stage are supported only by the Engineering 20 | teams; on-call support is not available. Documentation is either limited or not provided 21 | outside of code comments. No SLA is provided. 22 | > 23 | > Experimental projects or features are primarily intended for open source engineers who 24 | want to participate in ensuring systems stability, and to gain consensus and approval 25 | for open source governance projects. 26 | > 27 | > Projects and features in the Experimental phase are not meant to be used in production 28 | environments, and the risks are unknown/high. 29 | 30 | ## Example usage 31 | 32 | Configure the [Grafana Terraform Provider](https://registry.terraform.io/providers/grafana/grafana/latest) to access your Grafana instance (see [documentation](https://grafana.com/docs/grafana-cloud/infrastructure-as-code/terraform/)). Then use this Grafana Schemas Terraform provider to create your dashboards. 33 | 34 | ``` 35 | terraform { 36 | required_providers { 37 | schemas = { 38 | source = "grafana/schemas" 39 | version = "0.1.0" 40 | } 41 | grafana = { 42 | source = "grafana/grafana" 43 | version = "1.36.1" 44 | } 45 | } 46 | } 47 | provider "grafana" { 48 | url = "http://localhost:3000" 49 | auth = "admin:admin" 50 | } 51 | resource "grafana_dashboard" "example" { 52 | config_json = data.schemas_core_dashboard.my_dashboard.rendered_json 53 | } 54 | data "schemas_core_dashboard" "my_dashboard" { 55 | title = "My Dashboard" 56 | time = { 57 | from = "now-1h" 58 | } 59 | panels = [ 60 | data.schemas_panel_stat.my_panel.rendered_json, 61 | ] 62 | } 63 | data "schemas_panel_stat" "my_panel" { 64 | title = "My Panel" 65 | grid_pos = { 66 | h = 4 67 | w = 6 68 | x = 0 69 | y = 0 70 | } 71 | } 72 | ``` -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | - Using welcoming and inclusive language 12 | - Being respectful of differing viewpoints and experiences 13 | - Gracefully accepting constructive criticism 14 | - Focusing on what is best for the community 15 | - Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | - Trolling, insulting/derogatory comments, and personal or political attacks 21 | - Public or private harassment 22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | - Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at conduct@grafana.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/types/node.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "cuelang.org/go/cue" 8 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf/internal/utils" 9 | ) 10 | 11 | type Node struct { 12 | Name string 13 | Kind cue.Kind 14 | SubKind cue.Kind // For list only, kind of its elements 15 | IsMap bool 16 | IsDisjunction bool 17 | Optional bool 18 | Default string 19 | Doc string 20 | Children []Node 21 | Parent *Node 22 | DisjunctionKinds []cue.Kind 23 | } 24 | 25 | func (n *Node) TerraformModelField(structName string) string { 26 | kind := kindMappings[n.Kind] 27 | subKind := kindMappings[n.SubKind] 28 | typeStr := "" 29 | switch true { 30 | case n.Kind == cue.ListKind && n.SubKind == cue.StructKind: 31 | typeStr = "[]" + structName + "_" + utils.Title(n.Name) 32 | case n.Kind == cue.ListKind && subKind != nil: 33 | typeStr = "types.List" 34 | case n.Kind == cue.StructKind: 35 | if n.IsMap { 36 | typeStr = "map[string]" 37 | } 38 | typeStr += structName + "_" + utils.Title(n.Name) 39 | if n.Optional { 40 | typeStr = "*" + typeStr 41 | } 42 | default: 43 | typeStr = "types." + kind.terraformType 44 | } 45 | 46 | return fmt.Sprintf("%s %s `tfsdk:\"%s\"`", utils.ToCamelCase(n.Name), typeStr, utils.ToSnakeCase(n.Name)) 47 | } 48 | 49 | func (n *Node) JSONModelField() string { 50 | kind := kindMappings[n.Kind] 51 | subKind := kindMappings[n.SubKind] 52 | golangType := "" 53 | switch true { 54 | case n.Kind == cue.ListKind && n.SubKind == cue.StructKind: 55 | golangType = "[]interface{}" 56 | case n.Kind == cue.ListKind && subKind != nil: 57 | golangType = "[]" + subKind.golangType 58 | case n.Kind == cue.StructKind || len(n.DisjunctionKinds) > 0: 59 | golangType = "interface{}" 60 | default: 61 | golangType = kind.golangType 62 | } 63 | 64 | omitStr := "" 65 | if n.Optional { 66 | if !strings.HasPrefix(golangType, "[]") && golangType != "interface{}" { 67 | golangType = "*" + golangType 68 | } 69 | omitStr = ",omitempty" 70 | } 71 | 72 | return fmt.Sprintf("%s %s `json:\"%s%s\"`", utils.ToCamelCase(n.Name), golangType, n.Name, omitStr) 73 | } 74 | 75 | func (n *Node) TerraformType() string { 76 | if kindMappings[n.Kind] == nil { 77 | return "" 78 | } 79 | 80 | return kindMappings[n.Kind].terraformType 81 | } 82 | 83 | func (n *Node) SubTerraformType() string { 84 | if kindMappings[n.SubKind] == nil { 85 | return "" 86 | } 87 | 88 | return kindMappings[n.SubKind].terraformType 89 | } 90 | 91 | func (n *Node) subGolangType() string { 92 | if kindMappings[n.SubKind] == nil { 93 | return "" 94 | } 95 | 96 | return kindMappings[n.SubKind].golangType 97 | } 98 | 99 | func (n *Node) terraformFunc() string { 100 | if kindMappings[n.Kind] == nil { 101 | return "" 102 | } 103 | 104 | terraformFunc := kindMappings[n.Kind].terraformFunc 105 | if n.Optional { 106 | return terraformFunc + "Pointer()" 107 | } 108 | 109 | return terraformFunc + "()" 110 | } 111 | 112 | func (n *Node) subTerraformFunc() string { 113 | if kindMappings[n.SubKind] == nil { 114 | return "" 115 | } 116 | 117 | return kindMappings[n.SubKind].terraformFunc + "()" 118 | } 119 | 120 | func (n *Node) IsGenerated() bool { 121 | return kindMappings[n.Kind] != nil || 122 | (n.Kind == cue.ListKind && kindMappings[n.SubKind] != nil) || 123 | (n.Kind == cue.ListKind && n.SubKind == cue.StructKind) || 124 | (n.Kind == cue.StructKind) 125 | } 126 | -------------------------------------------------------------------------------- /examples/schemas_core_dashboard/prometheus/dashboard.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | schemas = { 4 | source = "grafana/schemas" 5 | version = "0.1.0" 6 | } 7 | grafana = { 8 | source = "grafana/grafana" 9 | version = "1.36.1" 10 | } 11 | } 12 | } 13 | 14 | provider "grafana" { 15 | url = "http://localhost:3000" 16 | auth = "admin:admin" 17 | } 18 | 19 | resource "grafana_dashboard" "example" { 20 | config_json = data.schemas_core_dashboard.prometheus_dashboard.rendered_json 21 | } 22 | 23 | resource "grafana_data_source" "prometheus" { 24 | type = "prometheus" 25 | name = "Prometheus" 26 | url = "http://localhost:9090" 27 | basic_auth_enabled = false 28 | } 29 | 30 | data "schemas_core_dashboard" "prometheus_dashboard" { 31 | title = "Prometheus Dashboard" 32 | 33 | time = { 34 | from = "now-1h" 35 | } 36 | 37 | panels = [ 38 | data.schemas_panel_stat.disk.rendered_json, 39 | data.schemas_panel_time_series.cpu_usage.rendered_json, 40 | data.schemas_panel_time_series.disk_usage.rendered_json, 41 | ] 42 | } 43 | 44 | data "schemas_panel_stat" "disk" { 45 | title = "Disk" 46 | 47 | datasource = { 48 | uid = resource.grafana_data_source.prometheus.uid 49 | type = resource.grafana_data_source.prometheus.type 50 | } 51 | 52 | grid_pos = { 53 | h = 4 54 | w = 6 55 | x = 8 56 | y = 0 57 | } 58 | 59 | field_config = { 60 | defaults = { 61 | unit = "percentunit" 62 | } 63 | } 64 | 65 | targets = [ 66 | data.schemas_query_prometheus.disk_target.rendered_json 67 | ] 68 | } 69 | 70 | data "schemas_query_prometheus" "cores_target" { 71 | expr = "count(count by(cpu)(node_cpu_seconds_total))" 72 | format = "time_series" 73 | ref_id = "A" 74 | } 75 | 76 | data "schemas_panel_time_series" "cpu_usage" { 77 | title = "CPU usage" 78 | 79 | datasource = { 80 | uid = resource.grafana_data_source.prometheus.uid 81 | type = resource.grafana_data_source.prometheus.type 82 | } 83 | 84 | grid_pos = { 85 | h = 8 86 | w = 12 87 | x = 0 88 | y = 4 89 | } 90 | 91 | options = { 92 | legend = { 93 | calcs = [ 94 | "mean", 95 | "lastNotNull", 96 | "max", 97 | "min" 98 | ] 99 | display_mode = "table" 100 | placement = "bottom" 101 | show_legend = true 102 | } 103 | } 104 | 105 | targets = [ 106 | data.schemas_query_prometheus.cpu_target.rendered_json 107 | ] 108 | } 109 | 110 | data "schemas_query_prometheus" "cpu_target" { 111 | expr = "sum by(mode) (irate(node_cpu_seconds_total{mode!=\"idle\"}[5m]))" 112 | format = "time_series" 113 | ref_id = "A" 114 | } 115 | 116 | data "schemas_panel_time_series" "disk_usage" { 117 | title = "Disk I/O utilization" 118 | 119 | datasource = { 120 | uid = resource.grafana_data_source.prometheus.uid 121 | type = resource.grafana_data_source.prometheus.type 122 | } 123 | 124 | grid_pos = { 125 | h = 8 126 | w = 12 127 | x = 12 128 | y = 4 129 | } 130 | 131 | options = { 132 | legend = { 133 | calcs = [ 134 | "mean", 135 | "lastNotNull", 136 | "max", 137 | "min" 138 | ] 139 | display_mode = "table" 140 | placement = "bottom" 141 | show_legend = true 142 | } 143 | } 144 | 145 | field_config = { 146 | defaults = { 147 | unit = "percentunit" 148 | min = 0 149 | max = 1 150 | } 151 | } 152 | 153 | targets = [ 154 | data.schemas_query_prometheus.disk_target.rendered_json 155 | ] 156 | } 157 | 158 | data "schemas_query_prometheus" "disk_target" { 159 | expr = "sum(irate(node_disk_io_time_seconds_total[5m]))" 160 | format = "time_series" 161 | ref_id = "A" 162 | } 163 | -------------------------------------------------------------------------------- /docs/data-sources/query_test_data.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_query_test_data Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_query_test_data (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Required 19 | 20 | - `ref_id` (String) A unique identifier for the query within the list of targets. 21 | In server side expressions, the refId is used as a variable name to identify results. 22 | By default, the UI will assign A->Z; however setting meaningful names may be useful. 23 | 24 | ### Optional 25 | 26 | - `alias` (String) 27 | - `channel` (String) 28 | - `csv_content` (String) 29 | - `csv_file_name` (String) 30 | - `csv_wave` (Attributes List) (see [below for nested schema](#nestedatt--csv_wave)) 31 | - `drop_percent` (Number) Drop percentage (the chance we will lose a point 0-100) 32 | - `error_type` (String) 33 | - `hide` (Boolean) true if query is disabled (ie should not be returned to the dashboard) 34 | Note this does not always imply that the query should not be executed since 35 | the results from a hidden query may be used as the input to other queries (SSE etc) 36 | - `labels` (String) 37 | - `level_column` (Boolean) 38 | - `lines` (Number) 39 | - `nodes` (Attributes) (see [below for nested schema](#nestedatt--nodes)) 40 | - `pulse_wave` (Attributes) (see [below for nested schema](#nestedatt--pulse_wave)) 41 | - `query_type` (String) Specify the query flavor 42 | TODO make this required and give it a default 43 | - `raw_frame_content` (String) 44 | - `scenario_id` (String) Defaults to "random_walk". 45 | - `series_count` (Number) 46 | - `sim` (Attributes) (see [below for nested schema](#nestedatt--sim)) 47 | - `span_count` (Number) 48 | - `stream` (Attributes) (see [below for nested schema](#nestedatt--stream)) 49 | - `string_input` (String) 50 | - `usa` (Attributes) (see [below for nested schema](#nestedatt--usa)) 51 | 52 | ### Read-Only 53 | 54 | - `rendered_json` (String) This datasource rendered as JSON 55 | 56 | 57 | ### Nested Schema for `csv_wave` 58 | 59 | Optional: 60 | 61 | - `labels` (String) 62 | - `name` (String) 63 | - `time_step` (Number) 64 | - `values_csv` (String) 65 | 66 | 67 | 68 | ### Nested Schema for `nodes` 69 | 70 | Optional: 71 | 72 | - `count` (Number) 73 | - `type` (String) 74 | 75 | 76 | 77 | ### Nested Schema for `pulse_wave` 78 | 79 | Optional: 80 | 81 | - `off_count` (Number) 82 | - `off_value` (Number) 83 | - `on_count` (Number) 84 | - `on_value` (Number) 85 | - `time_step` (Number) 86 | 87 | 88 | 89 | ### Nested Schema for `sim` 90 | 91 | Optional: 92 | 93 | - `config` (Attributes) (see [below for nested schema](#nestedatt--sim--config)) 94 | - `key` (Attributes) (see [below for nested schema](#nestedatt--sim--key)) 95 | - `last` (Boolean) 96 | - `stream` (Boolean) 97 | 98 | 99 | ### Nested Schema for `sim.config` 100 | 101 | 102 | 103 | ### Nested Schema for `sim.key` 104 | 105 | Required: 106 | 107 | - `tick` (Number) 108 | - `type` (String) 109 | 110 | Optional: 111 | 112 | - `uid` (String) 113 | 114 | 115 | 116 | 117 | ### Nested Schema for `stream` 118 | 119 | Required: 120 | 121 | - `noise` (Number) 122 | - `speed` (Number) 123 | - `spread` (Number) 124 | - `type` (String) 125 | 126 | Optional: 127 | 128 | - `bands` (Number) 129 | - `url` (String) 130 | 131 | 132 | 133 | ### Nested Schema for `usa` 134 | 135 | Optional: 136 | 137 | - `fields` (List of String) 138 | - `mode` (String) 139 | - `period` (String) 140 | - `states` (List of String) 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grafana Schemas Terraform Provider (experimental) 2 | 3 | This is a generated provider to manage Grafana dashboards. 4 | 5 | The code in this repository should be considered experimental. It comes with no support, but we are keen to receive feedback on the product and suggestions on how to improve it, though we cannot commit to resolution of any particular issue. No SLAs are available. It is not meant to be used in production environments, and the risks are unknown/high. 6 | 7 | Our goal is for these generated data sources to become a part of our official Grafana provider once this project becomes more mature. At this time, we are not planning to create a migration path for data sources created with the `schemas` provider when they are merged into the `grafana` provider. Also, this work is subject to signficant changes as we iterate towards that level of quality. 8 | 9 | ## Requirements 10 | 11 | - [Terraform](https://www.terraform.io/downloads.html) >= 1.0 12 | 13 | ## Maturity 14 | 15 | Grafana Labs defines experimental features as follows: 16 | 17 | > Projects and features in the Experimental stage are supported only by the Engineering 18 | teams; on-call support is not available. Documentation is either limited or not provided 19 | outside of code comments. No SLA is provided. 20 | > 21 | > Experimental projects or features are primarily intended for open source engineers who 22 | want to participate in ensuring systems stability, and to gain consensus and approval 23 | for open source governance projects. 24 | > 25 | > Projects and features in the Experimental phase are not meant to be used in production 26 | environments, and the risks are unknown/high. 27 | 28 | ## Usage 29 | 30 | This provider should be used with the [Grafana Terraform Provider](https://registry.terraform.io/providers/grafana/grafana/latest). It is generated from the [CUE schemas](https://github.com/grafana/grafana/blob/main/kinds/dashboard/dashboard_kind.cue) defined in the Grafana repository to ensure it stays up-to-date. 31 | 32 | Configure the [Grafana Terraform Provider](https://registry.terraform.io/providers/grafana/grafana/latest) to access your Grafana instance (see [documentation](https://grafana.com/docs/grafana-cloud/infrastructure-as-code/terraform/)). Then use this Grafana Schemas Terraform provider to create your dashboards. 33 | 34 | ``` 35 | terraform { 36 | required_providers { 37 | schemas = { 38 | source = "grafana/schemas" 39 | version = "0.1.0" 40 | } 41 | grafana = { 42 | source = "grafana/grafana" 43 | version = "1.36.1" 44 | } 45 | } 46 | } 47 | 48 | provider "grafana" { 49 | url = "http://localhost:3000" 50 | auth = "admin:admin" 51 | } 52 | 53 | data "schemas_core_dashboard" "my_dashboard" { 54 | title = "My Dashboard" 55 | 56 | time = { 57 | from = "now-1h" 58 | } 59 | 60 | panels = [ 61 | data.schemas_panel_stat.my_panel.rendered_json, 62 | ] 63 | } 64 | 65 | data "schemas_panel_stat" "my_panel" { 66 | title = "My Panel" 67 | 68 | grid_pos = { 69 | h = 4 70 | w = 6 71 | x = 0 72 | y = 0 73 | } 74 | } 75 | 76 | resource "grafana_dashboard" "example" { 77 | config_json = data.schemas_core_dashboard.my_dashboard.rendered_json 78 | } 79 | ``` 80 | 81 | More examples are available in the ["examples"](https://github.com/grafana/terraform-provider-schemas/tree/main/examples/data-sources/schemas_core_dashboard) folder. 82 | 83 | ## Development 84 | 85 | ### Requirements 86 | 87 | - [Terraform](https://www.terraform.io/downloads.html) >= 1.0 88 | - [Go](https://golang.org/doc/install) >= 1.19 89 | 90 | ### Building The Provider 91 | 92 | 1. Clone the repository 93 | 1. Enter the repository directory 94 | 1. Build the provider using the Go `install` command: 95 | 96 | ```shell 97 | go install 98 | ``` 99 | 100 | If you want to re-generate the provider, use the `make generate` command. 101 | 102 | ### Adding Dependencies 103 | 104 | This provider uses [Go modules](https://github.com/golang/go/wiki/Modules). 105 | Please see the Go documentation for the most up to date information about using Go modules. 106 | 107 | To add a new dependency `github.com/author/dependency` to your Terraform provider: 108 | 109 | ```shell 110 | go get github.com/author/dependency 111 | go mod tidy 112 | ``` 113 | 114 | Then commit the changes to `go.mod` and `go.sum`. 115 | 116 | ### Developing the Provider 117 | 118 | If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (see [Requirements](#requirements) above). 119 | 120 | To compile the provider, run `go install`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory. 121 | 122 | To generate or update documentation, run `go generate`. 123 | 124 | In order to run the full suite of Acceptance tests, run `make testacc`. 125 | 126 | *Note:* Acceptance tests create real resources, and often cost money to run. 127 | 128 | ```shell 129 | make testacc 130 | ``` 131 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/templates/datasource.tmpl: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | 7 | "github.com/hashicorp/terraform-plugin-framework/attr" 8 | "github.com/hashicorp/terraform-plugin-framework/datasource" 9 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema" 10 | "github.com/hashicorp/terraform-plugin-framework/diag" 11 | "github.com/hashicorp/terraform-plugin-framework/types" 12 | "github.com/hashicorp/terraform-plugin-log/tflog" 13 | ) 14 | 15 | // Ensure that the imports are used to avoid compiler errors. 16 | var _ attr.Value 17 | var _ diag.Diagnostic 18 | 19 | // Ensure provider defined types fully satisfy framework interfaces. 20 | var ( 21 | _ datasource.DataSource = &{{.StructName}}{} 22 | _ datasource.DataSourceWithConfigure = &{{.StructName}}{} 23 | ) 24 | 25 | func New{{.StructName}}() datasource.DataSource { 26 | return &{{.StructName}}{} 27 | } 28 | 29 | // {{.StructName}} defines the data source implementation. 30 | type {{.StructName}} struct {} 31 | 32 | {{ .Models }} 33 | 34 | func (d *{{.StructName}}) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { 35 | resp.TypeName = req.ProviderTypeName + "_{{.Name}}" 36 | } 37 | 38 | func (d *{{.StructName}}) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { 39 | resp.Schema = schema.Schema{ 40 | // This description is used by the documentation generator and the language server. 41 | MarkdownDescription: "{{.Description}}", 42 | Attributes: map[string]schema.Attribute{ 43 | {{.SchemaAttributes}} 44 | "rendered_json": schema.StringAttribute{ 45 | Computed: true, 46 | MarkdownDescription: "This datasource rendered as JSON", 47 | }, 48 | }, 49 | } 50 | } 51 | 52 | func (d *{{.StructName}}) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {} 53 | 54 | func (d *{{.StructName}}) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { 55 | var data {{.StructName}}Model 56 | 57 | // Read Terraform configuration data into the model 58 | resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) 59 | 60 | if resp.Diagnostics.HasError() { 61 | return 62 | } 63 | 64 | JSONConfig, err := json.Marshal(data) 65 | if err != nil { 66 | resp.Diagnostics.AddError("JSON marshalling error", err.Error()) 67 | return 68 | } 69 | 70 | {{ if eq .StructName "CoreDashboardDataSource" }} 71 | // fix up the panel Attribute 72 | // Read into a map[string]interface{} and then marshal it back to JSON 73 | // This is a workaround for the fact that the panel attribute should be a list of maps but is a list of json strings 74 | dataMap := make(map[string]interface{}) 75 | err = json.Unmarshal(JSONConfig, &dataMap) 76 | if err != nil { 77 | resp.Diagnostics.AddError("error unmarshalling config into Go map", err.Error()) 78 | return 79 | } 80 | panels := data.Panels.Elements() 81 | panelsMaps := make([]map[string]interface{}, len(panels)) 82 | for i, panel := range panels { 83 | panelMap := make(map[string]interface{}) 84 | err = json.Unmarshal([]byte(panel.(types.String).ValueString()), &panelMap) 85 | if err != nil { 86 | resp.Diagnostics.AddError("error unmarshalling panel into go map", err.Error()) 87 | return 88 | } 89 | panelsMaps[i] = panelMap 90 | } 91 | 92 | dataMap["panels"] = panelsMaps 93 | JSONConfig, err = json.MarshalIndent(dataMap, "", " ") 94 | if err != nil { 95 | resp.Diagnostics.AddError("error marshalling go map into json", err.Error()) 96 | return 97 | } 98 | {{ end }} 99 | 100 | {{ if startsWith .StructName "Panel" }} 101 | // fix up the targets Attribute 102 | // Read into a map[string]interface{} and then marshal it back to JSON 103 | // This is a workaround for the fact that the targets attribute should be a list of maps but is a list of json strings 104 | dataMap := make(map[string]interface{}) 105 | err = json.Unmarshal(JSONConfig, &dataMap) 106 | if err != nil { 107 | resp.Diagnostics.AddError("error unmarshalling config into Go map", err.Error()) 108 | return 109 | } 110 | targets := data.Targets.Elements() 111 | targetsMaps := make([]map[string]interface{}, len(targets)) 112 | for i, target := range targets { 113 | targetMap := make(map[string]interface{}) 114 | err = json.Unmarshal([]byte(target.(types.String).ValueString()), &targetMap) 115 | if err != nil { 116 | resp.Diagnostics.AddError("error unmarshalling target into go map", err.Error()) 117 | return 118 | } 119 | targetsMaps[i] = targetMap 120 | } 121 | 122 | dataMap["targets"] = targetsMaps 123 | JSONConfig, err = json.MarshalIndent(dataMap, "", " ") 124 | if err != nil { 125 | resp.Diagnostics.AddError("error marshalling go map into json", err.Error()) 126 | return 127 | } 128 | {{ end }} 129 | 130 | // Not sure about that 131 | data.RenderedJSON = types.StringValue(string(JSONConfig)) 132 | 133 | // Write logs using the tflog package 134 | // Documentation: https://terraform.io/plugin/log 135 | tflog.Trace(ctx, "read a data source") 136 | 137 | // Save data into Terraform state 138 | resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) 139 | } 140 | -------------------------------------------------------------------------------- /internal/provider/datasource_query_parca_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated - EDITING IS FUTILE. DO NOT EDIT. 2 | // 3 | // Generated by pipeline: 4 | // terraform 5 | // Using jennies: 6 | // TerraformDataSourceJenny 7 | // ComposableLatestMajorsOrXJenny 8 | // 9 | // Run 'go generate ./' from repository root to regenerate. 10 | 11 | package provider 12 | 13 | import ( 14 | "context" 15 | "encoding/json" 16 | 17 | "github.com/hashicorp/terraform-plugin-framework/attr" 18 | "github.com/hashicorp/terraform-plugin-framework/datasource" 19 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema" 20 | "github.com/hashicorp/terraform-plugin-framework/diag" 21 | "github.com/hashicorp/terraform-plugin-framework/types" 22 | "github.com/hashicorp/terraform-plugin-log/tflog" 23 | ) 24 | 25 | // Ensure that the imports are used to avoid compiler errors. 26 | var _ attr.Value 27 | var _ diag.Diagnostic 28 | 29 | // Ensure provider defined types fully satisfy framework interfaces. 30 | var ( 31 | _ datasource.DataSource = &QueryParcaDataSource{} 32 | _ datasource.DataSourceWithConfigure = &QueryParcaDataSource{} 33 | ) 34 | 35 | func NewQueryParcaDataSource() datasource.DataSource { 36 | return &QueryParcaDataSource{} 37 | } 38 | 39 | // QueryParcaDataSource defines the data source implementation. 40 | type QueryParcaDataSource struct{} 41 | 42 | type QueryParcaDataSourceModel struct { 43 | RenderedJSON types.String `tfsdk:"rendered_json"` 44 | LabelSelector types.String `tfsdk:"label_selector"` 45 | ProfileTypeId types.String `tfsdk:"profile_type_id"` 46 | RefId types.String `tfsdk:"ref_id"` 47 | Hide types.Bool `tfsdk:"hide"` 48 | QueryType types.String `tfsdk:"query_type"` 49 | } 50 | 51 | func (m QueryParcaDataSourceModel) MarshalJSON() ([]byte, error) { 52 | type jsonQueryParcaDataSourceModel struct { 53 | LabelSelector string `json:"labelSelector"` 54 | ProfileTypeId string `json:"profileTypeId"` 55 | RefId string `json:"refId"` 56 | Hide *bool `json:"hide,omitempty"` 57 | QueryType *string `json:"queryType,omitempty"` 58 | } 59 | 60 | m = m.ApplyDefaults() 61 | attr_labelselector := m.LabelSelector.ValueString() 62 | attr_profiletypeid := m.ProfileTypeId.ValueString() 63 | attr_refid := m.RefId.ValueString() 64 | attr_hide := m.Hide.ValueBoolPointer() 65 | attr_querytype := m.QueryType.ValueStringPointer() 66 | 67 | model := &jsonQueryParcaDataSourceModel{ 68 | LabelSelector: attr_labelselector, 69 | ProfileTypeId: attr_profiletypeid, 70 | RefId: attr_refid, 71 | Hide: attr_hide, 72 | QueryType: attr_querytype, 73 | } 74 | return json.Marshal(model) 75 | } 76 | 77 | func (m QueryParcaDataSourceModel) ApplyDefaults() QueryParcaDataSourceModel { 78 | if m.LabelSelector.IsNull() { 79 | m.LabelSelector = types.StringValue(`{}`) 80 | } 81 | return m 82 | } 83 | 84 | func (d *QueryParcaDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { 85 | resp.TypeName = req.ProviderTypeName + "_query_parca" 86 | } 87 | 88 | func (d *QueryParcaDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { 89 | resp.Schema = schema.Schema{ 90 | // This description is used by the documentation generator and the language server. 91 | MarkdownDescription: "", 92 | Attributes: map[string]schema.Attribute{ 93 | "label_selector": schema.StringAttribute{ 94 | MarkdownDescription: `Specifies the query label selectors. Defaults to "{}".`, 95 | Computed: true, 96 | Optional: true, 97 | Required: false, 98 | }, 99 | "profile_type_id": schema.StringAttribute{ 100 | MarkdownDescription: `Specifies the type of profile to query.`, 101 | Computed: false, 102 | Optional: false, 103 | Required: true, 104 | }, 105 | "ref_id": schema.StringAttribute{ 106 | MarkdownDescription: `A unique identifier for the query within the list of targets. 107 | In server side expressions, the refId is used as a variable name to identify results. 108 | By default, the UI will assign A->Z; however setting meaningful names may be useful.`, 109 | Computed: false, 110 | Optional: false, 111 | Required: true, 112 | }, 113 | "hide": schema.BoolAttribute{ 114 | MarkdownDescription: `true if query is disabled (ie should not be returned to the dashboard) 115 | Note this does not always imply that the query should not be executed since 116 | the results from a hidden query may be used as the input to other queries (SSE etc)`, 117 | Computed: false, 118 | Optional: true, 119 | Required: false, 120 | }, 121 | "query_type": schema.StringAttribute{ 122 | MarkdownDescription: `Specify the query flavor 123 | TODO make this required and give it a default`, 124 | Computed: false, 125 | Optional: true, 126 | Required: false, 127 | }, 128 | 129 | "rendered_json": schema.StringAttribute{ 130 | Computed: true, 131 | MarkdownDescription: "This datasource rendered as JSON", 132 | }, 133 | }, 134 | } 135 | } 136 | 137 | func (d *QueryParcaDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { 138 | } 139 | 140 | func (d *QueryParcaDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { 141 | var data QueryParcaDataSourceModel 142 | 143 | // Read Terraform configuration data into the model 144 | resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) 145 | 146 | if resp.Diagnostics.HasError() { 147 | return 148 | } 149 | 150 | JSONConfig, err := json.Marshal(data) 151 | if err != nil { 152 | resp.Diagnostics.AddError("JSON marshalling error", err.Error()) 153 | return 154 | } 155 | 156 | // Not sure about that 157 | data.RenderedJSON = types.StringValue(string(JSONConfig)) 158 | 159 | // Write logs using the tflog package 160 | // Documentation: https://terraform.io/plugin/log 161 | tflog.Trace(ctx, "read a data source") 162 | 163 | // Save data into Terraform state 164 | resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) 165 | } 166 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/grafana/terraform-provider-schemas 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/grafana/thema v0.0.0-20230615161902-b6e21996aef8 7 | github.com/hashicorp/terraform-plugin-docs v0.16.0 8 | github.com/hashicorp/terraform-plugin-framework v1.4.2 9 | github.com/hashicorp/terraform-plugin-log v0.9.0 10 | ) 11 | 12 | require ( 13 | github.com/Masterminds/goutils v1.1.1 // indirect 14 | github.com/Masterminds/semver/v3 v3.1.1 // indirect 15 | github.com/Masterminds/sprig/v3 v3.2.2 // indirect 16 | github.com/ProtonMail/go-crypto v0.0.0-20230426101702-58e86b294756 // indirect 17 | github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect 18 | github.com/armon/go-radix v1.0.0 // indirect 19 | github.com/bgentry/speakeasy v0.1.0 // indirect 20 | github.com/cloudflare/circl v1.3.3 // indirect 21 | github.com/cockroachdb/errors v1.9.1 // indirect 22 | github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f // indirect 23 | github.com/cockroachdb/redact v1.1.3 // indirect 24 | github.com/dave/dst v0.27.2 // indirect 25 | github.com/getkin/kin-openapi v0.115.0 // indirect 26 | github.com/getsentry/sentry-go v0.12.0 // indirect 27 | github.com/go-logr/logr v1.2.4 // indirect 28 | github.com/go-openapi/jsonpointer v0.19.6 // indirect 29 | github.com/go-openapi/swag v0.22.3 // indirect 30 | github.com/google/gofuzz v1.2.0 // indirect 31 | github.com/google/wire v0.5.0 // indirect 32 | github.com/grafana/cuetsy v0.1.9 // indirect 33 | github.com/hashicorp/go-checkpoint v0.5.0 // indirect 34 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 35 | github.com/hashicorp/go-version v1.6.0 // indirect 36 | github.com/hashicorp/hc-install v0.5.2 // indirect 37 | github.com/hashicorp/terraform-exec v0.18.1 // indirect 38 | github.com/hashicorp/terraform-json v0.17.1 // indirect 39 | github.com/hashicorp/terraform-plugin-go v0.19.0 // indirect 40 | github.com/huandu/xstrings v1.3.2 // indirect 41 | github.com/imdario/mergo v0.3.13 // indirect 42 | github.com/invopop/yaml v0.2.0 // indirect 43 | github.com/josharian/intern v1.0.0 // indirect 44 | github.com/json-iterator/go v1.1.12 // indirect 45 | github.com/labstack/echo/v4 v4.10.2 // indirect 46 | github.com/labstack/gommon v0.4.0 // indirect 47 | github.com/mailru/easyjson v0.7.7 // indirect 48 | github.com/mattn/go-runewidth v0.0.14 // indirect 49 | github.com/mitchellh/cli v1.1.5 // indirect 50 | github.com/mitchellh/copystructure v1.2.0 // indirect 51 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 52 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 53 | github.com/modern-go/reflect2 v1.0.2 // indirect 54 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect 55 | github.com/olekukonko/tablewriter v0.0.5 // indirect 56 | github.com/perimeterx/marshmallow v1.1.4 // indirect 57 | github.com/posener/complete v1.2.3 // indirect 58 | github.com/rivo/uniseg v0.4.4 // indirect 59 | github.com/russross/blackfriday v1.6.0 // indirect 60 | github.com/shopspring/decimal v1.3.1 // indirect 61 | github.com/spf13/cast v1.5.0 // indirect 62 | github.com/valyala/bytebufferpool v1.0.0 // indirect 63 | github.com/valyala/fasttemplate v1.2.2 // indirect 64 | github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect 65 | github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect 66 | github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect 67 | github.com/xlab/treeprint v1.2.0 // indirect 68 | github.com/zclconf/go-cty v1.13.2 // indirect 69 | golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect 70 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect 71 | gopkg.in/inf.v0 v0.9.1 // indirect 72 | gopkg.in/yaml.v2 v2.4.0 // indirect 73 | k8s.io/apimachinery v0.27.2 // indirect 74 | k8s.io/klog/v2 v2.100.1 // indirect 75 | k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect 76 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 77 | sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect 78 | ) 79 | 80 | require ( 81 | github.com/google/go-cmp v0.6.0 // indirect 82 | github.com/grafana/grafana v1.9.2-0.20230706143427-a8d2a9ae2ba1 83 | github.com/yalue/merged_fs v1.2.3 // indirect 84 | golang.org/x/sync v0.4.0 // indirect 85 | ) 86 | 87 | require ( 88 | cuelang.org/go v0.6.0-0.dev 89 | github.com/cockroachdb/apd/v2 v2.0.2 // indirect 90 | github.com/emicklei/proto v1.11.2 // indirect 91 | github.com/fatih/color v1.15.0 // indirect 92 | github.com/gogo/protobuf v1.3.2 // indirect 93 | github.com/golang/protobuf v1.5.3 // indirect 94 | github.com/google/uuid v1.3.0 // indirect 95 | github.com/grafana/codejen v0.0.4-0.20221122220907-a5e7cc5407b3 96 | github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482 97 | github.com/hashicorp/errwrap v1.1.0 // indirect 98 | github.com/hashicorp/go-hclog v1.5.0 // indirect 99 | github.com/hashicorp/go-multierror v1.1.1 // indirect 100 | github.com/hashicorp/go-plugin v1.5.1 // indirect 101 | github.com/hashicorp/go-uuid v1.0.3 // indirect 102 | github.com/hashicorp/terraform-registry-address v0.2.2 // indirect 103 | github.com/hashicorp/terraform-svchost v0.1.1 // indirect 104 | github.com/hashicorp/yamux v0.1.1 // indirect 105 | github.com/kr/pretty v0.3.1 // indirect 106 | github.com/kr/text v0.2.0 // indirect 107 | github.com/mattn/go-colorable v0.1.13 // indirect 108 | github.com/mattn/go-isatty v0.0.19 // indirect 109 | github.com/mitchellh/go-testing-interface v1.14.1 // indirect 110 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 111 | github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect 112 | github.com/oklog/run v1.1.0 // indirect 113 | github.com/pkg/errors v0.9.1 // indirect 114 | github.com/protocolbuffers/txtpbfmt v0.0.0-20230412060525-fa9f017c0ded // indirect 115 | github.com/rogpeppe/go-internal v1.10.0 // indirect 116 | golang.org/x/crypto v0.14.0 // indirect 117 | golang.org/x/mod v0.13.0 // indirect 118 | golang.org/x/net v0.17.0 // indirect 119 | golang.org/x/sys v0.13.0 // indirect 120 | golang.org/x/text v0.13.0 121 | golang.org/x/tools v0.14.0 122 | google.golang.org/grpc v1.57.0 // indirect 123 | google.golang.org/protobuf v1.31.0 // indirect 124 | gopkg.in/yaml.v3 v3.0.1 // indirect 125 | ) 126 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/types/model.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "cuelang.org/go/cue" 8 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf/internal/utils" 9 | ) 10 | 11 | type Model struct { 12 | Name string 13 | IsDisjunction bool 14 | Nodes []Node 15 | Nested bool 16 | } 17 | 18 | // terraformModel generates the Terraform SDK model. 19 | func (s *Model) terraformModel() string { 20 | fields := make([]string, 0) 21 | if !s.Nested { 22 | fields = append(fields, "RenderedJSON types.String `tfsdk:\"rendered_json\"`") 23 | } 24 | 25 | for _, node := range s.Nodes { 26 | if !node.IsGenerated() { 27 | continue 28 | } 29 | fields = append(fields, node.TerraformModelField(s.Name)) 30 | } 31 | 32 | return fmt.Sprintf(`type %s struct { 33 | %s 34 | } 35 | `, s.Name, strings.Join(fields, "\n")) 36 | } 37 | 38 | // jsonModel generates the JSON model used to convert the Terraform SDK model to JSON. 39 | func (s *Model) jsonModel() string { 40 | fields := make([]string, 0) 41 | for _, node := range s.Nodes { 42 | if !node.IsGenerated() { 43 | continue 44 | } 45 | fields = append(fields, node.JSONModelField()) 46 | } 47 | 48 | return fmt.Sprintf(`type json%s struct { 49 | %s 50 | } 51 | `, s.Name, strings.Join(fields, "\n")) 52 | } 53 | 54 | // generateToJSONFunction generates a function that converts the Terraform SDK model to the JSON model representation. 55 | func (s *Model) generateToJSONFunction() string { 56 | b := strings.Builder{} 57 | 58 | for _, node := range s.Nodes { 59 | if len(node.DisjunctionKinds) > 0 { 60 | b.WriteString(s.generateGetAttrFunction(node)) 61 | } 62 | } 63 | 64 | fmt.Fprintf(&b, "func (m %s) MarshalJSON() ([]byte, error) {\n", s.Name) 65 | if s.IsDisjunction { 66 | fmt.Fprintf(&b, "var json_%s interface{}\n", s.Name) 67 | } else { 68 | b.WriteString(s.jsonModel() + "\n") 69 | } 70 | b.WriteString("m = m.ApplyDefaults()\n") 71 | 72 | structLines := make([]string, 0) 73 | for _, node := range s.Nodes { 74 | if !node.IsGenerated() { 75 | continue 76 | } 77 | 78 | fieldName := utils.ToCamelCase(node.Name) 79 | varName := "attr_" + strings.ToLower(node.Name) 80 | if s.IsDisjunction { 81 | varName = "json_" + s.Name 82 | } 83 | funcString := node.terraformFunc() 84 | 85 | if node.Kind == cue.ListKind { 86 | subType := node.SubTerraformType() 87 | subTypeGolang := node.subGolangType() 88 | subTypeFunc := node.subTerraformFunc() 89 | if subType != "" { 90 | fmt.Fprintf(&b, " %s := []%s{}\n", varName, subTypeGolang) 91 | fmt.Fprintf(&b, " for _, v := range m.%s.Elements() {\n", fieldName) 92 | fmt.Fprintf(&b, " %s = append(%s, v.(types.%s).%s)\n", varName, varName, subType, subTypeFunc) 93 | b.WriteString(" }\n") 94 | } else if node.SubKind == cue.StructKind { 95 | fmt.Fprintf(&b, " %s := []interface{}{}\n", varName) 96 | fmt.Fprintf(&b, " for _, v := range m.%s {\n", fieldName) 97 | fmt.Fprintf(&b, " %s = append(%s, v)\n", varName, varName) 98 | b.WriteString(" }\n") 99 | } 100 | } else if node.Kind == cue.StructKind { 101 | if !s.IsDisjunction { 102 | fmt.Fprintf(&b, " var %s interface{}\n", varName) 103 | } 104 | if node.Optional { 105 | fmt.Fprintf(&b, " if m.%s != nil {\n", fieldName) 106 | fmt.Fprintf(&b, " %s = m.%s\n", varName, fieldName) 107 | b.WriteString(" }\n") 108 | } else { 109 | fmt.Fprintf(&b, " %s = m.%s\n", varName, fieldName) 110 | } 111 | } else if len(node.DisjunctionKinds) > 0 { 112 | fmt.Fprintf(&b, " %s := m.GetAttr%s()\n", varName, fieldName) 113 | } else if funcString != "" { 114 | fmt.Fprintf(&b, "%s := m.%s.%s\n", varName, fieldName, funcString) 115 | } 116 | 117 | structLines = append(structLines, fmt.Sprintf(" %s: %s,\n", fieldName, varName)) 118 | } 119 | 120 | if s.IsDisjunction { 121 | fmt.Fprintf(&b, ` 122 | 123 | return json.Marshal(json_%s) 124 | } 125 | 126 | `, s.Name) 127 | } else { 128 | fmt.Fprintf(&b, ` 129 | 130 | model := &json%s { 131 | %s 132 | } 133 | return json.Marshal(model) 134 | } 135 | 136 | `, s.Name, strings.Join(structLines, "")) 137 | } 138 | 139 | return b.String() 140 | } 141 | 142 | func (s *Model) generateGetAttrFunction(node Node) string { 143 | b := strings.Builder{} 144 | attrName := utils.ToCamelCase(node.Name) 145 | 146 | fmt.Fprintf(&b, "func (m %s) GetAttr%s() interface{} {\n", s.Name, attrName) 147 | b.WriteString("var attr interface{}\nvar err error\n\n") 148 | 149 | for _, kind := range node.DisjunctionKinds { 150 | switch kind { 151 | case cue.StructKind, cue.ListKind: 152 | fmt.Fprintf(&b, "err = json.Unmarshal([]byte(m.%s.ValueString()), &attr)", attrName) 153 | case cue.BoolKind: 154 | fmt.Fprintf(&b, "attr, err = strconv.ParseBool(m.%s.ValueString())", attrName) 155 | case cue.IntKind: 156 | fmt.Fprintf(&b, "attr, err = strconv.ParseInt(m.%s.ValueString(), 10, 64)", attrName) 157 | case cue.NumberKind, cue.FloatKind: 158 | fmt.Fprintf(&b, "attr, err = strconv.ParseFloat(m.%s.ValueString(), 64)", attrName) 159 | case cue.StringKind: 160 | continue 161 | } 162 | 163 | b.WriteString(` 164 | if err == nil { 165 | return attr 166 | } 167 | `) 168 | } 169 | fmt.Fprintf(&b, ` 170 | return m.%s.ValueString() 171 | } 172 | 173 | `, attrName) 174 | 175 | return b.String() 176 | } 177 | 178 | func (s *Model) generateDefaultsFunction() string { 179 | defaults := make([]string, 0) 180 | for _, node := range s.Nodes { 181 | kind := node.TerraformType() 182 | 183 | if kind != "" && node.Default != "" { 184 | defaults = append(defaults, fmt.Sprintf(`if m.%s.IsNull() { 185 | m.%s = types.%sValue(%s) 186 | }`, utils.ToCamelCase(node.Name), utils.ToCamelCase(node.Name), kind, node.Default)) 187 | } 188 | 189 | if node.Kind == cue.ListKind && node.SubTerraformType() != "" { 190 | defaults = append(defaults, fmt.Sprintf(`if len(m.%s.Elements()) == 0 { 191 | m.%s, _ = types.ListValue(types.%sType, []attr.Value{}) 192 | }`, utils.ToCamelCase(node.Name), utils.ToCamelCase(node.Name), node.SubTerraformType())) 193 | } 194 | 195 | } 196 | 197 | return fmt.Sprintf(`func (m %[1]s) ApplyDefaults() %[1]s { 198 | %s 199 | return m 200 | } 201 | 202 | `, s.Name, strings.Join(defaults, "\n")) 203 | } 204 | 205 | func (s *Model) Generate() string { 206 | b := strings.Builder{} 207 | for _, node := range s.Nodes { 208 | if node.Kind == cue.StructKind || node.Kind == cue.ListKind && node.SubKind == cue.StructKind { 209 | nestedModel := Model{ 210 | Name: s.Name + "_" + utils.Title(node.Name), 211 | IsDisjunction: node.IsDisjunction, 212 | Nodes: node.Children, 213 | Nested: true, 214 | } 215 | b.WriteString(nestedModel.Generate()) 216 | } 217 | } 218 | 219 | b.WriteString(s.terraformModel()) 220 | b.WriteString(s.generateToJSONFunction()) 221 | b.WriteString(s.generateDefaultsFunction()) 222 | 223 | return b.String() 224 | } 225 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/internal/nodes.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "regexp" 7 | "strings" 8 | 9 | "cuelang.org/go/cue" 10 | "cuelang.org/go/cue/ast" 11 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf/types" 12 | ) 13 | 14 | func GetAllNodes(val cue.Value) ([]types.Node, error) { 15 | if err := val.Validate(); err != nil { 16 | return nil, fmt.Errorf("error validating value: %w", err) 17 | } 18 | 19 | iter, err := val.Fields( 20 | cue.Definitions(false), // Should we do something with those? 21 | cue.Optional(true), 22 | ) 23 | if err != nil { 24 | return nil, fmt.Errorf("error retrieving value fields: %w", err) 25 | } 26 | 27 | nodes := make([]types.Node, 0) 28 | for iter.Next() { 29 | if iter.Selector().String() == "id" { 30 | // id is a field generated by the Grafana server and should not be included in the schema 31 | continue 32 | } 33 | 34 | node, err := GetSingleNode(iter.Selector().String(), iter.Value(), iter.IsOptional()) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | if node != nil { 40 | nodes = append(nodes, *node) 41 | } 42 | } 43 | 44 | return nodes, nil 45 | } 46 | 47 | func GetSingleNode(name string, val cue.Value, optional bool) (*types.Node, error) { 48 | // TODO: fixme 49 | if name == "reducer" { 50 | return nil, nil 51 | } 52 | 53 | node := types.Node{ 54 | Name: name, 55 | Kind: val.IncompleteKind(), 56 | // Structs should be optional if we want to set nested defaults 57 | Optional: optional || val.IncompleteKind() == cue.StructKind, 58 | Default: getDefault(val), 59 | Doc: formatDoc(val.Doc()), 60 | } 61 | 62 | val = cue.Dereference(val) 63 | op, args := val.Expr() 64 | if op == cue.OrOp { 65 | err := handleDisjunction(&node, args) 66 | return &node, err 67 | } 68 | 69 | switch node.Kind { 70 | case cue.ListKind: 71 | err := handleList(&node, val) 72 | if err != nil { 73 | return nil, err 74 | } 75 | case cue.StructKind: 76 | // Checks [string]something only. 77 | // It skips structs like {...} (cue.TopKind) to avoid undesired results. 78 | v := val.LookupPath(cue.MakePath(cue.AnyString)) 79 | if v.Exists() && v.IncompleteKind() != cue.TopKind { 80 | val = v 81 | node.IsMap = true 82 | } 83 | 84 | children, err := GetAllNodes(val.Value()) 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | node.Children = children 90 | for i := range node.Children { 91 | node.Children[i].Parent = &node 92 | } 93 | } 94 | 95 | return &node, nil 96 | } 97 | 98 | func handleList(node *types.Node, val cue.Value) error { 99 | node.Optional = true 100 | 101 | // TODO: fixme 102 | // Using a string type to allow composition of panel datasources 103 | // Doesn't seem possible to have an arbitrary map type here 104 | if node.Name == "panels" || node.Name == "targets" { 105 | node.SubKind = cue.StringKind 106 | return nil 107 | } 108 | 109 | // From cuetsy: 110 | // If the default (all lists have a default, usually self, ugh) differs from the 111 | // input list, peel it off. Otherwise our AnyIndex lookup may end up getting 112 | // sent on the wrong path. 113 | defv, _ := val.Default() 114 | if !defv.Equals(val) { 115 | _, v := val.Expr() 116 | val = v[0] 117 | } 118 | 119 | e := val.LookupPath(cue.MakePath(cue.AnyIndex)) 120 | if !e.Exists() { 121 | return errors.New("unreachable - open list must have a type") 122 | } 123 | 124 | e = cue.Dereference(e) 125 | op, args := e.Expr() 126 | if op == cue.OrOp { 127 | return handleDisjunction(node, args) 128 | } 129 | 130 | node.SubKind = e.IncompleteKind() 131 | switch node.SubKind { 132 | case cue.StructKind: 133 | children, err := GetAllNodes(e) 134 | if err != nil { 135 | return err 136 | } 137 | 138 | node.Children = children 139 | for i := range node.Children { 140 | node.Children[i].Parent = node 141 | } 142 | case cue.ListKind: 143 | // TODO - handle list in list 144 | case cue.TopKind: 145 | // TODO - handle open lists ([...]) 146 | } 147 | 148 | return nil 149 | } 150 | 151 | func handleDisjunction(node *types.Node, vals []cue.Value) error { 152 | children := make([]types.Node, 0) 153 | disjuncts := make([]cue.Value, 0) 154 | 155 | isComplex := false 156 | for _, val := range vals { 157 | isStructOrList := val.IncompleteKind() == cue.StructKind || val.IncompleteKind() == cue.ListKind 158 | if isStructOrList || !containsKind(disjuncts, val.IncompleteKind()) { 159 | disjuncts = append(disjuncts, val) 160 | } 161 | 162 | if isStructOrList { 163 | isComplex = true 164 | } 165 | } 166 | 167 | if len(disjuncts) <= 1 && !isComplex { 168 | return nil 169 | } 170 | 171 | if !isComplex || containsKind(disjuncts, cue.StringKind) { 172 | node.Kind = cue.StringKind 173 | for _, d := range disjuncts { 174 | node.DisjunctionKinds = append(node.DisjunctionKinds, d.IncompleteKind()) 175 | } 176 | if isComplex { 177 | node.Doc = "JSON-encoded string. " + node.Doc 178 | } 179 | return nil 180 | } 181 | 182 | for _, val := range disjuncts { 183 | node.SubKind = val.IncompleteKind() 184 | 185 | _, p := val.ReferencePath() 186 | arr := strings.Split(p.String(), ".") 187 | name := strings.ReplaceAll(arr[len(arr)-1], "#", "") 188 | // TODO - currently this catches setting a default object 189 | if name == "" { 190 | continue 191 | } 192 | 193 | child, err := GetSingleNode(name, val, true) 194 | if err != nil { 195 | return err 196 | } 197 | child.Parent = node 198 | 199 | children = append(children, *child) 200 | } 201 | node.IsDisjunction = true 202 | node.Children = children 203 | 204 | return nil 205 | } 206 | 207 | func containsKind(values []cue.Value, kind cue.Kind) bool { 208 | for _, v := range values { 209 | if v.IncompleteKind() == kind { 210 | return true 211 | } 212 | } 213 | return false 214 | } 215 | 216 | func getDefault(v cue.Value) string { 217 | _, ok := v.Default() 218 | if !ok { 219 | return "" 220 | } 221 | 222 | switch v.IncompleteKind() { 223 | case cue.StringKind: 224 | s, err := v.String() 225 | if err != nil { 226 | return "" 227 | } 228 | return fmt.Sprintf("`%s`", s) 229 | case cue.FloatKind, cue.NumberKind: 230 | f, err := v.Float64() 231 | if err != nil { 232 | return "" 233 | } 234 | return fmt.Sprintf("%f", f) 235 | case cue.IntKind: 236 | i, err := v.Int64() 237 | if err != nil { 238 | return "" 239 | } 240 | return fmt.Sprintf("%d", i) 241 | case cue.BoolKind: 242 | b, err := v.Bool() 243 | if err != nil { 244 | return "" 245 | } 246 | return fmt.Sprintf("%t", b) 247 | default: 248 | return "" 249 | } 250 | } 251 | 252 | func formatDoc(comments []*ast.CommentGroup) string { 253 | result := "" 254 | for _, comment := range comments { 255 | result += comment.Text() 256 | } 257 | 258 | result = strings.ReplaceAll(result, "`", "") 259 | 260 | reg := regexp.MustCompile(`{{([^}]*)}}`) 261 | result = reg.ReplaceAllString(result, "` + \"{{`{{${1}}}`}}\" + `") 262 | 263 | return strings.Trim(result, "\n ") 264 | } 265 | -------------------------------------------------------------------------------- /internal/provider/datasource_query_grafana_pyroscope_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated - EDITING IS FUTILE. DO NOT EDIT. 2 | // 3 | // Generated by pipeline: 4 | // terraform 5 | // Using jennies: 6 | // TerraformDataSourceJenny 7 | // ComposableLatestMajorsOrXJenny 8 | // 9 | // Run 'go generate ./' from repository root to regenerate. 10 | 11 | package provider 12 | 13 | import ( 14 | "context" 15 | "encoding/json" 16 | 17 | "github.com/hashicorp/terraform-plugin-framework/attr" 18 | "github.com/hashicorp/terraform-plugin-framework/datasource" 19 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema" 20 | "github.com/hashicorp/terraform-plugin-framework/diag" 21 | "github.com/hashicorp/terraform-plugin-framework/types" 22 | "github.com/hashicorp/terraform-plugin-log/tflog" 23 | ) 24 | 25 | // Ensure that the imports are used to avoid compiler errors. 26 | var _ attr.Value 27 | var _ diag.Diagnostic 28 | 29 | // Ensure provider defined types fully satisfy framework interfaces. 30 | var ( 31 | _ datasource.DataSource = &QueryGrafanaPyroscopeDataSource{} 32 | _ datasource.DataSourceWithConfigure = &QueryGrafanaPyroscopeDataSource{} 33 | ) 34 | 35 | func NewQueryGrafanaPyroscopeDataSource() datasource.DataSource { 36 | return &QueryGrafanaPyroscopeDataSource{} 37 | } 38 | 39 | // QueryGrafanaPyroscopeDataSource defines the data source implementation. 40 | type QueryGrafanaPyroscopeDataSource struct{} 41 | 42 | type QueryGrafanaPyroscopeDataSourceModel struct { 43 | RenderedJSON types.String `tfsdk:"rendered_json"` 44 | LabelSelector types.String `tfsdk:"label_selector"` 45 | ProfileTypeId types.String `tfsdk:"profile_type_id"` 46 | GroupBy types.List `tfsdk:"group_by"` 47 | MaxNodes types.Int64 `tfsdk:"max_nodes"` 48 | RefId types.String `tfsdk:"ref_id"` 49 | Hide types.Bool `tfsdk:"hide"` 50 | QueryType types.String `tfsdk:"query_type"` 51 | } 52 | 53 | func (m QueryGrafanaPyroscopeDataSourceModel) MarshalJSON() ([]byte, error) { 54 | type jsonQueryGrafanaPyroscopeDataSourceModel struct { 55 | LabelSelector string `json:"labelSelector"` 56 | ProfileTypeId string `json:"profileTypeId"` 57 | GroupBy []string `json:"groupBy,omitempty"` 58 | MaxNodes *int64 `json:"maxNodes,omitempty"` 59 | RefId string `json:"refId"` 60 | Hide *bool `json:"hide,omitempty"` 61 | QueryType *string `json:"queryType,omitempty"` 62 | } 63 | 64 | m = m.ApplyDefaults() 65 | attr_labelselector := m.LabelSelector.ValueString() 66 | attr_profiletypeid := m.ProfileTypeId.ValueString() 67 | attr_groupby := []string{} 68 | for _, v := range m.GroupBy.Elements() { 69 | attr_groupby = append(attr_groupby, v.(types.String).ValueString()) 70 | } 71 | attr_maxnodes := m.MaxNodes.ValueInt64Pointer() 72 | attr_refid := m.RefId.ValueString() 73 | attr_hide := m.Hide.ValueBoolPointer() 74 | attr_querytype := m.QueryType.ValueStringPointer() 75 | 76 | model := &jsonQueryGrafanaPyroscopeDataSourceModel{ 77 | LabelSelector: attr_labelselector, 78 | ProfileTypeId: attr_profiletypeid, 79 | GroupBy: attr_groupby, 80 | MaxNodes: attr_maxnodes, 81 | RefId: attr_refid, 82 | Hide: attr_hide, 83 | QueryType: attr_querytype, 84 | } 85 | return json.Marshal(model) 86 | } 87 | 88 | func (m QueryGrafanaPyroscopeDataSourceModel) ApplyDefaults() QueryGrafanaPyroscopeDataSourceModel { 89 | if m.LabelSelector.IsNull() { 90 | m.LabelSelector = types.StringValue(`{}`) 91 | } 92 | if len(m.GroupBy.Elements()) == 0 { 93 | m.GroupBy, _ = types.ListValue(types.StringType, []attr.Value{}) 94 | } 95 | return m 96 | } 97 | 98 | func (d *QueryGrafanaPyroscopeDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { 99 | resp.TypeName = req.ProviderTypeName + "_query_grafana_pyroscope" 100 | } 101 | 102 | func (d *QueryGrafanaPyroscopeDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { 103 | resp.Schema = schema.Schema{ 104 | // This description is used by the documentation generator and the language server. 105 | MarkdownDescription: "", 106 | Attributes: map[string]schema.Attribute{ 107 | "label_selector": schema.StringAttribute{ 108 | MarkdownDescription: `Specifies the query label selectors. Defaults to "{}".`, 109 | Computed: true, 110 | Optional: true, 111 | Required: false, 112 | }, 113 | "profile_type_id": schema.StringAttribute{ 114 | MarkdownDescription: `Specifies the type of profile to query.`, 115 | Computed: false, 116 | Optional: false, 117 | Required: true, 118 | }, 119 | "group_by": schema.ListAttribute{ 120 | MarkdownDescription: `Allows to group the results.`, 121 | Computed: false, 122 | Optional: true, 123 | Required: false, 124 | ElementType: types.StringType, 125 | }, 126 | "max_nodes": schema.Int64Attribute{ 127 | MarkdownDescription: `Sets the maximum number of nodes in the flamegraph.`, 128 | Computed: false, 129 | Optional: true, 130 | Required: false, 131 | }, 132 | "ref_id": schema.StringAttribute{ 133 | MarkdownDescription: `A unique identifier for the query within the list of targets. 134 | In server side expressions, the refId is used as a variable name to identify results. 135 | By default, the UI will assign A->Z; however setting meaningful names may be useful.`, 136 | Computed: false, 137 | Optional: false, 138 | Required: true, 139 | }, 140 | "hide": schema.BoolAttribute{ 141 | MarkdownDescription: `true if query is disabled (ie should not be returned to the dashboard) 142 | Note this does not always imply that the query should not be executed since 143 | the results from a hidden query may be used as the input to other queries (SSE etc)`, 144 | Computed: false, 145 | Optional: true, 146 | Required: false, 147 | }, 148 | "query_type": schema.StringAttribute{ 149 | MarkdownDescription: `Specify the query flavor 150 | TODO make this required and give it a default`, 151 | Computed: false, 152 | Optional: true, 153 | Required: false, 154 | }, 155 | 156 | "rendered_json": schema.StringAttribute{ 157 | Computed: true, 158 | MarkdownDescription: "This datasource rendered as JSON", 159 | }, 160 | }, 161 | } 162 | } 163 | 164 | func (d *QueryGrafanaPyroscopeDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { 165 | } 166 | 167 | func (d *QueryGrafanaPyroscopeDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { 168 | var data QueryGrafanaPyroscopeDataSourceModel 169 | 170 | // Read Terraform configuration data into the model 171 | resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) 172 | 173 | if resp.Diagnostics.HasError() { 174 | return 175 | } 176 | 177 | JSONConfig, err := json.Marshal(data) 178 | if err != nil { 179 | resp.Diagnostics.AddError("JSON marshalling error", err.Error()) 180 | return 181 | } 182 | 183 | // Not sure about that 184 | data.RenderedJSON = types.StringValue(string(JSONConfig)) 185 | 186 | // Write logs using the tflog package 187 | // Documentation: https://terraform.io/plugin/log 188 | tflog.Trace(ctx, "read a data source") 189 | 190 | // Save data into Terraform state 191 | resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) 192 | } 193 | -------------------------------------------------------------------------------- /internal/provider/datasource_query_loki_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated - EDITING IS FUTILE. DO NOT EDIT. 2 | // 3 | // Generated by pipeline: 4 | // terraform 5 | // Using jennies: 6 | // TerraformDataSourceJenny 7 | // ComposableLatestMajorsOrXJenny 8 | // 9 | // Run 'go generate ./' from repository root to regenerate. 10 | 11 | package provider 12 | 13 | import ( 14 | "context" 15 | "encoding/json" 16 | 17 | "github.com/hashicorp/terraform-plugin-framework/attr" 18 | "github.com/hashicorp/terraform-plugin-framework/datasource" 19 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema" 20 | "github.com/hashicorp/terraform-plugin-framework/diag" 21 | "github.com/hashicorp/terraform-plugin-framework/types" 22 | "github.com/hashicorp/terraform-plugin-log/tflog" 23 | ) 24 | 25 | // Ensure that the imports are used to avoid compiler errors. 26 | var _ attr.Value 27 | var _ diag.Diagnostic 28 | 29 | // Ensure provider defined types fully satisfy framework interfaces. 30 | var ( 31 | _ datasource.DataSource = &QueryLokiDataSource{} 32 | _ datasource.DataSourceWithConfigure = &QueryLokiDataSource{} 33 | ) 34 | 35 | func NewQueryLokiDataSource() datasource.DataSource { 36 | return &QueryLokiDataSource{} 37 | } 38 | 39 | // QueryLokiDataSource defines the data source implementation. 40 | type QueryLokiDataSource struct{} 41 | 42 | type QueryLokiDataSourceModel struct { 43 | RenderedJSON types.String `tfsdk:"rendered_json"` 44 | Expr types.String `tfsdk:"expr"` 45 | LegendFormat types.String `tfsdk:"legend_format"` 46 | MaxLines types.Int64 `tfsdk:"max_lines"` 47 | Resolution types.Int64 `tfsdk:"resolution"` 48 | EditorMode types.String `tfsdk:"editor_mode"` 49 | Range types.Bool `tfsdk:"range"` 50 | Instant types.Bool `tfsdk:"instant"` 51 | Step types.String `tfsdk:"step"` 52 | RefId types.String `tfsdk:"ref_id"` 53 | Hide types.Bool `tfsdk:"hide"` 54 | QueryType types.String `tfsdk:"query_type"` 55 | } 56 | 57 | func (m QueryLokiDataSourceModel) MarshalJSON() ([]byte, error) { 58 | type jsonQueryLokiDataSourceModel struct { 59 | Expr string `json:"expr"` 60 | LegendFormat *string `json:"legendFormat,omitempty"` 61 | MaxLines *int64 `json:"maxLines,omitempty"` 62 | Resolution *int64 `json:"resolution,omitempty"` 63 | EditorMode *string `json:"editorMode,omitempty"` 64 | Range *bool `json:"range,omitempty"` 65 | Instant *bool `json:"instant,omitempty"` 66 | Step *string `json:"step,omitempty"` 67 | RefId string `json:"refId"` 68 | Hide *bool `json:"hide,omitempty"` 69 | QueryType *string `json:"queryType,omitempty"` 70 | } 71 | 72 | m = m.ApplyDefaults() 73 | attr_expr := m.Expr.ValueString() 74 | attr_legendformat := m.LegendFormat.ValueStringPointer() 75 | attr_maxlines := m.MaxLines.ValueInt64Pointer() 76 | attr_resolution := m.Resolution.ValueInt64Pointer() 77 | attr_editormode := m.EditorMode.ValueStringPointer() 78 | attr_range := m.Range.ValueBoolPointer() 79 | attr_instant := m.Instant.ValueBoolPointer() 80 | attr_step := m.Step.ValueStringPointer() 81 | attr_refid := m.RefId.ValueString() 82 | attr_hide := m.Hide.ValueBoolPointer() 83 | attr_querytype := m.QueryType.ValueStringPointer() 84 | 85 | model := &jsonQueryLokiDataSourceModel{ 86 | Expr: attr_expr, 87 | LegendFormat: attr_legendformat, 88 | MaxLines: attr_maxlines, 89 | Resolution: attr_resolution, 90 | EditorMode: attr_editormode, 91 | Range: attr_range, 92 | Instant: attr_instant, 93 | Step: attr_step, 94 | RefId: attr_refid, 95 | Hide: attr_hide, 96 | QueryType: attr_querytype, 97 | } 98 | return json.Marshal(model) 99 | } 100 | 101 | func (m QueryLokiDataSourceModel) ApplyDefaults() QueryLokiDataSourceModel { 102 | 103 | return m 104 | } 105 | 106 | func (d *QueryLokiDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { 107 | resp.TypeName = req.ProviderTypeName + "_query_loki" 108 | } 109 | 110 | func (d *QueryLokiDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { 111 | resp.Schema = schema.Schema{ 112 | // This description is used by the documentation generator and the language server. 113 | MarkdownDescription: "", 114 | Attributes: map[string]schema.Attribute{ 115 | "expr": schema.StringAttribute{ 116 | MarkdownDescription: `The LogQL query.`, 117 | Computed: false, 118 | Optional: false, 119 | Required: true, 120 | }, 121 | "legend_format": schema.StringAttribute{ 122 | MarkdownDescription: `Used to override the name of the series.`, 123 | Computed: false, 124 | Optional: true, 125 | Required: false, 126 | }, 127 | "max_lines": schema.Int64Attribute{ 128 | MarkdownDescription: `Used to limit the number of log rows returned.`, 129 | Computed: false, 130 | Optional: true, 131 | Required: false, 132 | }, 133 | "resolution": schema.Int64Attribute{ 134 | MarkdownDescription: `@deprecated, now use step.`, 135 | Computed: false, 136 | Optional: true, 137 | Required: false, 138 | DeprecationMessage: `Now use step.`, 139 | }, 140 | "editor_mode": schema.StringAttribute{ 141 | MarkdownDescription: ``, 142 | Computed: false, 143 | Optional: true, 144 | Required: false, 145 | }, 146 | "range": schema.BoolAttribute{ 147 | MarkdownDescription: `@deprecated, now use queryType.`, 148 | Computed: false, 149 | Optional: true, 150 | Required: false, 151 | DeprecationMessage: `Now use queryType.`, 152 | }, 153 | "instant": schema.BoolAttribute{ 154 | MarkdownDescription: `@deprecated, now use queryType.`, 155 | Computed: false, 156 | Optional: true, 157 | Required: false, 158 | DeprecationMessage: `Now use queryType.`, 159 | }, 160 | "step": schema.StringAttribute{ 161 | MarkdownDescription: `Used to set step value for range queries.`, 162 | Computed: false, 163 | Optional: true, 164 | Required: false, 165 | }, 166 | "ref_id": schema.StringAttribute{ 167 | MarkdownDescription: `A unique identifier for the query within the list of targets. 168 | In server side expressions, the refId is used as a variable name to identify results. 169 | By default, the UI will assign A->Z; however setting meaningful names may be useful.`, 170 | Computed: false, 171 | Optional: false, 172 | Required: true, 173 | }, 174 | "hide": schema.BoolAttribute{ 175 | MarkdownDescription: `true if query is disabled (ie should not be returned to the dashboard) 176 | Note this does not always imply that the query should not be executed since 177 | the results from a hidden query may be used as the input to other queries (SSE etc)`, 178 | Computed: false, 179 | Optional: true, 180 | Required: false, 181 | }, 182 | "query_type": schema.StringAttribute{ 183 | MarkdownDescription: `Specify the query flavor 184 | TODO make this required and give it a default`, 185 | Computed: false, 186 | Optional: true, 187 | Required: false, 188 | }, 189 | 190 | "rendered_json": schema.StringAttribute{ 191 | Computed: true, 192 | MarkdownDescription: "This datasource rendered as JSON", 193 | }, 194 | }, 195 | } 196 | } 197 | 198 | func (d *QueryLokiDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { 199 | } 200 | 201 | func (d *QueryLokiDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { 202 | var data QueryLokiDataSourceModel 203 | 204 | // Read Terraform configuration data into the model 205 | resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) 206 | 207 | if resp.Diagnostics.HasError() { 208 | return 209 | } 210 | 211 | JSONConfig, err := json.Marshal(data) 212 | if err != nil { 213 | resp.Diagnostics.AddError("JSON marshalling error", err.Error()) 214 | return 215 | } 216 | 217 | // Not sure about that 218 | data.RenderedJSON = types.StringValue(string(JSONConfig)) 219 | 220 | // Write logs using the tflog package 221 | // Documentation: https://terraform.io/plugin/log 222 | tflog.Trace(ctx, "read a data source") 223 | 224 | // Save data into Terraform state 225 | resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) 226 | } 227 | -------------------------------------------------------------------------------- /internal/provider/datasource_query_prometheus_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated - EDITING IS FUTILE. DO NOT EDIT. 2 | // 3 | // Generated by pipeline: 4 | // terraform 5 | // Using jennies: 6 | // TerraformDataSourceJenny 7 | // ComposableLatestMajorsOrXJenny 8 | // 9 | // Run 'go generate ./' from repository root to regenerate. 10 | 11 | package provider 12 | 13 | import ( 14 | "context" 15 | "encoding/json" 16 | 17 | "github.com/hashicorp/terraform-plugin-framework/attr" 18 | "github.com/hashicorp/terraform-plugin-framework/datasource" 19 | "github.com/hashicorp/terraform-plugin-framework/datasource/schema" 20 | "github.com/hashicorp/terraform-plugin-framework/diag" 21 | "github.com/hashicorp/terraform-plugin-framework/types" 22 | "github.com/hashicorp/terraform-plugin-log/tflog" 23 | ) 24 | 25 | // Ensure that the imports are used to avoid compiler errors. 26 | var _ attr.Value 27 | var _ diag.Diagnostic 28 | 29 | // Ensure provider defined types fully satisfy framework interfaces. 30 | var ( 31 | _ datasource.DataSource = &QueryPrometheusDataSource{} 32 | _ datasource.DataSourceWithConfigure = &QueryPrometheusDataSource{} 33 | ) 34 | 35 | func NewQueryPrometheusDataSource() datasource.DataSource { 36 | return &QueryPrometheusDataSource{} 37 | } 38 | 39 | // QueryPrometheusDataSource defines the data source implementation. 40 | type QueryPrometheusDataSource struct{} 41 | 42 | type QueryPrometheusDataSourceModel struct { 43 | RenderedJSON types.String `tfsdk:"rendered_json"` 44 | Expr types.String `tfsdk:"expr"` 45 | Instant types.Bool `tfsdk:"instant"` 46 | Range types.Bool `tfsdk:"range"` 47 | Exemplar types.Bool `tfsdk:"exemplar"` 48 | EditorMode types.String `tfsdk:"editor_mode"` 49 | Format types.String `tfsdk:"format"` 50 | LegendFormat types.String `tfsdk:"legend_format"` 51 | IntervalFactor types.Float64 `tfsdk:"interval_factor"` 52 | RefId types.String `tfsdk:"ref_id"` 53 | Hide types.Bool `tfsdk:"hide"` 54 | QueryType types.String `tfsdk:"query_type"` 55 | } 56 | 57 | func (m QueryPrometheusDataSourceModel) MarshalJSON() ([]byte, error) { 58 | type jsonQueryPrometheusDataSourceModel struct { 59 | Expr string `json:"expr"` 60 | Instant *bool `json:"instant,omitempty"` 61 | Range *bool `json:"range,omitempty"` 62 | Exemplar *bool `json:"exemplar,omitempty"` 63 | EditorMode *string `json:"editorMode,omitempty"` 64 | Format *string `json:"format,omitempty"` 65 | LegendFormat *string `json:"legendFormat,omitempty"` 66 | IntervalFactor *float64 `json:"intervalFactor,omitempty"` 67 | RefId string `json:"refId"` 68 | Hide *bool `json:"hide,omitempty"` 69 | QueryType *string `json:"queryType,omitempty"` 70 | } 71 | 72 | m = m.ApplyDefaults() 73 | attr_expr := m.Expr.ValueString() 74 | attr_instant := m.Instant.ValueBoolPointer() 75 | attr_range := m.Range.ValueBoolPointer() 76 | attr_exemplar := m.Exemplar.ValueBoolPointer() 77 | attr_editormode := m.EditorMode.ValueStringPointer() 78 | attr_format := m.Format.ValueStringPointer() 79 | attr_legendformat := m.LegendFormat.ValueStringPointer() 80 | attr_intervalfactor := m.IntervalFactor.ValueFloat64Pointer() 81 | attr_refid := m.RefId.ValueString() 82 | attr_hide := m.Hide.ValueBoolPointer() 83 | attr_querytype := m.QueryType.ValueStringPointer() 84 | 85 | model := &jsonQueryPrometheusDataSourceModel{ 86 | Expr: attr_expr, 87 | Instant: attr_instant, 88 | Range: attr_range, 89 | Exemplar: attr_exemplar, 90 | EditorMode: attr_editormode, 91 | Format: attr_format, 92 | LegendFormat: attr_legendformat, 93 | IntervalFactor: attr_intervalfactor, 94 | RefId: attr_refid, 95 | Hide: attr_hide, 96 | QueryType: attr_querytype, 97 | } 98 | return json.Marshal(model) 99 | } 100 | 101 | func (m QueryPrometheusDataSourceModel) ApplyDefaults() QueryPrometheusDataSourceModel { 102 | 103 | return m 104 | } 105 | 106 | func (d *QueryPrometheusDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { 107 | resp.TypeName = req.ProviderTypeName + "_query_prometheus" 108 | } 109 | 110 | func (d *QueryPrometheusDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { 111 | resp.Schema = schema.Schema{ 112 | // This description is used by the documentation generator and the language server. 113 | MarkdownDescription: "", 114 | Attributes: map[string]schema.Attribute{ 115 | "expr": schema.StringAttribute{ 116 | MarkdownDescription: `The actual expression/query that will be evaluated by Prometheus`, 117 | Computed: false, 118 | Optional: false, 119 | Required: true, 120 | }, 121 | "instant": schema.BoolAttribute{ 122 | MarkdownDescription: `Returns only the latest value that Prometheus has scraped for the requested time series`, 123 | Computed: false, 124 | Optional: true, 125 | Required: false, 126 | }, 127 | "range": schema.BoolAttribute{ 128 | MarkdownDescription: `Returns a Range vector, comprised of a set of time series containing a range of data points over time for each time series`, 129 | Computed: false, 130 | Optional: true, 131 | Required: false, 132 | }, 133 | "exemplar": schema.BoolAttribute{ 134 | MarkdownDescription: `Execute an additional query to identify interesting raw samples relevant for the given expr`, 135 | Computed: false, 136 | Optional: true, 137 | Required: false, 138 | }, 139 | "editor_mode": schema.StringAttribute{ 140 | MarkdownDescription: `Specifies which editor is being used to prepare the query. It can be "code" or "builder"`, 141 | Computed: false, 142 | Optional: true, 143 | Required: false, 144 | }, 145 | "format": schema.StringAttribute{ 146 | MarkdownDescription: `Query format to determine how to display data points in panel. It can be "time_series", "table", "heatmap"`, 147 | Computed: false, 148 | Optional: true, 149 | Required: false, 150 | }, 151 | "legend_format": schema.StringAttribute{ 152 | MarkdownDescription: `Series name override or template. Ex. ` + "{{`{{hostname}}`}}" + ` will be replaced with label value for hostname`, 153 | Computed: false, 154 | Optional: true, 155 | Required: false, 156 | }, 157 | "interval_factor": schema.Float64Attribute{ 158 | MarkdownDescription: `@deprecated Used to specify how many times to divide max data points by. We use max data points under query options 159 | See https://github.com/grafana/grafana/issues/48081`, 160 | Computed: false, 161 | Optional: true, 162 | Required: false, 163 | DeprecationMessage: `Used to specify how many times to divide max data points by. We use max data points under query options 164 | See https://github.com/grafana/grafana/issues/48081`, 165 | }, 166 | "ref_id": schema.StringAttribute{ 167 | MarkdownDescription: `A unique identifier for the query within the list of targets. 168 | In server side expressions, the refId is used as a variable name to identify results. 169 | By default, the UI will assign A->Z; however setting meaningful names may be useful.`, 170 | Computed: false, 171 | Optional: false, 172 | Required: true, 173 | }, 174 | "hide": schema.BoolAttribute{ 175 | MarkdownDescription: `true if query is disabled (ie should not be returned to the dashboard) 176 | Note this does not always imply that the query should not be executed since 177 | the results from a hidden query may be used as the input to other queries (SSE etc)`, 178 | Computed: false, 179 | Optional: true, 180 | Required: false, 181 | }, 182 | "query_type": schema.StringAttribute{ 183 | MarkdownDescription: `Specify the query flavor 184 | TODO make this required and give it a default`, 185 | Computed: false, 186 | Optional: true, 187 | Required: false, 188 | }, 189 | 190 | "rendered_json": schema.StringAttribute{ 191 | Computed: true, 192 | MarkdownDescription: "This datasource rendered as JSON", 193 | }, 194 | }, 195 | } 196 | } 197 | 198 | func (d *QueryPrometheusDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { 199 | } 200 | 201 | func (d *QueryPrometheusDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { 202 | var data QueryPrometheusDataSourceModel 203 | 204 | // Read Terraform configuration data into the model 205 | resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) 206 | 207 | if resp.Diagnostics.HasError() { 208 | return 209 | } 210 | 211 | JSONConfig, err := json.Marshal(data) 212 | if err != nil { 213 | resp.Diagnostics.AddError("JSON marshalling error", err.Error()) 214 | return 215 | } 216 | 217 | // Not sure about that 218 | data.RenderedJSON = types.StringValue(string(JSONConfig)) 219 | 220 | // Write logs using the tflog package 221 | // Documentation: https://terraform.io/plugin/log 222 | tflog.Trace(ctx, "read a data source") 223 | 224 | // Save data into Terraform state 225 | resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) 226 | } 227 | -------------------------------------------------------------------------------- /gen/terraform/cuetf/datasource_generator.go: -------------------------------------------------------------------------------- 1 | package cuetf 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "fmt" 7 | "go/format" 8 | "regexp" 9 | "strings" 10 | 11 | "cuelang.org/go/cue" 12 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf/internal" 13 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf/internal/utils" 14 | "github.com/grafana/terraform-provider-schemas/gen/terraform/cuetf/types" 15 | "github.com/grafana/thema" 16 | ) 17 | 18 | // GenerateDataSource takes a cue.Value and generates the corresponding Terraform data source. 19 | func GenerateDataSource(schema thema.Schema) (b []byte, err error) { 20 | value := schema.Underlying().LookupPath(cue.MakePath(cue.Str("schema"), cue.Str("spec"))) 21 | if !value.Exists() { 22 | value = schema.Underlying().LookupPath(cue.MakePath(cue.Str("schema"))) 23 | } 24 | 25 | nodes, err := internal.GetAllNodes(value) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | if err := extractPanelNodes(schema); err != nil { 31 | return nil, err 32 | } 33 | 34 | linName := schema.Lineage().Name() 35 | if strings.HasPrefix(GetKindName(linName), "Panel") { 36 | // The common schema has an `options` field that is empty and overridden by `panelOptions` in the panel schema 37 | // and a `fieldConfig` field that should contain a `custom` field that contains the panel schema `panelFieldConfig` nodes 38 | // It seems like all other fields in the panel schema should be definitions 39 | var panelOptions *types.Node 40 | var panelFieldConfig *types.Node 41 | for i, node := range nodes { 42 | if node.Name == "Options" { 43 | nodes[i].Name = "options" 44 | panelOptions = &nodes[i] 45 | } else if node.Name == "FieldConfig" { 46 | nodes[i].Name = "custom" 47 | panelFieldConfig = &nodes[i] 48 | } 49 | } 50 | 51 | if len(panelNodes) == 0 { 52 | return nil, errors.New("panel schema not found") 53 | } 54 | 55 | for i, node := range panelNodes { 56 | if node.Name == "options" && panelOptions != nil { 57 | panelNodes[i] = *panelOptions 58 | } 59 | 60 | if node.Name == "fieldConfig" && panelFieldConfig != nil { 61 | for _, n1 := range node.Children { 62 | if n1.Name != "defaults" { 63 | continue 64 | } 65 | 66 | for j, n2 := range n1.Children { 67 | if n2.Name == "custom" { 68 | n1.Children[j] = *panelFieldConfig 69 | } 70 | } 71 | } 72 | } 73 | 74 | // TODO: set it as read-only? 75 | if node.Name == "type" { 76 | panelType := GetPanelType(linName) 77 | node.Default = fmt.Sprintf("`%s`", panelType) 78 | panelNodes[i] = node 79 | } 80 | } 81 | 82 | nodes = panelNodes 83 | } 84 | 85 | schemaAttributes, err := GenerateSchemaAttributes(nodes) 86 | if err != nil { 87 | return nil, err 88 | } 89 | 90 | structName := GetStructName(linName) 91 | model := types.Model{ 92 | Name: structName + "Model", 93 | Nodes: nodes, 94 | } 95 | 96 | vars := TVarsDataSource{ 97 | Name: GetResourceName(linName), 98 | StructName: structName, 99 | Models: model.Generate(), 100 | SchemaAttributes: schemaAttributes, 101 | } 102 | 103 | buf := new(bytes.Buffer) 104 | if err := tmpls.Lookup("datasource.tmpl").Execute(buf, vars); err != nil { 105 | return nil, fmt.Errorf("failed executing datasource template: %w", err) 106 | } 107 | // return buf.Bytes(), nil 108 | 109 | return format.Source(buf.Bytes()) 110 | } 111 | 112 | func GenerateSchemaAttributes(nodes []types.Node) (string, error) { 113 | attributes := make([]string, 0) 114 | for _, node := range nodes { 115 | // TODO: all nodes should be generated 116 | if !node.IsGenerated() { 117 | continue 118 | } 119 | 120 | description := node.Doc 121 | if node.Default != "" { 122 | if description != "" && !strings.HasSuffix(description, ".") { 123 | description += "." 124 | } 125 | description += " Defaults to " + strings.ReplaceAll(node.Default, "`", `"`) + "." 126 | } 127 | 128 | var deprecated string 129 | if strings.Contains(node.Doc, "@deprecated") { 130 | deprecated = deprecationMessage(node.Doc) 131 | } 132 | 133 | vars := TVarsSchemaAttribute{ 134 | Name: utils.ToSnakeCase(node.Name), 135 | Description: description, 136 | DeprecationMessage: deprecated, 137 | AttributeType: node.TerraformType(), 138 | Computed: false, 139 | Optional: node.Optional, 140 | } 141 | 142 | if node.Default != "" { 143 | vars.Optional = true 144 | vars.Computed = true 145 | } 146 | 147 | switch node.Kind { 148 | case cue.ListKind: 149 | subType := node.SubTerraformType() 150 | if subType != "" { 151 | // "example_attribute": schema.ListAttribute{ 152 | // ElementType: types.StringType, 153 | // // ... other fields ... 154 | // }, 155 | vars.AttributeType = "List" 156 | vars.ElementType = fmt.Sprintf("types.%sType", subType) 157 | } else if node.SubKind == cue.StructKind { 158 | // "nested_attribute": schema.ListNestedAttribute{ 159 | // NestedObject: schema.NestedAttributeObject{ 160 | // Attributes: map[string]schema.Attribute{ 161 | // "hello": schema.StringAttribute{ 162 | // /* ... */ 163 | // }, 164 | // }, 165 | // }, 166 | // }, 167 | vars.AttributeType = "ListNested" 168 | nestedObjectAttributes, err := GenerateSchemaAttributes(node.Children) 169 | if err != nil { 170 | return "", fmt.Errorf("error trying to generate nested attributes in list: %s", err) 171 | } 172 | vars.NestedObjectAttributes = nestedObjectAttributes 173 | } 174 | case cue.StructKind: 175 | if node.IsMap { 176 | // "nested_attribute": schema.MapNestedAttribute{ 177 | // NestedObject: schema.NestedAttributeObject{ 178 | // Attributes: map[string]schema.Attribute{ 179 | // "hello": schema.StringAttribute{ 180 | // /* ... */ 181 | // }, 182 | // }, 183 | // }, 184 | // }, 185 | vars.AttributeType = "MapNested" 186 | nestedObjectAttributes, err := GenerateSchemaAttributes(node.Children) 187 | if err != nil { 188 | return "", fmt.Errorf("error trying to generate nested attributes in map: %s", err) 189 | } 190 | vars.NestedObjectAttributes = nestedObjectAttributes 191 | } else { 192 | // "nested_attribute": schema.SingleNestedAttribute{ 193 | // Attributes: map[string]schema.Attribute{ 194 | // "hello": schema.StringAttribute{ 195 | // /* ... */ 196 | // }, 197 | // }, 198 | // }, 199 | vars.AttributeType = "SingleNested" 200 | nestedAttributes, err := GenerateSchemaAttributes(node.Children) 201 | if err != nil { 202 | return "", fmt.Errorf("error trying to generate nested attributes in struct: %w", err) 203 | } 204 | vars.NestedAttributes = nestedAttributes 205 | 206 | // Structs should be computed if we want to set nested defaults? 207 | vars.Computed = true 208 | } 209 | } 210 | 211 | buf := new(bytes.Buffer) 212 | if err := tmpls.Lookup("schema_attribute.tmpl").Execute(buf, vars); err != nil { 213 | return "", fmt.Errorf("failed executing datasource template: %w", err) 214 | } 215 | 216 | attributes = append(attributes, buf.String()) 217 | } 218 | 219 | return strings.Join(attributes, ""), nil 220 | } 221 | 222 | var deprecatedMatch = regexp.MustCompile(`^\W*@deprecated\W*`) 223 | 224 | func deprecationMessage(str string) string { 225 | deprecated := deprecatedMatch.ReplaceAllString(str, "") 226 | return utils.CapitalizeFirstLetter(deprecated) 227 | } 228 | 229 | var panelNodes []types.Node 230 | 231 | func extractPanelNodes(schema thema.Schema) error { 232 | if schema.Lineage().Name() == "dashboard" { 233 | schemaValue := schema.Underlying().LookupPath(cue.MakePath(cue.Str("schema"))) 234 | iter, err := schemaValue.Fields( 235 | cue.Definitions(true), 236 | cue.Optional(false), 237 | cue.Attributes(false), 238 | ) 239 | if err != nil { 240 | return err 241 | } 242 | for iter.Next() { 243 | if iter.Selector().String() == "#Panel" { 244 | if panelNodes, err = internal.GetAllNodes(iter.Value()); err != nil { 245 | return err 246 | } 247 | break 248 | } 249 | } 250 | } 251 | return nil 252 | } 253 | 254 | func GetKindName(rawName string) string { 255 | name := rawName 256 | if strings.HasSuffix(name, "PanelCfg") { 257 | name = "Panel" + strings.TrimSuffix(name, "PanelCfg") 258 | } else if strings.HasSuffix(name, "DataQuery") { 259 | name = "Query" + strings.TrimSuffix(name, "DataQuery") 260 | } else { 261 | switch name { 262 | case "accesspolicy": 263 | name = "AccessPolicy" 264 | case "librarypanel": 265 | name = "LibraryPanel" 266 | case "publicdashboard": 267 | name = "PublicDashboard" 268 | case "rolebinding": 269 | name = "RoleBinding" 270 | default: 271 | name = utils.Title(name) 272 | } 273 | name = "Core" + name 274 | } 275 | 276 | return name 277 | } 278 | 279 | // From https://github.com/grafana/grafana/blob/main/pkg/kindsysreport/codegen/report.go#LL283-L299 280 | // used to map names for those plugins that aren't following 281 | // naming conventions, like 'annonlist' which comes from "Annotations list". 282 | var irregularPluginNames = map[string]string{ 283 | "alertgroups": "alertGroups", 284 | "annotationslist": "annolist", 285 | "dashboardlist": "dashlist", 286 | "nodegraph": "nodeGraph", 287 | "statetimeline": "state-timeline", 288 | "statushistory": "status-history", 289 | "tableold": "table-old", 290 | } 291 | 292 | // TODO: Better way to get panel type? 293 | func GetPanelType(name string) string { 294 | panelType := strings.ToLower(strings.TrimPrefix(GetKindName(name), "Panel")) 295 | 296 | if name, isIrregular := irregularPluginNames[panelType]; isIrregular { 297 | panelType = name 298 | } 299 | 300 | return panelType 301 | } 302 | 303 | func GetStructName(rawName string) string { 304 | return utils.Title(GetKindName(rawName)) + "DataSource" 305 | } 306 | 307 | func GetResourceName(rawName string) string { 308 | return utils.ToSnakeCase(GetKindName(rawName)) 309 | } 310 | -------------------------------------------------------------------------------- /docs/data-sources/core_dashboard.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_core_dashboard Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_core_dashboard (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Optional 19 | 20 | - `annotations` (Attributes) Contains the list of annotations that are associated with the dashboard. 21 | Annotations are used to overlay event markers and overlay event tags on graphs. 22 | Grafana comes with a native annotation store and the ability to add annotation events directly from the graph panel or via the HTTP API. 23 | See https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/annotate-visualizations/ (see [below for nested schema](#nestedatt--annotations)) 24 | - `description` (String) Description of dashboard. 25 | - `editable` (Boolean) Whether a dashboard is editable or not. Defaults to true. 26 | - `fiscal_year_start_month` (Number) The month that the fiscal year starts on. 0 = January, 11 = December. Defaults to 0. 27 | - `gnet_id` (String) ID of a dashboard imported from the https://grafana.com/grafana/dashboards/ portal 28 | - `graph_tooltip` (Number) Configuration of dashboard cursor sync behavior. 29 | Accepted values are 0 (sync turned off), 1 (shared crosshair), 2 (shared crosshair and tooltip). Defaults to 0. 30 | - `links` (Attributes List) Links with references to other dashboards or external websites. (see [below for nested schema](#nestedatt--links)) 31 | - `live_now` (Boolean) When set to true, the dashboard will redraw panels at an interval matching the pixel width. 32 | This will keep data "moving left" regardless of the query refresh rate. This setting helps 33 | avoid dashboards presenting stale live data 34 | - `panels` (List of String) List of dashboard panels 35 | - `refresh` (String) Refresh rate of dashboard. Represented via interval string, e.g. "5s", "1m", "1h", "1d". 36 | - `revision` (Number) This property should only be used in dashboards defined by plugins. It is a quick check 37 | to see if the version has changed since the last time. 38 | - `schema_version` (Number) Version of the JSON schema, incremented each time a Grafana update brings 39 | changes to said schema. Defaults to 36. 40 | - `snapshot` (Attributes) Snapshot options. They are present only if the dashboard is a snapshot. (see [below for nested schema](#nestedatt--snapshot)) 41 | - `style` (String) Theme of dashboard. 42 | Default value: dark. Defaults to "dark". 43 | - `tags` (List of String) Tags associated with dashboard. 44 | - `templating` (Attributes) Configured template variables (see [below for nested schema](#nestedatt--templating)) 45 | - `time` (Attributes) Time range for dashboard. 46 | Accepted values are relative time strings like {from: 'now-6h', to: 'now'} or absolute time strings like {from: '2020-07-10T08:00:00.000Z', to: '2020-07-10T14:00:00.000Z'}. (see [below for nested schema](#nestedatt--time)) 47 | - `timepicker` (Attributes) Configuration of the time picker shown at the top of a dashboard. (see [below for nested schema](#nestedatt--timepicker)) 48 | - `timezone` (String) Timezone of dashboard. Accepted values are IANA TZDB zone ID or "browser" or "utc". Defaults to "browser". 49 | - `title` (String) Title of dashboard. 50 | - `uid` (String) Unique dashboard identifier that can be generated by anyone. string (8-40) 51 | - `version` (Number) Version of the dashboard, incremented each time the dashboard is updated. 52 | - `week_start` (String) Day when the week starts. Expressed by the name of the day in lowercase, e.g. "monday". 53 | 54 | ### Read-Only 55 | 56 | - `rendered_json` (String) This datasource rendered as JSON 57 | 58 | 59 | ### Nested Schema for `annotations` 60 | 61 | Optional: 62 | 63 | - `list` (Attributes List) List of annotations (see [below for nested schema](#nestedatt--annotations--list)) 64 | 65 | 66 | ### Nested Schema for `annotations.list` 67 | 68 | Required: 69 | 70 | - `icon_color` (String) Color to use for the annotation event markers 71 | - `name` (String) Name of annotation. 72 | 73 | Optional: 74 | 75 | - `datasource` (Attributes) Datasource where the annotations data is (see [below for nested schema](#nestedatt--annotations--list--datasource)) 76 | - `enable` (Boolean) When enabled the annotation query is issued with every dashboard refresh. Defaults to true. 77 | - `filter` (Attributes) Filters to apply when fetching annotations (see [below for nested schema](#nestedatt--annotations--list--filter)) 78 | - `hide` (Boolean) Annotation queries can be toggled on or off at the top of the dashboard. 79 | When hide is true, the toggle is not shown in the dashboard. Defaults to false. 80 | - `target` (Attributes) TODO.. this should just be a normal query target (see [below for nested schema](#nestedatt--annotations--list--target)) 81 | - `type` (String) TODO -- this should not exist here, it is based on the --grafana-- datasource 82 | 83 | 84 | ### Nested Schema for `annotations.list.datasource` 85 | 86 | Optional: 87 | 88 | - `type` (String) The plugin type-id 89 | - `uid` (String) Specific datasource instance 90 | 91 | 92 | 93 | ### Nested Schema for `annotations.list.filter` 94 | 95 | Optional: 96 | 97 | - `exclude` (Boolean) Should the specified panels be included or excluded. Defaults to false. 98 | - `ids` (List of Number) Panel IDs that should be included or excluded 99 | 100 | 101 | 102 | ### Nested Schema for `annotations.list.target` 103 | 104 | Required: 105 | 106 | - `limit` (Number) Only required/valid for the grafana datasource... 107 | but code+tests is already depending on it so hard to change 108 | - `match_any` (Boolean) Only required/valid for the grafana datasource... 109 | but code+tests is already depending on it so hard to change 110 | - `type` (String) Only required/valid for the grafana datasource... 111 | but code+tests is already depending on it so hard to change 112 | 113 | Optional: 114 | 115 | - `tags` (List of String) Only required/valid for the grafana datasource... 116 | but code+tests is already depending on it so hard to change 117 | 118 | 119 | 120 | 121 | 122 | ### Nested Schema for `links` 123 | 124 | Required: 125 | 126 | - `icon` (String) Icon name to be displayed with the link 127 | - `title` (String) Title to display with the link 128 | - `tooltip` (String) Tooltip to display when the user hovers their mouse over it 129 | - `type` (String) Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource) 130 | - `url` (String) Link URL. Only required/valid if the type is link 131 | 132 | Optional: 133 | 134 | - `as_dropdown` (Boolean) If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards. Defaults to false. 135 | - `include_vars` (Boolean) If true, includes current template variables values in the link as query params. Defaults to false. 136 | - `keep_time` (Boolean) If true, includes current time range in the link as query params. Defaults to false. 137 | - `tags` (List of String) List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards 138 | - `target_blank` (Boolean) If true, the link will be opened in a new tab. Defaults to false. 139 | 140 | 141 | 142 | ### Nested Schema for `snapshot` 143 | 144 | Required: 145 | 146 | - `created` (String) Time when the snapshot was created 147 | - `expires` (String) Time when the snapshot expires, default is never to expire 148 | - `external` (Boolean) Is the snapshot saved in an external grafana instance 149 | - `external_url` (String) external url, if snapshot was shared in external grafana instance 150 | - `key` (String) Optional, defined the unique key of the snapshot, required if external is true 151 | - `name` (String) Optional, name of the snapshot 152 | - `org_id` (Number) org id of the snapshot 153 | - `updated` (String) last time when the snapshot was updated 154 | - `user_id` (Number) user id of the snapshot creator 155 | 156 | Optional: 157 | 158 | - `url` (String) url of the snapshot, if snapshot was shared internally 159 | 160 | 161 | 162 | ### Nested Schema for `templating` 163 | 164 | Optional: 165 | 166 | - `list` (Attributes List) List of configured template variables with their saved values along with some other metadata (see [below for nested schema](#nestedatt--templating--list)) 167 | 168 | 169 | ### Nested Schema for `templating.list` 170 | 171 | Required: 172 | 173 | - `hide` (Number) Visibility configuration for the variable 174 | - `name` (String) Name of variable 175 | - `type` (String) Type of variable 176 | 177 | Optional: 178 | 179 | - `all_format` (String) Format to use while fetching all values from data source, eg: wildcard, glob, regex, pipe, etc. 180 | - `current` (Attributes) Shows current selected variable text/value on the dashboard (see [below for nested schema](#nestedatt--templating--list--current)) 181 | - `datasource` (Attributes) Data source used to fetch values for a variable. It can be defined but null. (see [below for nested schema](#nestedatt--templating--list--datasource)) 182 | - `description` (String) Description of variable. It can be defined but null. 183 | - `label` (String) Optional display name 184 | - `multi` (Boolean) Whether multiple values can be selected or not from variable value list. Defaults to false. 185 | - `options` (Attributes List) Options that can be selected for a variable. (see [below for nested schema](#nestedatt--templating--list--options)) 186 | - `query` (String) JSON-encoded string. Query used to fetch values for a variable 187 | - `refresh` (Number) 188 | - `skip_url_sync` (Boolean) Whether the variable value should be managed by URL query params or not. Defaults to false. 189 | 190 | 191 | ### Nested Schema for `templating.list.current` 192 | 193 | Required: 194 | 195 | - `text` (String) JSON-encoded string. Text to be displayed for the option 196 | - `value` (String) JSON-encoded string. Value of the option 197 | 198 | Optional: 199 | 200 | - `selected` (Boolean) Whether the option is selected or not 201 | 202 | 203 | 204 | ### Nested Schema for `templating.list.datasource` 205 | 206 | Optional: 207 | 208 | - `type` (String) The plugin type-id 209 | - `uid` (String) Specific datasource instance 210 | 211 | 212 | 213 | ### Nested Schema for `templating.list.options` 214 | 215 | Required: 216 | 217 | - `text` (String) JSON-encoded string. Text to be displayed for the option 218 | - `value` (String) JSON-encoded string. Value of the option 219 | 220 | Optional: 221 | 222 | - `selected` (Boolean) Whether the option is selected or not 223 | 224 | 225 | 226 | 227 | 228 | ### Nested Schema for `time` 229 | 230 | Optional: 231 | 232 | - `from` (String) Defaults to "now-6h". 233 | - `to` (String) Defaults to "now". 234 | 235 | 236 | 237 | ### Nested Schema for `timepicker` 238 | 239 | Optional: 240 | 241 | - `collapse` (Boolean) Whether timepicker is collapsed or not. Has no effect on provisioned dashboard. Defaults to false. 242 | - `enable` (Boolean) Whether timepicker is enabled or not. Has no effect on provisioned dashboard. Defaults to true. 243 | - `hidden` (Boolean) Whether timepicker is visible or not. Defaults to false. 244 | - `refresh_intervals` (List of String) Interval options available in the refresh picker dropdown. 245 | - `time_options` (List of String) Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard. 246 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 HashiCorp, Inc. 2 | 3 | Mozilla Public License Version 2.0 4 | ================================== 5 | 6 | 1. Definitions 7 | -------------- 8 | 9 | 1.1. "Contributor" 10 | means each individual or legal entity that creates, contributes to 11 | the creation of, or owns Covered Software. 12 | 13 | 1.2. "Contributor Version" 14 | means the combination of the Contributions of others (if any) used 15 | by a Contributor and that particular Contributor's Contribution. 16 | 17 | 1.3. "Contribution" 18 | means Covered Software of a particular Contributor. 19 | 20 | 1.4. "Covered Software" 21 | means Source Code Form to which the initial Contributor has attached 22 | the notice in Exhibit A, the Executable Form of such Source Code 23 | Form, and Modifications of such Source Code Form, in each case 24 | including portions thereof. 25 | 26 | 1.5. "Incompatible With Secondary Licenses" 27 | means 28 | 29 | (a) that the initial Contributor has attached the notice described 30 | in Exhibit B to the Covered Software; or 31 | 32 | (b) that the Covered Software was made available under the terms of 33 | version 1.1 or earlier of the License, but not also under the 34 | terms of a Secondary License. 35 | 36 | 1.6. "Executable Form" 37 | means any form of the work other than Source Code Form. 38 | 39 | 1.7. "Larger Work" 40 | means a work that combines Covered Software with other material, in 41 | a separate file or files, that is not Covered Software. 42 | 43 | 1.8. "License" 44 | means this document. 45 | 46 | 1.9. "Licensable" 47 | means having the right to grant, to the maximum extent possible, 48 | whether at the time of the initial grant or subsequently, any and 49 | all of the rights conveyed by this License. 50 | 51 | 1.10. "Modifications" 52 | means any of the following: 53 | 54 | (a) any file in Source Code Form that results from an addition to, 55 | deletion from, or modification of the contents of Covered 56 | Software; or 57 | 58 | (b) any new file in Source Code Form that contains any Covered 59 | Software. 60 | 61 | 1.11. "Patent Claims" of a Contributor 62 | means any patent claim(s), including without limitation, method, 63 | process, and apparatus claims, in any patent Licensable by such 64 | Contributor that would be infringed, but for the grant of the 65 | License, by the making, using, selling, offering for sale, having 66 | made, import, or transfer of either its Contributions or its 67 | Contributor Version. 68 | 69 | 1.12. "Secondary License" 70 | means either the GNU General Public License, Version 2.0, the GNU 71 | Lesser General Public License, Version 2.1, the GNU Affero General 72 | Public License, Version 3.0, or any later versions of those 73 | licenses. 74 | 75 | 1.13. "Source Code Form" 76 | means the form of the work preferred for making modifications. 77 | 78 | 1.14. "You" (or "Your") 79 | means an individual or a legal entity exercising rights under this 80 | License. For legal entities, "You" includes any entity that 81 | controls, is controlled by, or is under common control with You. For 82 | purposes of this definition, "control" means (a) the power, direct 83 | or indirect, to cause the direction or management of such entity, 84 | whether by contract or otherwise, or (b) ownership of more than 85 | fifty percent (50%) of the outstanding shares or beneficial 86 | ownership of such entity. 87 | 88 | 2. License Grants and Conditions 89 | -------------------------------- 90 | 91 | 2.1. Grants 92 | 93 | Each Contributor hereby grants You a world-wide, royalty-free, 94 | non-exclusive license: 95 | 96 | (a) under intellectual property rights (other than patent or trademark) 97 | Licensable by such Contributor to use, reproduce, make available, 98 | modify, display, perform, distribute, and otherwise exploit its 99 | Contributions, either on an unmodified basis, with Modifications, or 100 | as part of a Larger Work; and 101 | 102 | (b) under Patent Claims of such Contributor to make, use, sell, offer 103 | for sale, have made, import, and otherwise transfer either its 104 | Contributions or its Contributor Version. 105 | 106 | 2.2. Effective Date 107 | 108 | The licenses granted in Section 2.1 with respect to any Contribution 109 | become effective for each Contribution on the date the Contributor first 110 | distributes such Contribution. 111 | 112 | 2.3. Limitations on Grant Scope 113 | 114 | The licenses granted in this Section 2 are the only rights granted under 115 | this License. No additional rights or licenses will be implied from the 116 | distribution or licensing of Covered Software under this License. 117 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 118 | Contributor: 119 | 120 | (a) for any code that a Contributor has removed from Covered Software; 121 | or 122 | 123 | (b) for infringements caused by: (i) Your and any other third party's 124 | modifications of Covered Software, or (ii) the combination of its 125 | Contributions with other software (except as part of its Contributor 126 | Version); or 127 | 128 | (c) under Patent Claims infringed by Covered Software in the absence of 129 | its Contributions. 130 | 131 | This License does not grant any rights in the trademarks, service marks, 132 | or logos of any Contributor (except as may be necessary to comply with 133 | the notice requirements in Section 3.4). 134 | 135 | 2.4. Subsequent Licenses 136 | 137 | No Contributor makes additional grants as a result of Your choice to 138 | distribute the Covered Software under a subsequent version of this 139 | License (see Section 10.2) or under the terms of a Secondary License (if 140 | permitted under the terms of Section 3.3). 141 | 142 | 2.5. Representation 143 | 144 | Each Contributor represents that the Contributor believes its 145 | Contributions are its original creation(s) or it has sufficient rights 146 | to grant the rights to its Contributions conveyed by this License. 147 | 148 | 2.6. Fair Use 149 | 150 | This License is not intended to limit any rights You have under 151 | applicable copyright doctrines of fair use, fair dealing, or other 152 | equivalents. 153 | 154 | 2.7. Conditions 155 | 156 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 157 | in Section 2.1. 158 | 159 | 3. Responsibilities 160 | ------------------- 161 | 162 | 3.1. Distribution of Source Form 163 | 164 | All distribution of Covered Software in Source Code Form, including any 165 | Modifications that You create or to which You contribute, must be under 166 | the terms of this License. You must inform recipients that the Source 167 | Code Form of the Covered Software is governed by the terms of this 168 | License, and how they can obtain a copy of this License. You may not 169 | attempt to alter or restrict the recipients' rights in the Source Code 170 | Form. 171 | 172 | 3.2. Distribution of Executable Form 173 | 174 | If You distribute Covered Software in Executable Form then: 175 | 176 | (a) such Covered Software must also be made available in Source Code 177 | Form, as described in Section 3.1, and You must inform recipients of 178 | the Executable Form how they can obtain a copy of such Source Code 179 | Form by reasonable means in a timely manner, at a charge no more 180 | than the cost of distribution to the recipient; and 181 | 182 | (b) You may distribute such Executable Form under the terms of this 183 | License, or sublicense it under different terms, provided that the 184 | license for the Executable Form does not attempt to limit or alter 185 | the recipients' rights in the Source Code Form under this License. 186 | 187 | 3.3. Distribution of a Larger Work 188 | 189 | You may create and distribute a Larger Work under terms of Your choice, 190 | provided that You also comply with the requirements of this License for 191 | the Covered Software. If the Larger Work is a combination of Covered 192 | Software with a work governed by one or more Secondary Licenses, and the 193 | Covered Software is not Incompatible With Secondary Licenses, this 194 | License permits You to additionally distribute such Covered Software 195 | under the terms of such Secondary License(s), so that the recipient of 196 | the Larger Work may, at their option, further distribute the Covered 197 | Software under the terms of either this License or such Secondary 198 | License(s). 199 | 200 | 3.4. Notices 201 | 202 | You may not remove or alter the substance of any license notices 203 | (including copyright notices, patent notices, disclaimers of warranty, 204 | or limitations of liability) contained within the Source Code Form of 205 | the Covered Software, except that You may alter any license notices to 206 | the extent required to remedy known factual inaccuracies. 207 | 208 | 3.5. Application of Additional Terms 209 | 210 | You may choose to offer, and to charge a fee for, warranty, support, 211 | indemnity or liability obligations to one or more recipients of Covered 212 | Software. However, You may do so only on Your own behalf, and not on 213 | behalf of any Contributor. You must make it absolutely clear that any 214 | such warranty, support, indemnity, or liability obligation is offered by 215 | You alone, and You hereby agree to indemnify every Contributor for any 216 | liability incurred by such Contributor as a result of warranty, support, 217 | indemnity or liability terms You offer. You may include additional 218 | disclaimers of warranty and limitations of liability specific to any 219 | jurisdiction. 220 | 221 | 4. Inability to Comply Due to Statute or Regulation 222 | --------------------------------------------------- 223 | 224 | If it is impossible for You to comply with any of the terms of this 225 | License with respect to some or all of the Covered Software due to 226 | statute, judicial order, or regulation then You must: (a) comply with 227 | the terms of this License to the maximum extent possible; and (b) 228 | describe the limitations and the code they affect. Such description must 229 | be placed in a text file included with all distributions of the Covered 230 | Software under this License. Except to the extent prohibited by statute 231 | or regulation, such description must be sufficiently detailed for a 232 | recipient of ordinary skill to be able to understand it. 233 | 234 | 5. Termination 235 | -------------- 236 | 237 | 5.1. The rights granted under this License will terminate automatically 238 | if You fail to comply with any of its terms. However, if You become 239 | compliant, then the rights granted under this License from a particular 240 | Contributor are reinstated (a) provisionally, unless and until such 241 | Contributor explicitly and finally terminates Your grants, and (b) on an 242 | ongoing basis, if such Contributor fails to notify You of the 243 | non-compliance by some reasonable means prior to 60 days after You have 244 | come back into compliance. Moreover, Your grants from a particular 245 | Contributor are reinstated on an ongoing basis if such Contributor 246 | notifies You of the non-compliance by some reasonable means, this is the 247 | first time You have received notice of non-compliance with this License 248 | from such Contributor, and You become compliant prior to 30 days after 249 | Your receipt of the notice. 250 | 251 | 5.2. If You initiate litigation against any entity by asserting a patent 252 | infringement claim (excluding declaratory judgment actions, 253 | counter-claims, and cross-claims) alleging that a Contributor Version 254 | directly or indirectly infringes any patent, then the rights granted to 255 | You by any and all Contributors for the Covered Software under Section 256 | 2.1 of this License shall terminate. 257 | 258 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 259 | end user license agreements (excluding distributors and resellers) which 260 | have been validly granted by You or Your distributors under this License 261 | prior to termination shall survive termination. 262 | 263 | ************************************************************************ 264 | * * 265 | * 6. Disclaimer of Warranty * 266 | * ------------------------- * 267 | * * 268 | * Covered Software is provided under this License on an "as is" * 269 | * basis, without warranty of any kind, either expressed, implied, or * 270 | * statutory, including, without limitation, warranties that the * 271 | * Covered Software is free of defects, merchantable, fit for a * 272 | * particular purpose or non-infringing. The entire risk as to the * 273 | * quality and performance of the Covered Software is with You. * 274 | * Should any Covered Software prove defective in any respect, You * 275 | * (not any Contributor) assume the cost of any necessary servicing, * 276 | * repair, or correction. This disclaimer of warranty constitutes an * 277 | * essential part of this License. No use of any Covered Software is * 278 | * authorized under this License except under this disclaimer. * 279 | * * 280 | ************************************************************************ 281 | 282 | ************************************************************************ 283 | * * 284 | * 7. Limitation of Liability * 285 | * -------------------------- * 286 | * * 287 | * Under no circumstances and under no legal theory, whether tort * 288 | * (including negligence), contract, or otherwise, shall any * 289 | * Contributor, or anyone who distributes Covered Software as * 290 | * permitted above, be liable to You for any direct, indirect, * 291 | * special, incidental, or consequential damages of any character * 292 | * including, without limitation, damages for lost profits, loss of * 293 | * goodwill, work stoppage, computer failure or malfunction, or any * 294 | * and all other commercial damages or losses, even if such party * 295 | * shall have been informed of the possibility of such damages. This * 296 | * limitation of liability shall not apply to liability for death or * 297 | * personal injury resulting from such party's negligence to the * 298 | * extent applicable law prohibits such limitation. Some * 299 | * jurisdictions do not allow the exclusion or limitation of * 300 | * incidental or consequential damages, so this exclusion and * 301 | * limitation may not apply to You. * 302 | * * 303 | ************************************************************************ 304 | 305 | 8. Litigation 306 | ------------- 307 | 308 | Any litigation relating to this License may be brought only in the 309 | courts of a jurisdiction where the defendant maintains its principal 310 | place of business and such litigation shall be governed by laws of that 311 | jurisdiction, without reference to its conflict-of-law provisions. 312 | Nothing in this Section shall prevent a party's ability to bring 313 | cross-claims or counter-claims. 314 | 315 | 9. Miscellaneous 316 | ---------------- 317 | 318 | This License represents the complete agreement concerning the subject 319 | matter hereof. If any provision of this License is held to be 320 | unenforceable, such provision shall be reformed only to the extent 321 | necessary to make it enforceable. Any law or regulation which provides 322 | that the language of a contract shall be construed against the drafter 323 | shall not be used to construe this License against a Contributor. 324 | 325 | 10. Versions of the License 326 | --------------------------- 327 | 328 | 10.1. New Versions 329 | 330 | Mozilla Foundation is the license steward. Except as provided in Section 331 | 10.3, no one other than the license steward has the right to modify or 332 | publish new versions of this License. Each version will be given a 333 | distinguishing version number. 334 | 335 | 10.2. Effect of New Versions 336 | 337 | You may distribute the Covered Software under the terms of the version 338 | of the License under which You originally received the Covered Software, 339 | or under the terms of any subsequent version published by the license 340 | steward. 341 | 342 | 10.3. Modified Versions 343 | 344 | If you create software not governed by this License, and you want to 345 | create a new license for such software, you may create and use a 346 | modified version of this License if you rename the license and remove 347 | any references to the name of the license steward (except to note that 348 | such modified license differs from this License). 349 | 350 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 351 | Licenses 352 | 353 | If You choose to distribute Source Code Form that is Incompatible With 354 | Secondary Licenses under the terms of this version of the License, the 355 | notice described in Exhibit B of this License must be attached. 356 | 357 | Exhibit A - Source Code Form License Notice 358 | ------------------------------------------- 359 | 360 | This Source Code Form is subject to the terms of the Mozilla Public 361 | License, v. 2.0. If a copy of the MPL was not distributed with this 362 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 363 | 364 | If it is not possible or desirable to put the notice in a particular 365 | file, then You may include the notice in a location (such as a LICENSE 366 | file in a relevant directory) where a recipient would be likely to look 367 | for such a notice. 368 | 369 | You may add additional accurate notices of copyright ownership. 370 | 371 | Exhibit B - "Incompatible With Secondary Licenses" Notice 372 | --------------------------------------------------------- 373 | 374 | This Source Code Form is "Incompatible With Secondary Licenses", as 375 | defined by the Mozilla Public License, v. 2.0. 376 | -------------------------------------------------------------------------------- /docs/data-sources/panel_alert_groups.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_panel_alert_groups Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_panel_alert_groups (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Optional 19 | 20 | - `datasource` (Attributes) The datasource used in all targets. (see [below for nested schema](#nestedatt--datasource)) 21 | - `description` (String) Panel description. 22 | - `field_config` (Attributes) Field options allow you to change how the data is displayed in your visualizations. (see [below for nested schema](#nestedatt--field_config)) 23 | - `grid_pos` (Attributes) Grid position. (see [below for nested schema](#nestedatt--grid_pos)) 24 | - `interval` (String) The min time interval setting defines a lower limit for the $__interval and $__interval_ms variables. 25 | This value must be formatted as a number followed by a valid time 26 | identifier like: "40s", "3d", etc. 27 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 28 | - `library_panel` (Attributes) Dynamically load the panel (see [below for nested schema](#nestedatt--library_panel)) 29 | - `links` (Attributes List) Panel links. (see [below for nested schema](#nestedatt--links)) 30 | - `max_data_points` (Number) The maximum number of data points that the panel queries are retrieving. 31 | - `options` (Attributes) (see [below for nested schema](#nestedatt--options)) 32 | - `plugin_version` (String) The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs. 33 | - `repeat` (String) Name of template variable to repeat for. 34 | - `repeat_direction` (String) Direction to repeat in if 'repeat' is set. 35 | h for horizontal, v for vertical. Defaults to "h". 36 | - `repeat_panel_id` (Number) Id of the repeating panel. 37 | - `tags` (List of String) Tags for the panel. 38 | - `targets` (List of String) Depends on the panel plugin. See the plugin documentation for details. 39 | - `time_from` (String) Overrides the relative time range for individual panels, 40 | which causes them to be different than what is selected in 41 | the dashboard time picker in the top-right corner of the dashboard. You can use this to show metrics from different 42 | time periods or days on the same dashboard. 43 | The value is formatted as time operation like: now-5m (Last 5 minutes), now/d (the day so far), 44 | now-5d/d(Last 5 days), now/w (This week so far), now-2y/y (Last 2 years). 45 | Note: Panel time overrides have no effect when the dashboard’s time range is absolute. 46 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 47 | - `time_shift` (String) Overrides the time range for individual panels by shifting its start and end relative to the time picker. 48 | For example, you can shift the time range for the panel to be two hours earlier than the dashboard time picker setting 2h. 49 | Note: Panel time overrides have no effect when the dashboard’s time range is absolute. 50 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 51 | - `title` (String) Panel title. 52 | - `transformations` (Attributes List) List of transformations that are applied to the panel data before rendering. 53 | When there are multiple transformations, Grafana applies them in the order they are listed. 54 | Each transformation creates a result set that then passes on to the next transformation in the processing pipeline. (see [below for nested schema](#nestedatt--transformations)) 55 | - `transparent` (Boolean) Whether to display the panel without a background. Defaults to false. 56 | - `type` (String) The panel plugin type id. This is used to find the plugin to display the panel. Defaults to "alertGroups". 57 | 58 | ### Read-Only 59 | 60 | - `rendered_json` (String) This datasource rendered as JSON 61 | 62 | 63 | ### Nested Schema for `datasource` 64 | 65 | Optional: 66 | 67 | - `type` (String) The plugin type-id 68 | - `uid` (String) Specific datasource instance 69 | 70 | 71 | 72 | ### Nested Schema for `field_config` 73 | 74 | Optional: 75 | 76 | - `defaults` (Attributes) Defaults are the options applied to all fields. (see [below for nested schema](#nestedatt--field_config--defaults)) 77 | - `overrides` (Attributes List) Overrides are the options applied to specific fields overriding the defaults. (see [below for nested schema](#nestedatt--field_config--overrides)) 78 | 79 | 80 | ### Nested Schema for `field_config.defaults` 81 | 82 | Optional: 83 | 84 | - `color` (Attributes) Panel color configuration (see [below for nested schema](#nestedatt--field_config--defaults--color)) 85 | - `custom` (Attributes) custom is specified by the FieldConfig field 86 | in panel plugin schemas. (see [below for nested schema](#nestedatt--field_config--defaults--custom)) 87 | - `decimals` (Number) Specify the number of decimals Grafana includes in the rendered value. 88 | If you leave this field blank, Grafana automatically truncates the number of decimals based on the value. 89 | For example 1.1234 will display as 1.12 and 100.456 will display as 100. 90 | To display all decimals, set the unit to String. 91 | - `description` (String) Human readable field metadata 92 | - `display_name` (String) The display value for this field. This supports template variables blank is auto 93 | - `display_name_from_ds` (String) This can be used by data sources that return and explicit naming structure for values and labels 94 | When this property is configured, this value is used rather than the default naming strategy. 95 | - `filterable` (Boolean) True if data source field supports ad-hoc filters 96 | - `mappings` (Attributes List) Convert input values into a display string (see [below for nested schema](#nestedatt--field_config--defaults--mappings)) 97 | - `max` (Number) The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields. 98 | - `min` (Number) The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields. 99 | - `no_value` (String) Alternative to empty string 100 | - `path` (String) An explicit path to the field in the datasource. When the frame meta includes a path, 101 | This will default to ${frame.meta.path}/${field.name} 102 | 103 | When defined, this value can be used as an identifier within the datasource scope, and 104 | may be used to update the results 105 | - `thresholds` (Attributes) Map numeric values to states (see [below for nested schema](#nestedatt--field_config--defaults--thresholds)) 106 | - `unit` (String) Unit a field should use. The unit you select is applied to all fields except time. 107 | You can use the units ID availables in Grafana or a custom unit. 108 | Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts 109 | As custom unit, you can use the following formats: 110 | suffix: for custom unit that should go after value. 111 | prefix: for custom unit that should go before value. 112 | time: For custom date time formats type for example time:YYYY-MM-DD. 113 | si: for custom SI units. For example: si: mF. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character. 114 | count: for a custom count unit. 115 | currency: for custom a currency unit. 116 | - `writeable` (Boolean) True if data source can write a value to the path. Auth/authz are supported separately 117 | 118 | 119 | ### Nested Schema for `field_config.defaults.color` 120 | 121 | Required: 122 | 123 | - `mode` (String) The main color scheme mode. 124 | 125 | Optional: 126 | 127 | - `fixed_color` (String) The fixed color value for fixed or shades color modes. 128 | - `series_by` (String) Some visualizations need to know how to assign a series color from by value color schemes. 129 | 130 | 131 | 132 | ### Nested Schema for `field_config.defaults.custom` 133 | 134 | 135 | 136 | ### Nested Schema for `field_config.defaults.mappings` 137 | 138 | Optional: 139 | 140 | - `range_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--range_map)) 141 | - `regex_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--regex_map)) 142 | - `special_value_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--special_value_map)) 143 | - `value_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map)) 144 | 145 | 146 | ### Nested Schema for `field_config.defaults.mappings.value_map` 147 | 148 | Required: 149 | 150 | - `type` (String) 151 | 152 | Optional: 153 | 154 | - `options` (Attributes) Range to match against and the result to apply when the value is within the range (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 155 | 156 | 157 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 158 | 159 | Required: 160 | 161 | - `from` (String) Min value of the range. It can be null which means -Infinity 162 | - `to` (String) Max value of the range. It can be null which means +Infinity 163 | 164 | Optional: 165 | 166 | - `result` (Attributes) Config to apply when the value is within the range (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 167 | 168 | 169 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 170 | 171 | Optional: 172 | 173 | - `color` (String) Text to use when the value matches 174 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 175 | - `index` (Number) Position in the mapping array. Only used internally. 176 | - `text` (String) Text to display when the value matches 177 | 178 | 179 | 180 | 181 | 182 | ### Nested Schema for `field_config.defaults.mappings.value_map` 183 | 184 | Required: 185 | 186 | - `type` (String) 187 | 188 | Optional: 189 | 190 | - `options` (Attributes) Regular expression to match against and the result to apply when the value matches the regex (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 191 | 192 | 193 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 194 | 195 | Required: 196 | 197 | - `pattern` (String) Regular expression to match against 198 | 199 | Optional: 200 | 201 | - `result` (Attributes) Config to apply when the value matches the regex (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 202 | 203 | 204 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 205 | 206 | Optional: 207 | 208 | - `color` (String) Text to use when the value matches 209 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 210 | - `index` (Number) Position in the mapping array. Only used internally. 211 | - `text` (String) Text to display when the value matches 212 | 213 | 214 | 215 | 216 | 217 | ### Nested Schema for `field_config.defaults.mappings.value_map` 218 | 219 | Required: 220 | 221 | - `type` (String) 222 | 223 | Optional: 224 | 225 | - `options` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 226 | 227 | 228 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 229 | 230 | Required: 231 | 232 | - `match` (String) Special value to match against 233 | 234 | Optional: 235 | 236 | - `result` (Attributes) Config to apply when the value matches the special value (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 237 | 238 | 239 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 240 | 241 | Optional: 242 | 243 | - `color` (String) Text to use when the value matches 244 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 245 | - `index` (Number) Position in the mapping array. Only used internally. 246 | - `text` (String) Text to display when the value matches 247 | 248 | 249 | 250 | 251 | 252 | ### Nested Schema for `field_config.defaults.mappings.value_map` 253 | 254 | Required: 255 | 256 | - `type` (String) 257 | 258 | Optional: 259 | 260 | - `options` (Attributes Map) Map with : ValueMappingResult. For example: { "10": { text: "Perfection!", color: "green" } } (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 261 | 262 | 263 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 264 | 265 | Optional: 266 | 267 | - `color` (String) Text to use when the value matches 268 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 269 | - `index` (Number) Position in the mapping array. Only used internally. 270 | - `text` (String) Text to display when the value matches 271 | 272 | 273 | 274 | 275 | 276 | ### Nested Schema for `field_config.defaults.thresholds` 277 | 278 | Required: 279 | 280 | - `mode` (String) Thresholds mode. 281 | 282 | Optional: 283 | 284 | - `steps` (Attributes List) Must be sorted by 'value', first value is always -Infinity (see [below for nested schema](#nestedatt--field_config--defaults--thresholds--steps)) 285 | 286 | 287 | ### Nested Schema for `field_config.defaults.thresholds.steps` 288 | 289 | Required: 290 | 291 | - `color` (String) Color represents the color of the visual change that will occur in the dashboard when the threshold value is met or exceeded. 292 | - `value` (String) Value represents a specified metric for the threshold, which triggers a visual change in the dashboard when this value is met or exceeded. 293 | Nulls currently appear here when serializing -Infinity to JSON. 294 | 295 | 296 | 297 | 298 | 299 | ### Nested Schema for `field_config.overrides` 300 | 301 | Optional: 302 | 303 | - `matcher` (Attributes) (see [below for nested schema](#nestedatt--field_config--overrides--matcher)) 304 | - `properties` (Attributes List) (see [below for nested schema](#nestedatt--field_config--overrides--properties)) 305 | 306 | 307 | ### Nested Schema for `field_config.overrides.matcher` 308 | 309 | 310 | 311 | ### Nested Schema for `field_config.overrides.properties` 312 | 313 | 314 | 315 | 316 | 317 | ### Nested Schema for `grid_pos` 318 | 319 | Optional: 320 | 321 | - `h` (Number) Panel height. The height is the number of rows from the top edge of the panel. Defaults to 9. 322 | - `static` (Boolean) Whether the panel is fixed within the grid. If true, the panel will not be affected by other panels' interactions 323 | - `w` (Number) Panel width. The width is the number of columns from the left edge of the panel. Defaults to 12. 324 | - `x` (Number) Panel x. The x coordinate is the number of columns from the left edge of the grid. Defaults to 0. 325 | - `y` (Number) Panel y. The y coordinate is the number of rows from the top edge of the grid. Defaults to 0. 326 | 327 | 328 | 329 | ### Nested Schema for `library_panel` 330 | 331 | Required: 332 | 333 | - `name` (String) Library panel name 334 | - `uid` (String) Library panel uid 335 | 336 | 337 | 338 | ### Nested Schema for `links` 339 | 340 | Required: 341 | 342 | - `icon` (String) Icon name to be displayed with the link 343 | - `title` (String) Title to display with the link 344 | - `tooltip` (String) Tooltip to display when the user hovers their mouse over it 345 | - `type` (String) Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource) 346 | - `url` (String) Link URL. Only required/valid if the type is link 347 | 348 | Optional: 349 | 350 | - `as_dropdown` (Boolean) If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards. Defaults to false. 351 | - `include_vars` (Boolean) If true, includes current template variables values in the link as query params. Defaults to false. 352 | - `keep_time` (Boolean) If true, includes current time range in the link as query params. Defaults to false. 353 | - `tags` (List of String) List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards 354 | - `target_blank` (Boolean) If true, the link will be opened in a new tab. Defaults to false. 355 | 356 | 357 | 358 | ### Nested Schema for `options` 359 | 360 | Required: 361 | 362 | - `alertmanager` (String) Name of the alertmanager used as a source for alerts 363 | - `expand_all` (Boolean) Expand all alert groups by default 364 | - `labels` (String) Comma-separated list of values used to filter alert results 365 | 366 | 367 | 368 | ### Nested Schema for `transformations` 369 | 370 | Optional: 371 | 372 | - `disabled` (Boolean) Disabled transformations are skipped 373 | - `filter` (Attributes) Optional frame matcher. When missing it will be applied to all results (see [below for nested schema](#nestedatt--transformations--filter)) 374 | 375 | 376 | ### Nested Schema for `transformations.filter` 377 | -------------------------------------------------------------------------------- /docs/data-sources/panel_annotations_list.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_panel_annotations_list Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_panel_annotations_list (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Optional 19 | 20 | - `datasource` (Attributes) The datasource used in all targets. (see [below for nested schema](#nestedatt--datasource)) 21 | - `description` (String) Panel description. 22 | - `field_config` (Attributes) Field options allow you to change how the data is displayed in your visualizations. (see [below for nested schema](#nestedatt--field_config)) 23 | - `grid_pos` (Attributes) Grid position. (see [below for nested schema](#nestedatt--grid_pos)) 24 | - `interval` (String) The min time interval setting defines a lower limit for the $__interval and $__interval_ms variables. 25 | This value must be formatted as a number followed by a valid time 26 | identifier like: "40s", "3d", etc. 27 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 28 | - `library_panel` (Attributes) Dynamically load the panel (see [below for nested schema](#nestedatt--library_panel)) 29 | - `links` (Attributes List) Panel links. (see [below for nested schema](#nestedatt--links)) 30 | - `max_data_points` (Number) The maximum number of data points that the panel queries are retrieving. 31 | - `options` (Attributes) (see [below for nested schema](#nestedatt--options)) 32 | - `plugin_version` (String) The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs. 33 | - `repeat` (String) Name of template variable to repeat for. 34 | - `repeat_direction` (String) Direction to repeat in if 'repeat' is set. 35 | h for horizontal, v for vertical. Defaults to "h". 36 | - `repeat_panel_id` (Number) Id of the repeating panel. 37 | - `tags` (List of String) Tags for the panel. 38 | - `targets` (List of String) Depends on the panel plugin. See the plugin documentation for details. 39 | - `time_from` (String) Overrides the relative time range for individual panels, 40 | which causes them to be different than what is selected in 41 | the dashboard time picker in the top-right corner of the dashboard. You can use this to show metrics from different 42 | time periods or days on the same dashboard. 43 | The value is formatted as time operation like: now-5m (Last 5 minutes), now/d (the day so far), 44 | now-5d/d(Last 5 days), now/w (This week so far), now-2y/y (Last 2 years). 45 | Note: Panel time overrides have no effect when the dashboard’s time range is absolute. 46 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 47 | - `time_shift` (String) Overrides the time range for individual panels by shifting its start and end relative to the time picker. 48 | For example, you can shift the time range for the panel to be two hours earlier than the dashboard time picker setting 2h. 49 | Note: Panel time overrides have no effect when the dashboard’s time range is absolute. 50 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 51 | - `title` (String) Panel title. 52 | - `transformations` (Attributes List) List of transformations that are applied to the panel data before rendering. 53 | When there are multiple transformations, Grafana applies them in the order they are listed. 54 | Each transformation creates a result set that then passes on to the next transformation in the processing pipeline. (see [below for nested schema](#nestedatt--transformations)) 55 | - `transparent` (Boolean) Whether to display the panel without a background. Defaults to false. 56 | - `type` (String) The panel plugin type id. This is used to find the plugin to display the panel. Defaults to "annolist". 57 | 58 | ### Read-Only 59 | 60 | - `rendered_json` (String) This datasource rendered as JSON 61 | 62 | 63 | ### Nested Schema for `datasource` 64 | 65 | Optional: 66 | 67 | - `type` (String) The plugin type-id 68 | - `uid` (String) Specific datasource instance 69 | 70 | 71 | 72 | ### Nested Schema for `field_config` 73 | 74 | Optional: 75 | 76 | - `defaults` (Attributes) Defaults are the options applied to all fields. (see [below for nested schema](#nestedatt--field_config--defaults)) 77 | - `overrides` (Attributes List) Overrides are the options applied to specific fields overriding the defaults. (see [below for nested schema](#nestedatt--field_config--overrides)) 78 | 79 | 80 | ### Nested Schema for `field_config.defaults` 81 | 82 | Optional: 83 | 84 | - `color` (Attributes) Panel color configuration (see [below for nested schema](#nestedatt--field_config--defaults--color)) 85 | - `custom` (Attributes) custom is specified by the FieldConfig field 86 | in panel plugin schemas. (see [below for nested schema](#nestedatt--field_config--defaults--custom)) 87 | - `decimals` (Number) Specify the number of decimals Grafana includes in the rendered value. 88 | If you leave this field blank, Grafana automatically truncates the number of decimals based on the value. 89 | For example 1.1234 will display as 1.12 and 100.456 will display as 100. 90 | To display all decimals, set the unit to String. 91 | - `description` (String) Human readable field metadata 92 | - `display_name` (String) The display value for this field. This supports template variables blank is auto 93 | - `display_name_from_ds` (String) This can be used by data sources that return and explicit naming structure for values and labels 94 | When this property is configured, this value is used rather than the default naming strategy. 95 | - `filterable` (Boolean) True if data source field supports ad-hoc filters 96 | - `mappings` (Attributes List) Convert input values into a display string (see [below for nested schema](#nestedatt--field_config--defaults--mappings)) 97 | - `max` (Number) The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields. 98 | - `min` (Number) The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields. 99 | - `no_value` (String) Alternative to empty string 100 | - `path` (String) An explicit path to the field in the datasource. When the frame meta includes a path, 101 | This will default to ${frame.meta.path}/${field.name} 102 | 103 | When defined, this value can be used as an identifier within the datasource scope, and 104 | may be used to update the results 105 | - `thresholds` (Attributes) Map numeric values to states (see [below for nested schema](#nestedatt--field_config--defaults--thresholds)) 106 | - `unit` (String) Unit a field should use. The unit you select is applied to all fields except time. 107 | You can use the units ID availables in Grafana or a custom unit. 108 | Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts 109 | As custom unit, you can use the following formats: 110 | suffix: for custom unit that should go after value. 111 | prefix: for custom unit that should go before value. 112 | time: For custom date time formats type for example time:YYYY-MM-DD. 113 | si: for custom SI units. For example: si: mF. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character. 114 | count: for a custom count unit. 115 | currency: for custom a currency unit. 116 | - `writeable` (Boolean) True if data source can write a value to the path. Auth/authz are supported separately 117 | 118 | 119 | ### Nested Schema for `field_config.defaults.color` 120 | 121 | Required: 122 | 123 | - `mode` (String) The main color scheme mode. 124 | 125 | Optional: 126 | 127 | - `fixed_color` (String) The fixed color value for fixed or shades color modes. 128 | - `series_by` (String) Some visualizations need to know how to assign a series color from by value color schemes. 129 | 130 | 131 | 132 | ### Nested Schema for `field_config.defaults.custom` 133 | 134 | 135 | 136 | ### Nested Schema for `field_config.defaults.mappings` 137 | 138 | Optional: 139 | 140 | - `range_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--range_map)) 141 | - `regex_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--regex_map)) 142 | - `special_value_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--special_value_map)) 143 | - `value_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map)) 144 | 145 | 146 | ### Nested Schema for `field_config.defaults.mappings.value_map` 147 | 148 | Required: 149 | 150 | - `type` (String) 151 | 152 | Optional: 153 | 154 | - `options` (Attributes) Range to match against and the result to apply when the value is within the range (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 155 | 156 | 157 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 158 | 159 | Required: 160 | 161 | - `from` (String) Min value of the range. It can be null which means -Infinity 162 | - `to` (String) Max value of the range. It can be null which means +Infinity 163 | 164 | Optional: 165 | 166 | - `result` (Attributes) Config to apply when the value is within the range (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 167 | 168 | 169 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 170 | 171 | Optional: 172 | 173 | - `color` (String) Text to use when the value matches 174 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 175 | - `index` (Number) Position in the mapping array. Only used internally. 176 | - `text` (String) Text to display when the value matches 177 | 178 | 179 | 180 | 181 | 182 | ### Nested Schema for `field_config.defaults.mappings.value_map` 183 | 184 | Required: 185 | 186 | - `type` (String) 187 | 188 | Optional: 189 | 190 | - `options` (Attributes) Regular expression to match against and the result to apply when the value matches the regex (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 191 | 192 | 193 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 194 | 195 | Required: 196 | 197 | - `pattern` (String) Regular expression to match against 198 | 199 | Optional: 200 | 201 | - `result` (Attributes) Config to apply when the value matches the regex (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 202 | 203 | 204 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 205 | 206 | Optional: 207 | 208 | - `color` (String) Text to use when the value matches 209 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 210 | - `index` (Number) Position in the mapping array. Only used internally. 211 | - `text` (String) Text to display when the value matches 212 | 213 | 214 | 215 | 216 | 217 | ### Nested Schema for `field_config.defaults.mappings.value_map` 218 | 219 | Required: 220 | 221 | - `type` (String) 222 | 223 | Optional: 224 | 225 | - `options` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 226 | 227 | 228 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 229 | 230 | Required: 231 | 232 | - `match` (String) Special value to match against 233 | 234 | Optional: 235 | 236 | - `result` (Attributes) Config to apply when the value matches the special value (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 237 | 238 | 239 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 240 | 241 | Optional: 242 | 243 | - `color` (String) Text to use when the value matches 244 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 245 | - `index` (Number) Position in the mapping array. Only used internally. 246 | - `text` (String) Text to display when the value matches 247 | 248 | 249 | 250 | 251 | 252 | ### Nested Schema for `field_config.defaults.mappings.value_map` 253 | 254 | Required: 255 | 256 | - `type` (String) 257 | 258 | Optional: 259 | 260 | - `options` (Attributes Map) Map with : ValueMappingResult. For example: { "10": { text: "Perfection!", color: "green" } } (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 261 | 262 | 263 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 264 | 265 | Optional: 266 | 267 | - `color` (String) Text to use when the value matches 268 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 269 | - `index` (Number) Position in the mapping array. Only used internally. 270 | - `text` (String) Text to display when the value matches 271 | 272 | 273 | 274 | 275 | 276 | ### Nested Schema for `field_config.defaults.thresholds` 277 | 278 | Required: 279 | 280 | - `mode` (String) Thresholds mode. 281 | 282 | Optional: 283 | 284 | - `steps` (Attributes List) Must be sorted by 'value', first value is always -Infinity (see [below for nested schema](#nestedatt--field_config--defaults--thresholds--steps)) 285 | 286 | 287 | ### Nested Schema for `field_config.defaults.thresholds.steps` 288 | 289 | Required: 290 | 291 | - `color` (String) Color represents the color of the visual change that will occur in the dashboard when the threshold value is met or exceeded. 292 | - `value` (String) Value represents a specified metric for the threshold, which triggers a visual change in the dashboard when this value is met or exceeded. 293 | Nulls currently appear here when serializing -Infinity to JSON. 294 | 295 | 296 | 297 | 298 | 299 | ### Nested Schema for `field_config.overrides` 300 | 301 | Optional: 302 | 303 | - `matcher` (Attributes) (see [below for nested schema](#nestedatt--field_config--overrides--matcher)) 304 | - `properties` (Attributes List) (see [below for nested schema](#nestedatt--field_config--overrides--properties)) 305 | 306 | 307 | ### Nested Schema for `field_config.overrides.matcher` 308 | 309 | 310 | 311 | ### Nested Schema for `field_config.overrides.properties` 312 | 313 | 314 | 315 | 316 | 317 | ### Nested Schema for `grid_pos` 318 | 319 | Optional: 320 | 321 | - `h` (Number) Panel height. The height is the number of rows from the top edge of the panel. Defaults to 9. 322 | - `static` (Boolean) Whether the panel is fixed within the grid. If true, the panel will not be affected by other panels' interactions 323 | - `w` (Number) Panel width. The width is the number of columns from the left edge of the panel. Defaults to 12. 324 | - `x` (Number) Panel x. The x coordinate is the number of columns from the left edge of the grid. Defaults to 0. 325 | - `y` (Number) Panel y. The y coordinate is the number of rows from the top edge of the grid. Defaults to 0. 326 | 327 | 328 | 329 | ### Nested Schema for `library_panel` 330 | 331 | Required: 332 | 333 | - `name` (String) Library panel name 334 | - `uid` (String) Library panel uid 335 | 336 | 337 | 338 | ### Nested Schema for `links` 339 | 340 | Required: 341 | 342 | - `icon` (String) Icon name to be displayed with the link 343 | - `title` (String) Title to display with the link 344 | - `tooltip` (String) Tooltip to display when the user hovers their mouse over it 345 | - `type` (String) Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource) 346 | - `url` (String) Link URL. Only required/valid if the type is link 347 | 348 | Optional: 349 | 350 | - `as_dropdown` (Boolean) If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards. Defaults to false. 351 | - `include_vars` (Boolean) If true, includes current template variables values in the link as query params. Defaults to false. 352 | - `keep_time` (Boolean) If true, includes current time range in the link as query params. Defaults to false. 353 | - `tags` (List of String) List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards 354 | - `target_blank` (Boolean) If true, the link will be opened in a new tab. Defaults to false. 355 | 356 | 357 | 358 | ### Nested Schema for `options` 359 | 360 | Optional: 361 | 362 | - `limit` (Number) Defaults to 10. 363 | - `navigate_after` (String) Defaults to "10m". 364 | - `navigate_before` (String) Defaults to "10m". 365 | - `navigate_to_panel` (Boolean) Defaults to true. 366 | - `only_from_this_dashboard` (Boolean) Defaults to false. 367 | - `only_in_time_range` (Boolean) Defaults to false. 368 | - `show_tags` (Boolean) Defaults to true. 369 | - `show_time` (Boolean) Defaults to true. 370 | - `show_user` (Boolean) Defaults to true. 371 | - `tags` (List of String) 372 | 373 | 374 | 375 | ### Nested Schema for `transformations` 376 | 377 | Optional: 378 | 379 | - `disabled` (Boolean) Disabled transformations are skipped 380 | - `filter` (Attributes) Optional frame matcher. When missing it will be applied to all results (see [below for nested schema](#nestedatt--transformations--filter)) 381 | 382 | 383 | ### Nested Schema for `transformations.filter` 384 | -------------------------------------------------------------------------------- /docs/data-sources/panel_text.md: -------------------------------------------------------------------------------- 1 | --- 2 | # generated by https://github.com/hashicorp/terraform-plugin-docs 3 | page_title: "schemas_panel_text Data Source - terraform-provider-schemas" 4 | subcategory: "" 5 | description: |- 6 | 7 | --- 8 | 9 | # schemas_panel_text (Data Source) 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Schema 17 | 18 | ### Optional 19 | 20 | - `datasource` (Attributes) The datasource used in all targets. (see [below for nested schema](#nestedatt--datasource)) 21 | - `description` (String) Panel description. 22 | - `field_config` (Attributes) Field options allow you to change how the data is displayed in your visualizations. (see [below for nested schema](#nestedatt--field_config)) 23 | - `grid_pos` (Attributes) Grid position. (see [below for nested schema](#nestedatt--grid_pos)) 24 | - `interval` (String) The min time interval setting defines a lower limit for the $__interval and $__interval_ms variables. 25 | This value must be formatted as a number followed by a valid time 26 | identifier like: "40s", "3d", etc. 27 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 28 | - `library_panel` (Attributes) Dynamically load the panel (see [below for nested schema](#nestedatt--library_panel)) 29 | - `links` (Attributes List) Panel links. (see [below for nested schema](#nestedatt--links)) 30 | - `max_data_points` (Number) The maximum number of data points that the panel queries are retrieving. 31 | - `options` (Attributes) (see [below for nested schema](#nestedatt--options)) 32 | - `plugin_version` (String) The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs. 33 | - `repeat` (String) Name of template variable to repeat for. 34 | - `repeat_direction` (String) Direction to repeat in if 'repeat' is set. 35 | h for horizontal, v for vertical. Defaults to "h". 36 | - `repeat_panel_id` (Number) Id of the repeating panel. 37 | - `tags` (List of String) Tags for the panel. 38 | - `targets` (List of String) Depends on the panel plugin. See the plugin documentation for details. 39 | - `time_from` (String) Overrides the relative time range for individual panels, 40 | which causes them to be different than what is selected in 41 | the dashboard time picker in the top-right corner of the dashboard. You can use this to show metrics from different 42 | time periods or days on the same dashboard. 43 | The value is formatted as time operation like: now-5m (Last 5 minutes), now/d (the day so far), 44 | now-5d/d(Last 5 days), now/w (This week so far), now-2y/y (Last 2 years). 45 | Note: Panel time overrides have no effect when the dashboard’s time range is absolute. 46 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 47 | - `time_shift` (String) Overrides the time range for individual panels by shifting its start and end relative to the time picker. 48 | For example, you can shift the time range for the panel to be two hours earlier than the dashboard time picker setting 2h. 49 | Note: Panel time overrides have no effect when the dashboard’s time range is absolute. 50 | See: https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/#query-options 51 | - `title` (String) Panel title. 52 | - `transformations` (Attributes List) List of transformations that are applied to the panel data before rendering. 53 | When there are multiple transformations, Grafana applies them in the order they are listed. 54 | Each transformation creates a result set that then passes on to the next transformation in the processing pipeline. (see [below for nested schema](#nestedatt--transformations)) 55 | - `transparent` (Boolean) Whether to display the panel without a background. Defaults to false. 56 | - `type` (String) The panel plugin type id. This is used to find the plugin to display the panel. Defaults to "text". 57 | 58 | ### Read-Only 59 | 60 | - `rendered_json` (String) This datasource rendered as JSON 61 | 62 | 63 | ### Nested Schema for `datasource` 64 | 65 | Optional: 66 | 67 | - `type` (String) The plugin type-id 68 | - `uid` (String) Specific datasource instance 69 | 70 | 71 | 72 | ### Nested Schema for `field_config` 73 | 74 | Optional: 75 | 76 | - `defaults` (Attributes) Defaults are the options applied to all fields. (see [below for nested schema](#nestedatt--field_config--defaults)) 77 | - `overrides` (Attributes List) Overrides are the options applied to specific fields overriding the defaults. (see [below for nested schema](#nestedatt--field_config--overrides)) 78 | 79 | 80 | ### Nested Schema for `field_config.defaults` 81 | 82 | Optional: 83 | 84 | - `color` (Attributes) Panel color configuration (see [below for nested schema](#nestedatt--field_config--defaults--color)) 85 | - `custom` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--custom)) 86 | - `decimals` (Number) Specify the number of decimals Grafana includes in the rendered value. 87 | If you leave this field blank, Grafana automatically truncates the number of decimals based on the value. 88 | For example 1.1234 will display as 1.12 and 100.456 will display as 100. 89 | To display all decimals, set the unit to String. 90 | - `description` (String) Human readable field metadata 91 | - `display_name` (String) The display value for this field. This supports template variables blank is auto 92 | - `display_name_from_ds` (String) This can be used by data sources that return and explicit naming structure for values and labels 93 | When this property is configured, this value is used rather than the default naming strategy. 94 | - `filterable` (Boolean) True if data source field supports ad-hoc filters 95 | - `mappings` (Attributes List) Convert input values into a display string (see [below for nested schema](#nestedatt--field_config--defaults--mappings)) 96 | - `max` (Number) The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields. 97 | - `min` (Number) The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields. 98 | - `no_value` (String) Alternative to empty string 99 | - `path` (String) An explicit path to the field in the datasource. When the frame meta includes a path, 100 | This will default to ${frame.meta.path}/${field.name} 101 | 102 | When defined, this value can be used as an identifier within the datasource scope, and 103 | may be used to update the results 104 | - `thresholds` (Attributes) Map numeric values to states (see [below for nested schema](#nestedatt--field_config--defaults--thresholds)) 105 | - `unit` (String) Unit a field should use. The unit you select is applied to all fields except time. 106 | You can use the units ID availables in Grafana or a custom unit. 107 | Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts 108 | As custom unit, you can use the following formats: 109 | suffix: for custom unit that should go after value. 110 | prefix: for custom unit that should go before value. 111 | time: For custom date time formats type for example time:YYYY-MM-DD. 112 | si: for custom SI units. For example: si: mF. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character. 113 | count: for a custom count unit. 114 | currency: for custom a currency unit. 115 | - `writeable` (Boolean) True if data source can write a value to the path. Auth/authz are supported separately 116 | 117 | 118 | ### Nested Schema for `field_config.defaults.color` 119 | 120 | Required: 121 | 122 | - `mode` (String) The main color scheme mode. 123 | 124 | Optional: 125 | 126 | - `fixed_color` (String) The fixed color value for fixed or shades color modes. 127 | - `series_by` (String) Some visualizations need to know how to assign a series color from by value color schemes. 128 | 129 | 130 | 131 | ### Nested Schema for `field_config.defaults.custom` 132 | 133 | Optional: 134 | 135 | - `fill_opacity` (Number) Defaults to 70. 136 | - `hide_from` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--custom--hide_from)) 137 | - `line_width` (Number) Defaults to 1. 138 | 139 | 140 | ### Nested Schema for `field_config.defaults.custom.line_width` 141 | 142 | Required: 143 | 144 | - `legend` (Boolean) 145 | - `tooltip` (Boolean) 146 | - `viz` (Boolean) 147 | 148 | 149 | 150 | 151 | ### Nested Schema for `field_config.defaults.mappings` 152 | 153 | Optional: 154 | 155 | - `range_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--range_map)) 156 | - `regex_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--regex_map)) 157 | - `special_value_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--special_value_map)) 158 | - `value_map` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map)) 159 | 160 | 161 | ### Nested Schema for `field_config.defaults.mappings.value_map` 162 | 163 | Required: 164 | 165 | - `type` (String) 166 | 167 | Optional: 168 | 169 | - `options` (Attributes) Range to match against and the result to apply when the value is within the range (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 170 | 171 | 172 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 173 | 174 | Required: 175 | 176 | - `from` (String) Min value of the range. It can be null which means -Infinity 177 | - `to` (String) Max value of the range. It can be null which means +Infinity 178 | 179 | Optional: 180 | 181 | - `result` (Attributes) Config to apply when the value is within the range (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 182 | 183 | 184 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 185 | 186 | Optional: 187 | 188 | - `color` (String) Text to use when the value matches 189 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 190 | - `index` (Number) Position in the mapping array. Only used internally. 191 | - `text` (String) Text to display when the value matches 192 | 193 | 194 | 195 | 196 | 197 | ### Nested Schema for `field_config.defaults.mappings.value_map` 198 | 199 | Required: 200 | 201 | - `type` (String) 202 | 203 | Optional: 204 | 205 | - `options` (Attributes) Regular expression to match against and the result to apply when the value matches the regex (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 206 | 207 | 208 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 209 | 210 | Required: 211 | 212 | - `pattern` (String) Regular expression to match against 213 | 214 | Optional: 215 | 216 | - `result` (Attributes) Config to apply when the value matches the regex (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 217 | 218 | 219 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 220 | 221 | Optional: 222 | 223 | - `color` (String) Text to use when the value matches 224 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 225 | - `index` (Number) Position in the mapping array. Only used internally. 226 | - `text` (String) Text to display when the value matches 227 | 228 | 229 | 230 | 231 | 232 | ### Nested Schema for `field_config.defaults.mappings.value_map` 233 | 234 | Required: 235 | 236 | - `type` (String) 237 | 238 | Optional: 239 | 240 | - `options` (Attributes) (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 241 | 242 | 243 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 244 | 245 | Required: 246 | 247 | - `match` (String) Special value to match against 248 | 249 | Optional: 250 | 251 | - `result` (Attributes) Config to apply when the value matches the special value (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options--result)) 252 | 253 | 254 | ### Nested Schema for `field_config.defaults.mappings.value_map.options.result` 255 | 256 | Optional: 257 | 258 | - `color` (String) Text to use when the value matches 259 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 260 | - `index` (Number) Position in the mapping array. Only used internally. 261 | - `text` (String) Text to display when the value matches 262 | 263 | 264 | 265 | 266 | 267 | ### Nested Schema for `field_config.defaults.mappings.value_map` 268 | 269 | Required: 270 | 271 | - `type` (String) 272 | 273 | Optional: 274 | 275 | - `options` (Attributes Map) Map with : ValueMappingResult. For example: { "10": { text: "Perfection!", color: "green" } } (see [below for nested schema](#nestedatt--field_config--defaults--mappings--value_map--options)) 276 | 277 | 278 | ### Nested Schema for `field_config.defaults.mappings.value_map.options` 279 | 280 | Optional: 281 | 282 | - `color` (String) Text to use when the value matches 283 | - `icon` (String) Icon to display when the value matches. Only specific visualizations. 284 | - `index` (Number) Position in the mapping array. Only used internally. 285 | - `text` (String) Text to display when the value matches 286 | 287 | 288 | 289 | 290 | 291 | ### Nested Schema for `field_config.defaults.thresholds` 292 | 293 | Required: 294 | 295 | - `mode` (String) Thresholds mode. 296 | 297 | Optional: 298 | 299 | - `steps` (Attributes List) Must be sorted by 'value', first value is always -Infinity (see [below for nested schema](#nestedatt--field_config--defaults--thresholds--steps)) 300 | 301 | 302 | ### Nested Schema for `field_config.defaults.thresholds.steps` 303 | 304 | Required: 305 | 306 | - `color` (String) Color represents the color of the visual change that will occur in the dashboard when the threshold value is met or exceeded. 307 | - `value` (String) Value represents a specified metric for the threshold, which triggers a visual change in the dashboard when this value is met or exceeded. 308 | Nulls currently appear here when serializing -Infinity to JSON. 309 | 310 | 311 | 312 | 313 | 314 | ### Nested Schema for `field_config.overrides` 315 | 316 | Optional: 317 | 318 | - `matcher` (Attributes) (see [below for nested schema](#nestedatt--field_config--overrides--matcher)) 319 | - `properties` (Attributes List) (see [below for nested schema](#nestedatt--field_config--overrides--properties)) 320 | 321 | 322 | ### Nested Schema for `field_config.overrides.matcher` 323 | 324 | 325 | 326 | ### Nested Schema for `field_config.overrides.properties` 327 | 328 | 329 | 330 | 331 | 332 | ### Nested Schema for `grid_pos` 333 | 334 | Optional: 335 | 336 | - `h` (Number) Panel height. The height is the number of rows from the top edge of the panel. Defaults to 9. 337 | - `static` (Boolean) Whether the panel is fixed within the grid. If true, the panel will not be affected by other panels' interactions 338 | - `w` (Number) Panel width. The width is the number of columns from the left edge of the panel. Defaults to 12. 339 | - `x` (Number) Panel x. The x coordinate is the number of columns from the left edge of the grid. Defaults to 0. 340 | - `y` (Number) Panel y. The y coordinate is the number of rows from the top edge of the grid. Defaults to 0. 341 | 342 | 343 | 344 | ### Nested Schema for `library_panel` 345 | 346 | Required: 347 | 348 | - `name` (String) Library panel name 349 | - `uid` (String) Library panel uid 350 | 351 | 352 | 353 | ### Nested Schema for `links` 354 | 355 | Required: 356 | 357 | - `icon` (String) Icon name to be displayed with the link 358 | - `title` (String) Title to display with the link 359 | - `tooltip` (String) Tooltip to display when the user hovers their mouse over it 360 | - `type` (String) Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource) 361 | - `url` (String) Link URL. Only required/valid if the type is link 362 | 363 | Optional: 364 | 365 | - `as_dropdown` (Boolean) If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards. Defaults to false. 366 | - `include_vars` (Boolean) If true, includes current template variables values in the link as query params. Defaults to false. 367 | - `keep_time` (Boolean) If true, includes current time range in the link as query params. Defaults to false. 368 | - `tags` (List of String) List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards 369 | - `target_blank` (Boolean) If true, the link will be opened in a new tab. Defaults to false. 370 | 371 | 372 | 373 | ### Nested Schema for `options` 374 | 375 | Optional: 376 | 377 | - `code` (Attributes) (see [below for nested schema](#nestedatt--options--code)) 378 | - `content` (String) Defaults to "# Title 379 | 380 | For markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)". 381 | - `mode` (String) Defaults to "markdown". 382 | 383 | 384 | ### Nested Schema for `options.code` 385 | 386 | Optional: 387 | 388 | - `language` (String) The language passed to monaco code editor. Defaults to "plaintext". 389 | - `show_line_numbers` (Boolean) Defaults to false. 390 | - `show_mini_map` (Boolean) Defaults to false. 391 | 392 | 393 | 394 | 395 | ### Nested Schema for `transformations` 396 | 397 | Optional: 398 | 399 | - `disabled` (Boolean) Disabled transformations are skipped 400 | - `filter` (Attributes) Optional frame matcher. When missing it will be applied to all results (see [below for nested schema](#nestedatt--transformations--filter)) 401 | 402 | 403 | ### Nested Schema for `transformations.filter` 404 | --------------------------------------------------------------------------------