Skip to content

Commit

Permalink
Merge pull request #41368 from hashicorp/b-sagemaker-endpoint-empty-c…
Browse files Browse the repository at this point in the history
…apture-headers

resource/aws_sagemaker_endpoint_configuration: Prevents panic when `data_capture_config.capture_content_type_header` empty
  • Loading branch information
gdavison authored Feb 12, 2025
2 parents 977f4ef + 83fb1da commit e963be3
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 32 deletions.
11 changes: 11 additions & 0 deletions internal/errs/diag.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
)

const (
Expand Down Expand Up @@ -115,6 +116,16 @@ func NewAttributeRequiredWhenError(neededPath, otherPath cty.Path, value string)
)
}

// NewAtLeastOneOfChildrenError returns an error diagnostic indicating that at least on of the named children of
// parentPath is required.
func NewAtLeastOneOfChildrenError(parentPath cty.Path, paths ...cty.Path) diag.Diagnostic {
return NewAttributeErrorDiagnostic(
parentPath,
"Invalid Attribute Combination",
fmt.Sprintf("At least one attribute out of [%s] must be specified", strings.Join(tfslices.ApplyToAll(paths, PathString), ", ")),
)
}

// NewAttributeRequiredWhenError should only be used for apply-time validation, as it replicates
// the functionality of a `Required` attribute
func NewAttributeRequiredError(parentPath cty.Path, attrname string) diag.Diagnostic {
Expand Down
2 changes: 1 addition & 1 deletion internal/errs/sdkdiag/diags.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func DiagnosticString(d diag.Diagnostic) string {
fmt.Fprintf(&buf, "\n\n%s", d.Detail)
}
if len(d.AttributePath) > 0 {
fmt.Fprintf(&buf, "\n%s", pathString(d.AttributePath))
fmt.Fprintf(&buf, "\n\nPath: %s", pathString(d.AttributePath))
}

return buf.String()
Expand Down
75 changes: 73 additions & 2 deletions internal/service/sagemaker/endpoint_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ import (
"github.com/aws/aws-sdk-go-v2/service/sagemaker"
awstypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types"
"github.com/hashicorp/aws-sdk-go-base/v2/tfawserr"
"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/create"
"github.com/hashicorp/terraform-provider-aws/internal/enum"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
Expand Down Expand Up @@ -596,7 +599,75 @@ func resourceEndpointConfiguration() *schema.Resource {
names.AttrTagsAll: tftags.TagsSchemaComputed(),
},

CustomizeDiff: verify.SetTagsDiff,
CustomizeDiff: customdiff.All(
verify.SetTagsDiff,
validateDataCaptureConfigCustomDiff,
),
}
}

func validateDataCaptureConfigCustomDiff(ctx context.Context, d *schema.ResourceDiff, meta any) error {
var diags diag.Diagnostics

configRaw := d.GetRawConfig()
if !configRaw.IsKnown() || configRaw.IsNull() {
return nil
}

dataCapturesPath := cty.GetAttrPath("data_capture_config")
dataCaptures := configRaw.GetAttr("data_capture_config")
if dataCaptures.IsKnown() && !dataCaptures.IsNull() {
dataCaptureConfigPlanTimeValidate(dataCapturesPath, dataCaptures, &diags)
}

return sdkdiag.DiagnosticsError(diags)
}

func dataCaptureConfigPlanTimeValidate(path cty.Path, dataCaptures cty.Value, diags *diag.Diagnostics) {
it := dataCaptures.ElementIterator()
for it.Next() {
_, dataCapture := it.Element()

if !dataCapture.IsKnown() {
break
}
if dataCapture.IsNull() {
break
}

captureContentHeaderPath := path.GetAttr("capture_content_type_header")
captureContentHeaders := dataCapture.GetAttr("capture_content_type_header")

captureContentTypeHeaderPlanTimeValidate(captureContentHeaderPath, captureContentHeaders, diags)
}
}

func captureContentTypeHeaderPlanTimeValidate(path cty.Path, captureContentHeaders cty.Value, diags *diag.Diagnostics) {
it := captureContentHeaders.ElementIterator()
for it.Next() {
_, captureContentHeader := it.Element()

if !captureContentHeader.IsKnown() {
break
}
if captureContentHeader.IsNull() {
break
}

csvContentTypes := captureContentHeader.GetAttr("csv_content_types")
if csvContentTypes.IsKnown() && !csvContentTypes.IsNull() {
break
}

jsonContentTypes := captureContentHeader.GetAttr("json_content_types")
if jsonContentTypes.IsKnown() && !jsonContentTypes.IsNull() {
break
}

*diags = append(*diags, errs.NewAtLeastOneOfChildrenError(path,
cty.GetAttrPath("csv_content_types"),
cty.GetAttrPath("json_content_types"),
))
}
}

Expand Down Expand Up @@ -882,7 +953,7 @@ func expandDataCaptureConfig(configured []interface{}) *awstypes.DataCaptureConf
c.KmsKeyId = aws.String(v)
}

if v, ok := m["capture_content_type_header"].([]interface{}); ok && (len(v) > 0) {
if v, ok := m["capture_content_type_header"].([]interface{}); ok && len(v) > 0 && v[0] != nil {
c.CaptureContentTypeHeader = expandCaptureContentTypeHeader(v[0].(map[string]interface{}))
}

Expand Down
Loading

0 comments on commit e963be3

Please sign in to comment.