Skip to content

Commit e481fd5

Browse files
Datasource: Use UID instead of numerical ID (#1468)
* Datasource: Use UID instead of numerical ID The numerical ID is deprecated since v9. Let's remove it on next major version * Fix ML tests
1 parent f16e896 commit e481fd5

File tree

14 files changed

+190
-110
lines changed

14 files changed

+190
-110
lines changed

docs/data-sources/data_source.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ data "grafana_data_source" "from_uid" {
5050

5151
### Optional
5252

53+
- `id` (String, Deprecated) Deprecated: Use `uid` instead of `id`
5354
- `name` (String)
5455
- `org_id` (String) The Organization ID. If not set, the Org ID defined in the provider block will be used.
5556
- `uid` (String)
@@ -60,7 +61,6 @@ data "grafana_data_source" "from_uid" {
6061
- `basic_auth_enabled` (Boolean) Whether to enable basic auth for the data source.
6162
- `basic_auth_username` (String) Basic auth username.
6263
- `database_name` (String) (Required by some data source types) The name of the database to use on the selected data source server.
63-
- `id` (String) The ID of this resource.
6464
- `is_default` (Boolean) Whether to set the data source as default. This should only be `true` to a single data source.
6565
- `json_data_encoded` (String) Serialized JSON string containing the json data. This attribute can be used to pass configuration options to the data source. To figure out what options a datasource has available, see its docs or inspect the network data when saving it from the Grafana UI. Note that keys in this map are usually camelCased.
6666
- `type` (String) The data source type. Must be one of the supported data source keywords.

docs/resources/data_source_permission.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ resource "grafana_service_account" "sa" {
4747
}
4848
4949
resource "grafana_data_source_permission" "fooPermissions" {
50-
datasource_id = grafana_data_source.foo.id
50+
datasource_uid = grafana_data_source.foo.uid
5151
permissions {
5252
team_id = grafana_team.team.id
5353
permission = "Edit"
@@ -70,12 +70,10 @@ resource "grafana_data_source_permission" "fooPermissions" {
7070
<!-- schema generated by tfplugindocs -->
7171
## Schema
7272

73-
### Required
74-
75-
- `datasource_id` (String) ID of the datasource to apply permissions to.
76-
7773
### Optional
7874

75+
- `datasource_id` (String, Deprecated) Deprecated: Use `datasource_uid` instead.
76+
- `datasource_uid` (String) UID of the datasource to apply permissions to.
7977
- `org_id` (String) The Organization ID. If not set, the Org ID defined in the provider block will be used.
8078
- `permissions` (Block Set) The permission items to add/update. Items that are omitted from the list will be removed. (see [below for nested schema](#nestedblock--permissions))
8179

examples/resources/grafana_data_source_permission/resource.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ resource "grafana_service_account" "sa" {
3030
}
3131

3232
resource "grafana_data_source_permission" "fooPermissions" {
33-
datasource_id = grafana_data_source.foo.id
33+
datasource_uid = grafana_data_source.foo.uid
3434
permissions {
3535
team_id = grafana_team.team.id
3636
permission = "Edit"

examples/resources/grafana_machine_learning_job/datasource_uid_job.tf

Lines changed: 0 additions & 9 deletions
This file was deleted.

examples/resources/grafana_machine_learning_job/holidays_job.tf

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
resource "grafana_data_source" "foo" {
2+
type = "prometheus"
3+
name = "prometheus-ds-test"
4+
uid = "prometheus-ds-test-uid"
5+
url = "https://my-instance.com"
6+
basic_auth_enabled = true
7+
basic_auth_username = "username"
8+
9+
json_data_encoded = jsonencode({
10+
httpMethod = "POST"
11+
prometheusType = "Mimir"
12+
prometheusVersion = "2.4.0"
13+
})
14+
15+
secure_json_data_encoded = jsonencode({
16+
basicAuthPassword = "password"
17+
})
18+
}
19+
120
resource "grafana_machine_learning_holiday" "test_holiday" {
221
name = "Test Holiday"
322
custom_periods {
@@ -11,7 +30,7 @@ resource "grafana_machine_learning_job" "test_job" {
1130
name = "Test Job"
1231
metric = "tf_test_job"
1332
datasource_type = "prometheus"
14-
datasource_id = 10
33+
datasource_uid = grafana_data_source.foo.uid
1534
query_params = {
1635
expr = "grafanacloud_grafana_instance_active_user_count"
1736
}

examples/resources/grafana_machine_learning_job/job.tf

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
1+
resource "grafana_data_source" "foo" {
2+
type = "prometheus"
3+
name = "prometheus-ds-test"
4+
uid = "prometheus-ds-test-uid"
5+
url = "https://my-instance.com"
6+
basic_auth_enabled = true
7+
basic_auth_username = "username"
8+
9+
json_data_encoded = jsonencode({
10+
httpMethod = "POST"
11+
prometheusType = "Mimir"
12+
prometheusVersion = "2.4.0"
13+
})
14+
15+
secure_json_data_encoded = jsonencode({
16+
basicAuthPassword = "password"
17+
})
18+
}
19+
120
resource "grafana_machine_learning_job" "test_job" {
221
name = "Test Job"
322
metric = "tf_test_job"
423
datasource_type = "prometheus"
5-
datasource_id = 10
24+
datasource_uid = grafana_data_source.foo.uid
625
query_params = {
726
expr = "grafanacloud_grafana_instance_active_user_count"
827
}

examples/resources/grafana_machine_learning_job/tuned_job.tf

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
1+
resource "grafana_data_source" "foo" {
2+
type = "prometheus"
3+
name = "prometheus-ds-test"
4+
uid = "prometheus-ds-test-uid"
5+
url = "https://my-instance.com"
6+
basic_auth_enabled = true
7+
basic_auth_username = "username"
8+
9+
json_data_encoded = jsonencode({
10+
httpMethod = "POST"
11+
prometheusType = "Mimir"
12+
prometheusVersion = "2.4.0"
13+
})
14+
15+
secure_json_data_encoded = jsonencode({
16+
basicAuthPassword = "password"
17+
})
18+
}
19+
120
resource "grafana_machine_learning_job" "test_job" {
221
name = "Test Job"
322
metric = "tf_test_job"
423
datasource_type = "prometheus"
5-
datasource_uid = "grafanacloud-usage"
24+
datasource_uid = grafana_data_source.foo.uid
625
query_params = {
726
expr = "grafanacloud_grafana_instance_active_user_count"
827
}

internal/resources/grafana/common_check_exists_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,16 @@ var (
113113
},
114114
)
115115
datasourceCheckExists = newCheckExistsHelper(
116-
func(d *models.DataSource) string { return strconv.FormatInt(d.ID, 10) },
117-
func(client *goapi.GrafanaHTTPAPI, id string) (*models.DataSource, error) {
118-
resp, err := client.Datasources.GetDataSourceByID(id)
116+
func(d *models.DataSource) string { return d.UID },
117+
func(client *goapi.GrafanaHTTPAPI, uid string) (*models.DataSource, error) {
118+
resp, err := client.Datasources.GetDataSourceByUID(uid)
119119
return payloadOrError(resp, err)
120120
},
121121
)
122122
datasourcePermissionsCheckExists = newCheckExistsHelper(
123123
datasourceCheckExists.getIDFunc, // We use the DS as the reference
124-
func(client *goapi.GrafanaHTTPAPI, id string) (*models.DataSource, error) {
125-
ds, err := datasourceCheckExists.getResourceFunc(client, id)
124+
func(client *goapi.GrafanaHTTPAPI, uid string) (*models.DataSource, error) {
125+
ds, err := datasourceCheckExists.getResourceFunc(client, uid)
126126
if err != nil {
127127
return nil, err
128128
}

internal/resources/grafana/data_source_data_source.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package grafana
22

33
import (
44
"context"
5+
"strconv"
56

67
"github.com/grafana/grafana-openapi-client-go/models"
78
"github.com/grafana/terraform-provider-grafana/v2/internal/common"
@@ -20,6 +21,8 @@ func datasourceDatasource() *schema.Resource {
2021
Optional: true,
2122
Computed: true,
2223
AtLeastOneOf: []string{"id", "name", "uid"},
24+
Deprecated: "Use `uid` instead of `id`",
25+
Description: "Deprecated: Use `uid` instead of `id`",
2326
},
2427
"name": {
2528
Type: schema.TypeString,
@@ -49,7 +52,11 @@ func datasourceDatasourceRead(ctx context.Context, d *schema.ResourceData, meta
4952
resp, err = client.Datasources.GetDataSourceByName(name.(string))
5053
} else if id, ok := d.GetOk("id"); ok {
5154
_, idStr := SplitOrgResourceID(id.(string))
52-
resp, err = client.Datasources.GetDataSourceByID(idStr)
55+
if _, parseErr := strconv.ParseInt(idStr, 10, 64); parseErr == nil {
56+
resp, err = client.Datasources.GetDataSourceByID(idStr) // TODO: Remove on next major release
57+
} else {
58+
resp, err = client.Datasources.GetDataSourceByUID(idStr)
59+
}
5360
} else if uid, ok := d.GetOk("uid"); ok {
5461
resp, err = client.Datasources.GetDataSourceByUID(uid.(string))
5562
}

internal/resources/grafana/resource_data_source.go

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
1414
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1515

16+
goapi "github.com/grafana/grafana-openapi-client-go/client"
1617
"github.com/grafana/grafana-openapi-client-go/models"
1718
"github.com/grafana/terraform-provider-grafana/v2/internal/common"
1819
)
@@ -194,8 +195,7 @@ func CreateDataSource(ctx context.Context, d *schema.ResourceData, meta interfac
194195
return diag.FromErr(err)
195196
}
196197

197-
// TODO: Switch to UID
198-
d.SetId(MakeOrgResourceID(orgID, resp.Payload.Datasource.ID))
198+
d.SetId(MakeOrgResourceID(orgID, resp.Payload.Datasource.UID))
199199
return ReadDataSource(ctx, d, meta)
200200
}
201201

@@ -222,7 +222,7 @@ func UpdateDataSource(ctx context.Context, d *schema.ResourceData, meta interfac
222222
User: dataSource.User,
223223
WithCredentials: dataSource.WithCredentials,
224224
}
225-
_, err = client.Datasources.UpdateDataSourceByID(idStr, &body)
225+
_, err = client.Datasources.UpdateDataSourceByUID(idStr, &body)
226226

227227
return diag.FromErr(err)
228228
}
@@ -231,34 +231,25 @@ func UpdateDataSource(ctx context.Context, d *schema.ResourceData, meta interfac
231231
func ReadDataSource(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
232232
client, _, idStr := OAPIClientFromExistingOrgResource(meta, d.Id())
233233

234-
var resp interface{ GetPayload() *models.DataSource }
235-
var err error
236-
// Support both numerical and UID IDs, so that we can import an existing datasource with either.
237-
// Following the read, it's normalized to a numerical ID.
238-
if _, parseErr := strconv.ParseInt(idStr, 10, 64); parseErr == nil {
239-
resp, err = client.Datasources.GetDataSourceByID(idStr)
240-
} else {
241-
resp, err = client.Datasources.GetDataSourceByUID(idStr)
242-
}
243-
234+
ds, err := getDatasourceByUIDOrID(client, idStr)
244235
if err, shouldReturn := common.CheckReadError("datasource", d, err); shouldReturn {
245236
return err
246237
}
247238

248-
return datasourceToState(d, resp.GetPayload())
239+
return datasourceToState(d, ds)
249240
}
250241

251242
// DeleteDataSource deletes a Grafana datasource
252243
func DeleteDataSource(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
253244
client, _, idStr := OAPIClientFromExistingOrgResource(meta, d.Id())
254245

255-
_, err := client.Datasources.DeleteDataSourceByID(idStr)
246+
_, err := client.Datasources.DeleteDataSourceByUID(idStr)
256247
diag, _ := common.CheckReadError("datasource", d, err)
257248
return diag
258249
}
259250

260251
func datasourceToState(d *schema.ResourceData, dataSource *models.DataSource) diag.Diagnostics {
261-
d.SetId(MakeOrgResourceID(dataSource.OrgID, dataSource.ID))
252+
d.SetId(MakeOrgResourceID(dataSource.OrgID, dataSource.UID))
262253
d.Set("access_mode", dataSource.Access)
263254
d.Set("database_name", dataSource.Database)
264255
d.Set("is_default", dataSource.IsDefault)
@@ -397,3 +388,23 @@ func removeHeadersFromJSONData(input map[string]interface{}) (map[string]interfa
397388

398389
return jsonData, headers
399390
}
391+
392+
// Support both numerical and UID IDs, so that we can import an existing datasource with either.
393+
// Following the read, it's normalized to a UID.
394+
// TODO: Remove on next major version
395+
func getDatasourceByUIDOrID(client *goapi.GrafanaHTTPAPI, id string) (*models.DataSource, error) {
396+
var resp interface{ GetPayload() *models.DataSource }
397+
var err error
398+
399+
if _, parseErr := strconv.ParseInt(id, 10, 64); parseErr == nil {
400+
resp, err = client.Datasources.GetDataSourceByID(id)
401+
} else {
402+
resp, err = client.Datasources.GetDataSourceByUID(id)
403+
}
404+
405+
if err != nil {
406+
return nil, err
407+
}
408+
409+
return resp.GetPayload(), nil
410+
}

0 commit comments

Comments
 (0)