-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8a7f797
commit 8d5f3d2
Showing
5 changed files
with
293 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
159 changes: 159 additions & 0 deletions
159
internal/framework/customtypes/davinciexporttype/parsed_type.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package davinciexporttype | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/attr" | ||
"github.com/hashicorp/terraform-plugin-framework/attr/xattr" | ||
"github.com/hashicorp/terraform-plugin-framework/diag" | ||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes" | ||
"github.com/hashicorp/terraform-plugin-go/tftypes" | ||
"github.com/samir-gandhi/davinci-client-go/davinci" | ||
) | ||
|
||
// Ensure the implementation satisfies the expected interfaces | ||
var _ basetypes.StringTypable = ParsedType{} | ||
var _ xattr.TypeWithValidate = ParsedType{} | ||
|
||
type ParsedType struct { | ||
basetypes.StringType | ||
ImportFile bool | ||
// ... potentially other fields ... | ||
} | ||
|
||
func (t ParsedType) Equal(o attr.Type) bool { | ||
other, ok := o.(ParsedType) | ||
|
||
if !ok { | ||
return false | ||
} | ||
|
||
return t.StringType.Equal(other.StringType) | ||
} | ||
|
||
func (t ParsedType) String() string { | ||
return "davinciexporttype.ParsedType" | ||
} | ||
|
||
func (t ParsedType) ValueFromString(ctx context.Context, in basetypes.StringValue) (basetypes.StringValuable, diag.Diagnostics) { | ||
// ParsedValue defined in the value type section | ||
value := ParsedValue{ | ||
StringValue: in, | ||
ImportFile: t.ImportFile, | ||
} | ||
|
||
return value, nil | ||
} | ||
|
||
func (t ParsedType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) { | ||
attrValue, err := t.StringType.ValueFromTerraform(ctx, in) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
stringValue, ok := attrValue.(basetypes.StringValue) | ||
|
||
if !ok { | ||
return nil, fmt.Errorf("unexpected value type of %T", attrValue) | ||
} | ||
|
||
stringValuable, diags := t.ValueFromString(ctx, stringValue) | ||
|
||
if diags.HasError() { | ||
return nil, fmt.Errorf("unexpected error converting StringValue to StringValuable: %v", diags) | ||
} | ||
|
||
return stringValuable, nil | ||
} | ||
|
||
func (t ParsedType) ValueType(ctx context.Context) attr.Value { | ||
// ParsedValue defined in the value type section | ||
return ParsedValue{} | ||
} | ||
|
||
func (t ParsedType) Validate(ctx context.Context, in tftypes.Value, path path.Path) diag.Diagnostics { | ||
var diags diag.Diagnostics | ||
|
||
if in.Type() == nil { | ||
return diags | ||
} | ||
|
||
if !in.Type().Is(tftypes.String) { | ||
err := fmt.Errorf("expected String value, received %T with value: %v", in, in) | ||
diags.AddAttributeError( | ||
path, | ||
"DaVinci Export Parsed Type Validation Error", | ||
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. "+ | ||
"Please report the following to the provider developer:\n\n"+err.Error(), | ||
) | ||
return diags | ||
} | ||
|
||
if !in.IsKnown() || in.IsNull() { | ||
return diags | ||
} | ||
|
||
var valueString string | ||
|
||
if err := in.As(&valueString); err != nil { | ||
diags.AddAttributeError( | ||
path, | ||
"DaVinci Export Parsed Type Validation Error", | ||
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. "+ | ||
"Please report the following to the provider developer:\n\n"+err.Error(), | ||
) | ||
|
||
return diags | ||
} | ||
|
||
if ok := davinci.ValidFlowsInfoJSON([]byte(valueString), davinci.ExportCmpOpts{}); ok { | ||
Check failure on line 112 in internal/framework/customtypes/davinciexporttype/parsed_type.go GitHub Actions / Analyze (go)
|
||
diags.AddAttributeError( | ||
path, | ||
"Invalid DaVinci Flow Export String Value", | ||
"A string value was provided that is not valid DaVinci Export JSON string format. The export should not including subflows as these should be managed separately, as their own independent flows.\n\n"+ | ||
"Please re-export the DaVinci flow without subflows included.\n", | ||
) | ||
|
||
return diags | ||
} | ||
|
||
// Validate just the config of the export | ||
if ok := davinci.ValidFlowJSON([]byte(valueString), davinci.ExportCmpOpts{ | ||
Check failure on line 124 in internal/framework/customtypes/davinciexporttype/parsed_type.go GitHub Actions / Analyze (go)
|
||
IgnoreConfig: false, | ||
IgnoreDesignerCues: true, | ||
IgnoreEnvironmentMetadata: true, | ||
IgnoreUnmappedProperties: true, | ||
IgnoreVersionMetadata: true, | ||
IgnoreFlowMetadata: true, | ||
}); !ok { | ||
diags.AddAttributeError( | ||
path, | ||
"Invalid DaVinci Flow Export String Value", | ||
"A string value was provided that is not valid DaVinci Export JSON string format.\n\n"+ | ||
"Please re-export the DaVinci flow. If the flow JSON has been correctly exported from the DaVinci environment (and can be re-imported), please report this error to the provider maintainers.\n", | ||
) | ||
|
||
return diags | ||
} | ||
|
||
// Warn in case there are AdditionalProperties in the import file (since these aren't cleanly handled in the SDK, while they are preserved on import, there may be unpredictable results in diff calculation) | ||
if ok := davinci.ValidFlowJSON([]byte(valueString), davinci.ExportCmpOpts{ | ||
Check failure on line 143 in internal/framework/customtypes/davinciexporttype/parsed_type.go GitHub Actions / Analyze (go)
|
||
IgnoreConfig: true, | ||
IgnoreDesignerCues: true, | ||
IgnoreEnvironmentMetadata: true, | ||
IgnoreUnmappedProperties: false, | ||
IgnoreVersionMetadata: true, | ||
IgnoreFlowMetadata: true, | ||
}); !ok { | ||
diags.AddAttributeWarning( | ||
path, | ||
"DaVinci Export JSON contains unknown properties", | ||
"The DaVinci Flow Export contains properties that cannot be validated. These parameters will be preserved on import to the DaVinci service, but there may be unpredictable results in difference calculation.\n", | ||
) | ||
} | ||
|
||
return diags | ||
} |
86 changes: 86 additions & 0 deletions
86
internal/framework/customtypes/davinciexporttype/parsed_value.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package davinciexporttype | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/attr" | ||
"github.com/hashicorp/terraform-plugin-framework/diag" | ||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes" | ||
"github.com/samir-gandhi/davinci-client-go/davinci" | ||
) | ||
|
||
// Ensure the implementation satisfies the expected interfaces | ||
var _ basetypes.StringValuable = ParsedValue{} | ||
var _ basetypes.StringValuableWithSemanticEquals = ParsedValue{} | ||
|
||
type ParsedValue struct { | ||
basetypes.StringValue | ||
// ... potentially other fields ... | ||
ImportFile bool | ||
} | ||
|
||
func (v ParsedValue) Equal(o attr.Value) bool { | ||
other, ok := o.(ParsedValue) | ||
|
||
if !ok { | ||
return false | ||
} | ||
|
||
return v.StringValue.Equal(other.StringValue) | ||
} | ||
|
||
func (v ParsedValue) Type(ctx context.Context) attr.Type { | ||
// ParsedType defined in the schema type section | ||
return ParsedType{} | ||
} | ||
|
||
func (v ParsedValue) StringSemanticEquals(ctx context.Context, newValuable basetypes.StringValuable) (bool, diag.Diagnostics) { | ||
var diags diag.Diagnostics | ||
|
||
// The framework should always pass the correct value type, but always check | ||
newValue, ok := newValuable.(ParsedValue) | ||
|
||
if !ok { | ||
diags.AddError( | ||
"DaVinci Export Parsed Type Semantic Equality Check Error", | ||
"An unexpected value type was received while performing semantic equality checks. "+ | ||
"Please report this to the provider developers.\n\n"+ | ||
"Expected Value Type: "+fmt.Sprintf("%T", v)+"\n"+ | ||
"Got Value Type: "+fmt.Sprintf("%T", newValuable), | ||
) | ||
|
||
return false, diags | ||
} | ||
|
||
var priorFlow, newFlow davinci.Flow | ||
|
||
if err := json.Unmarshal([]byte(v.StringValue.ValueString()), &priorFlow); err != nil { | ||
diags.AddError( | ||
"DaVinci Export Parsed Type Semantic Equality Check Error", | ||
"An unexpected error was encountered trying to parse the prior attribute value to perform semantic equals evaluation. This is always an error in the provider. "+ | ||
"Please report the following to the provider developer:\n\n"+err.Error(), | ||
) | ||
return false, diags | ||
} | ||
|
||
if err := json.Unmarshal([]byte(newValue.ValueString()), &newFlow); err != nil { | ||
diags.AddError( | ||
"DaVinci Export Parsed Type Semantic Equality Check Error", | ||
"An unexpected error was encountered trying to parse the new attribute value to perform semantic equals evaluation. This is always an error in the provider. "+ | ||
"Please report the following to the provider developer:\n\n"+err.Error(), | ||
) | ||
return false, diags | ||
} | ||
|
||
// Check whether the flows are equal, ignoring environment metadata and designer UI cues. Just the flow configuration | ||
return davinci.FlowEqual(priorFlow, newFlow, davinci.ExportCmpOpts{ | ||
Check failure on line 78 in internal/framework/customtypes/davinciexporttype/parsed_value.go GitHub Actions / Analyze (go)
|
||
IgnoreConfig: false, | ||
IgnoreDesignerCues: true, | ||
IgnoreEnvironmentMetadata: !v.ImportFile, | ||
IgnoreUnmappedProperties: true, | ||
IgnoreVersionMetadata: true, | ||
IgnoreFlowMetadata: true, | ||
}), diags | ||
} |
Oops, something went wrong.