diff --git a/internal/resources/grafana/resource_data_source.go b/internal/resources/grafana/resource_data_source.go index d5d6f0bcf..45bd7ab75 100644 --- a/internal/resources/grafana/resource_data_source.go +++ b/internal/resources/grafana/resource_data_source.go @@ -245,13 +245,16 @@ func CreateDataSource(ctx context.Context, d *schema.ResourceData, meta any) dia return diag.FromErr(err) } + diags := checkDeprecatedPrometheusAuth(d) + resp, err := client.Datasources.AddDataSource(dataSource) if err != nil { return diag.FromErr(err) } d.SetId(MakeOrgResourceID(orgID, resp.Payload.Datasource.UID)) - return ReadDataSource(ctx, d, meta) + readDiags := ReadDataSource(ctx, d, meta) + return append(diags, readDiags...) } // UpdateDataSource updates a Grafana datasource @@ -262,6 +265,9 @@ func UpdateDataSource(ctx context.Context, d *schema.ResourceData, meta any) dia if err != nil { return diag.FromErr(err) } + + diags := checkDeprecatedPrometheusAuth(d) + body := models.UpdateDataSourceCommand{ Access: dataSource.Access, BasicAuth: dataSource.BasicAuth, @@ -279,7 +285,11 @@ func UpdateDataSource(ctx context.Context, d *schema.ResourceData, meta any) dia } _, err = client.Datasources.UpdateDataSourceByUID(idStr, &body) - return diag.FromErr(err) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + + return diags } // ReadDataSource reads a Grafana datasource @@ -450,3 +460,42 @@ func removeHeadersFromJSONData(input map[string]any) (map[string]any, map[string return jsonData, headers } + +// checkDeprecatedPrometheusAuth checks if the data source is using deprecated authentication methods +func checkDeprecatedPrometheusAuth(d *schema.ResourceData) diag.Diagnostics { + var diags diag.Diagnostics + + dsType := d.Get("type").(string) + if dsType != "prometheus" { + return diags + } + + jsonDataEncoded := d.Get("json_data_encoded").(string) + if jsonDataEncoded == "" { + return diags + } + + var jsonData map[string]any + if err := json.Unmarshal([]byte(jsonDataEncoded), &jsonData); err != nil { + // If we can't parse it, don't add a warning + return diags + } + + if sigV4Auth, ok := jsonData["sigV4Auth"].(bool); ok && sigV4Auth { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Warning, + Summary: "Deprecated authentication method", + Detail: "SigV4 authentication is deprecated for the core Prometheus data source. Please install Amazon Managed Service for Prometheus found here: https://grafana.com/grafana/plugins/grafana-amazonprometheus-datasource/ and then change the type of your data source to 'grafana-amazonprometheus-datasource'.", + }) + } + + if azureAuth, ok := jsonData["azureCredentials"]; ok && azureAuth != nil { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Warning, + Summary: "Deprecated authentication method", + Detail: "Azure authentication is deprecated for the core Prometheus data source. lease install Amazon Managed Service for Prometheus found here: https://grafana.com/grafana/plugins/grafana-azureprometheus-datasource/ and then change the type of your data source to 'grafana-azureprometheus-datasource'.", + }) + } + + return diags +} diff --git a/internal/resources/grafana/resource_data_source_deprecated_auth_test.go b/internal/resources/grafana/resource_data_source_deprecated_auth_test.go new file mode 100644 index 000000000..2c3f719f4 --- /dev/null +++ b/internal/resources/grafana/resource_data_source_deprecated_auth_test.go @@ -0,0 +1,70 @@ +package grafana + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/stretchr/testify/require" +) + +func TestCheckDeprecatedPrometheusAuth_SigV4(t *testing.T) { + d := schema.TestResourceDataRaw(t, resourceDataSource().Schema.Schema, map[string]interface{}{ + "name": "test-prometheus", + "type": "prometheus", + "url": "http://localhost:9090", + "json_data_encoded": `{"sigV4Auth":true}`, + }) + + diags := checkDeprecatedPrometheusAuth(d) + + if len(diags) != 1 { + t.Errorf("Expected 1 diagnostic, got %d", len(diags)) + } + + require.Equal(t, len(diags), 1) + require.Equal(t, diags[0].Severity, diag.Warning) +} + +func TestCheckDeprecatedPrometheusAuth_Azure(t *testing.T) { + d := schema.TestResourceDataRaw(t, resourceDataSource().Schema.Schema, map[string]interface{}{ + "name": "test-prometheus", + "type": "prometheus", + "url": "http://localhost:9090", + "json_data_encoded": `{"azureCredentials":{}}`, + }) + + diags := checkDeprecatedPrometheusAuth(d) + + if len(diags) != 1 { + t.Errorf("Expected 1 diagnostic, got %d", len(diags)) + } + + require.Equal(t, len(diags), 1) + require.Equal(t, diags[0].Severity, diag.Warning) +} + +func TestCheckDeprecatedPrometheusAuth_NoDeprecatedAuth(t *testing.T) { + d := schema.TestResourceDataRaw(t, resourceDataSource().Schema.Schema, map[string]interface{}{ + "name": "test-prometheus", + "type": "prometheus", + "url": "http://localhost:9090", + }) + + diags := checkDeprecatedPrometheusAuth(d) + + require.Equal(t, len(diags), 0) +} + +func TestCheckDeprecatedPrometheusAuth_NonPrometheusDataSource(t *testing.T) { + d := schema.TestResourceDataRaw(t, resourceDataSource().Schema.Schema, map[string]interface{}{ + "name": "test-loki", + "type": "loki", + "url": "http://localhost:9090", + "json_data_encoded": `{"sigV4Auth":true}`, + }) + + diags := checkDeprecatedPrometheusAuth(d) + + require.Equal(t, len(diags), 0) +}