From 599de97852b5efd1aeb0c2eaa8e958785a8b1c93 Mon Sep 17 00:00:00 2001 From: Tom Schutte Date: Mon, 12 Feb 2024 13:47:35 -0600 Subject: [PATCH] Pass Ambar API Errors to Terraform Handle taking Ambar API Exceptions and correctly outputting them to Terraform for more useful error when doing Terraform template files. --- .../provider/data_destination_resource.go | 7 +++++- internal/provider/data_source_resource.go | 7 +++++- internal/provider/filter_resource.go | 7 +++++- internal/provider/utils.go | 25 +++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 internal/provider/utils.go diff --git a/internal/provider/data_destination_resource.go b/internal/provider/data_destination_resource.go index a5f20a0..de06827 100644 --- a/internal/provider/data_destination_resource.go +++ b/internal/provider/data_destination_resource.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "io" "net/http" "strconv" "time" @@ -154,9 +155,13 @@ func (r *DataDestinationResource) Create(ctx context.Context, req resource.Creat // Create the API call and execute it createResourceResponse, httpResponse, err := r.client.AmbarAPI.CreateDataDestination(ctx).CreateDataDestinationRequest(createDataDestination).Execute() if err != nil || createResourceResponse == nil || httpResponse == nil { + tflog.Debug(ctx, "StatusCode: "+httpResponse.Status) + httpBody, _ := io.ReadAll(httpResponse.Body) + errString := string(httpBody) + tflog.Debug(ctx, errString) resp.Diagnostics.AddError( "Error creating DataDestination", - "Could not create DataDestination, unexpected error: "+err.Error(), + "Could not create DataDestination: "+AmbarApiErrorToTerraformErrorString(errString), ) return } diff --git a/internal/provider/data_source_resource.go b/internal/provider/data_source_resource.go index a682289..82285a4 100644 --- a/internal/provider/data_source_resource.go +++ b/internal/provider/data_source_resource.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "io" "net/http" "strconv" "strings" @@ -160,9 +161,13 @@ func (r *dataSourceResource) Create(ctx context.Context, req resource.CreateRequ // Create the API call and execute it createResourceResponse, httpResponse, err := r.client.AmbarAPI.CreateDataSource(ctx).CreateDataSourceRequest(createDataSource).Execute() if err != nil || createResourceResponse == nil || httpResponse == nil { + tflog.Debug(ctx, "StatusCode: "+httpResponse.Status) + httpBody, _ := io.ReadAll(httpResponse.Body) + errString := string(httpBody) + tflog.Debug(ctx, errString) resp.Diagnostics.AddError( "Error creating DataSource", - "Could not create DataSource, unexpected error: "+err.Error(), + "Could not create DataSource: "+AmbarApiErrorToTerraformErrorString(errString), ) return } diff --git a/internal/provider/filter_resource.go b/internal/provider/filter_resource.go index 338bfa2..df55046 100644 --- a/internal/provider/filter_resource.go +++ b/internal/provider/filter_resource.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "io" "net/http" "strconv" "time" @@ -146,9 +147,13 @@ func (r *FilterResource) Create(ctx context.Context, req resource.CreateRequest, // Create the API call and execute it createResourceResponse, httpResponse, err := r.client.AmbarAPI.CreateFilter(ctx).CreateFilterRequest(createFilter).Execute() if err != nil || createResourceResponse == nil || httpResponse == nil { + tflog.Debug(ctx, "StatusCode: "+httpResponse.Status) + httpBody, _ := io.ReadAll(httpResponse.Body) + errString := string(httpBody) + tflog.Debug(ctx, errString) resp.Diagnostics.AddError( "Error creating Filter", - "Could not create Filter, unexpected error: "+err.Error(), + "Could not create Filter: "+AmbarApiErrorToTerraformErrorString(errString), ) return } diff --git a/internal/provider/utils.go b/internal/provider/utils.go new file mode 100644 index 0000000..7c592b0 --- /dev/null +++ b/internal/provider/utils.go @@ -0,0 +1,25 @@ +package provider + +import ( + "regexp" + "strings" +) + +var matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") + +// Small utility functions to help convert the usual camel case used in HTTP +// to the names we give fields in Terraform. This is just to remove some cognitive overhead +// for Terraform users. +func toSnakeCase(s string) string { + snake := matchAllCap.ReplaceAllString(s, "${1}_${2}") + return snake +} + +// AmbarApiErrorToTerraformErrorString Extracts out just the error portion of the JSON body of the http response. +// We then use the other util functions to clean it up and correct the naming to be correct as fields would appear +// in Terraform template files. +func AmbarApiErrorToTerraformErrorString(apiString string) string { + slicedString := strings.SplitAfter(apiString, "\":") + errorContent := strings.Trim(slicedString[len(slicedString)-1], "\"{}") + return toSnakeCase(errorContent) +}