terraform-provider-grafana
terraform-provider-grafana copied to clipboard
Resource: Add LBAC for datasources `data_source_lbac_rules`
why/what We have seen that users would love to provision their lbac rules using terraform. this implements a experimental feature that will be highly developed. this is the first part of LBAC rules resource for terraform.
we have: updated swagger doc and swagger definitions in LBAC for datasources
- https://github.com/grafana/grafana-enterprise/pull/7117 ✅
- https://github.com/grafana/grafana/pull/92594 ✅
ability to run terraform plan, terraform apply and terraform destroy of the rules resource
Example terraform:
resource "grafana_data_source" "test" {
type = "loki"
name = "loki"
url = "http://localhost:3100"
basic_auth_enabled = true
basic_auth_username = "username"
lifecycle {
ignore_changes = [json_data_encoded, http_headers]
}
}
resource "grafana_team" "test" {
name = "test"
}
resource "grafana_data_source_config_lbac_rules" "test" {
datasource_uid = grafana_data_source.test.uid
org_id = grafana_team.test.org_id
rules = jsonencode({
"${grafana_team.test.id}" = [
"{ foo != \"bar\", foo !~ \"baz\" }",
"{ foo = \"qux\" }"
]
})
}
proposals and thought process
there is no ID for the json field teamHttpHeaders
- so the state is only “stored” in the datasource as a whole, therefore leaning on copying the
data_source_configresource more this is a resource that will be heavily used - i would like to have the internal state for terraform (some customers create about 500 rules and more), which clogs the datasource, i would like to copy the setup from
grafana_data_source_permission_itemfor this. as it suits well for how we would like to setup this resource - instead we make use of the api as it is. it is bulk update anyway. so we assume that all of the teams will be provided in the resource of
resource_data_source_config_lbac_rules
proposal of all rules combined into one resource
benefits
- one api call to grafana
- mimicing the get/update apis
tradeoffs
- clonky json encoding (could be fixed)
- not ideal for teams managing their own set of rules
resource "grafana_data_source_config_lbac_rules" "test" {
datasource_uid = grafana_data_source.test.uid
org_id = grafana_team.test.org_id
rules = jsonencode({
"${grafana_team.test.id}" = [
"{ foo != \"bar\", foo !~ \"baz\" }",
"{ foo = \"qux\" }"
]
})
}
proposal of each rule being a resource
benefits
- each team rules, would be able to be owned by a team. this is preferred from a user perspective
tradeoffs
- too many api calls to grafana, if we have 500 rules we would have 500 api calls to the datasource endpoint
resource "grafana_data_source_config_lbac_rule" "test" {
datasource_uid = grafana_data_source.test.uid
org_id = grafana_team.test.org_id
team_id = "1"
rules = [
"{ foo != \"bar\", foo !~ \"baz\" }",
"{ foo = \"qux\" }"
]
}
proposal of embedding it into a resource and then add it to the json
benefits:
- easier to implement
tradeoff
- management of lbac rules would lie inside of the json and we would not be able to move the storage of the lbac rules
It's a tradeoff of where you want the complexity to be. In Grafana with a new way to store this, or in the provider extracting it from json data, and possibly running into versioning issues.
I guess the less complex option is to leave everything as-is, isn't it? Have people manage those new fields in the existing json data? Perhaps provide a datasource helper for this, if the value is not trivial to build/represent
data "grafana_datasource_team_headers" "helper" { ... }
resource "grafana_datasource" "test" {
...
json_data_encoded = jsonencode({
teamHeaders = data.grafana_datasource_team_headers.helper.value
otherfields
})
}
run tests via
GRAFANA_VERSION=11.1.0
GRAFANA_URL=http://localhost:3000
GRAFANA_AUTH=admin:admin
TESTARGS="-run TestAccDataSourceLBAC_inOrg" make testacc-enterprise
The teamHttpHeaders resource is a datasource json field.
basically this introduced a way to add/update a datasource json field lbac-api
here is the doc for it. https://grafana.com/docs/grafana/latest/administration/data-source-management/teamlbac/
next steps
improvements:
- [ ] API of the resource could be made so that there is no need of escaped JSON. To enforces types and schema
- Create a template file (logql_query.tmpl):
{f="fea", b="bajs", a="abc"}
resource "grafana_data_source_config_lbac_rules" "test" {
datasource_uid = grafana_data_source.test.uid
rules = jsonencode({
"1" = [
"{ foo != \"bar\", foo !~ \"baz\" }",
"{ foo = \"qux\" }"
],
"2" = [
templatefile("${path.module}/logql_query.tmpl", {})
]
})
}
```[tasklist]
- [ ] fix the lifecycle of the jsondata within grafana
- [ ] make sure you cannot set teamhttpheaders from the json api (updateDatasource), ONLY through lbac/team api
- [ ] magic diffsuprressfunc to ignore changes on json_data_encoded for the specific field teamHttpHeaders