Skip to content

Commit

Permalink
add doc comments for internal funcs
Browse files Browse the repository at this point in the history
Signed-off-by: Erhan Cagirici <erhan@upbound.io>
  • Loading branch information
erhancagirici committed Jan 30, 2024
1 parent 25e29bd commit 2c2b7b1
Showing 1 changed file with 35 additions and 6 deletions.
41 changes: 35 additions & 6 deletions pkg/controller/external_terraform_plugin_framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ func (c *TerraformPluginFrameworkConnector) Connect(ctx context.Context, mg xpre
}, nil
}

// getResourceSchema returns the Terraform Plugin Framework-style resource schema for the configured framework resource on the connector
func (c *TerraformPluginFrameworkConnector) getResourceSchema(ctx context.Context) (rschema.Schema, error) {
res := c.config.TerraformPluginFrameworkResource
schemaResp := &fwresource.SchemaResponse{}
Expand All @@ -194,6 +195,11 @@ func (c *TerraformPluginFrameworkConnector) getResourceSchema(ctx context.Contex
return schemaResp.Schema, nil
}

// configureProvider returns a configured Terraform protocol v5 provider server
// with the preconfigured provider instance in the terraform setup.
// The provider instance used should be already preconfigured
// at the terraform setup layer with the relevant provider meta if needed
// by the provider implementation.
func (c *TerraformPluginFrameworkConnector) configureProvider(ctx context.Context, ts terraform.Setup) (tfprotov5.ProviderServer, error) {
var schemaResp fwprovider.SchemaResponse
ts.FrameworkProvider.Schema(ctx, fwprovider.SchemaRequest{}, &schemaResp)
Expand Down Expand Up @@ -222,6 +228,11 @@ func (c *TerraformPluginFrameworkConnector) configureProvider(ctx context.Contex
return providerServer, nil
}

// getDiffPlan calls the underlying native TF provider's PlanResourceChange RPC,
// and returns the planned state and whether a diff exists.
// If plan response contains non-empty RequiresReplace (i.e. the resource needs
// to be recreated) an error is returned as Crossplane Resource Model (XRM)
// prohibits resource re-creations and rejects this plan.
func (n *terraformPluginFrameworkExternalClient) getDiffPlan(ctx context.Context,
tfStateValue tftypes.Value) (*tfprotov5.DynamicValue, bool, error) {
tfConfigDynamicVal, err := protov5DynamicValueFromMap(n.params, n.resourceValueTerraformType)
Expand Down Expand Up @@ -305,7 +316,7 @@ func (n *terraformPluginFrameworkExternalClient) Observe(ctx context.Context, mg

var stateValueMap map[string]any
if resourceExists {
if conv, err := tfValueToMap(tfStateValue); err != nil {
if conv, err := tfValueToGoValue(tfStateValue); err != nil {
return managed.ExternalObservation{}, errors.Wrap(err, "cannot convert instance state to JSON map")
} else {
stateValueMap = conv.(map[string]any)
Expand Down Expand Up @@ -403,7 +414,7 @@ func (n *terraformPluginFrameworkExternalClient) Create(ctx context.Context, mg
}

var stateValueMap map[string]any
if goval, err := tfValueToMap(newStateAfterApplyVal); err != nil {
if goval, err := tfValueToGoValue(newStateAfterApplyVal); err != nil {
return managed.ExternalCreation{}, errors.New("cannot convert native state to go map")
} else {
stateValueMap = goval.(map[string]any)
Expand Down Expand Up @@ -463,7 +474,7 @@ func (n *terraformPluginFrameworkExternalClient) Update(ctx context.Context, mg
}

var stateValueMap map[string]any
if goval, err := tfValueToMap(newStateAfterApplyVal); err != nil {
if goval, err := tfValueToGoValue(newStateAfterApplyVal); err != nil {
return managed.ExternalUpdate{}, errors.New("cannot convert native state to go map")
} else {
stateValueMap = goval.(map[string]any)
Expand Down Expand Up @@ -532,7 +543,18 @@ func (n *terraformPluginFrameworkExternalClient) setExternalName(mg xpresource.M
return oldName != newName, nil
}

func tfValueToMap(input tftypes.Value) (any, error) { //nolint:gocyclo
// tfValueToGoValue converts a given tftypes.Value to Go-native any type.
// Useful for converting terraform values of state to JSON or for setting
// observations at the MR.
// Nested values are recursively converted.
// Supported conversions:
// tftypes.Object, tftypes.Map => map[string]any
// tftypes.Set, tftypes.List, tftypes.Tuple => []string
// tftypes.Bool => bool
// tftypes.Number => int64, float64
// tftypes.String => string
// tftypes.DynamicPseudoType => conversion not supported and returns an error
func tfValueToGoValue(input tftypes.Value) (any, error) { //nolint:gocyclo
if !input.IsKnown() {
return nil, fmt.Errorf("cannot convert unknown value")
}
Expand All @@ -548,7 +570,7 @@ func tfValueToMap(input tftypes.Value) (any, error) { //nolint:gocyclo
return nil, err
}
for k, v := range destInterim {
res, err := tfValueToMap(v)
res, err := tfValueToGoValue(v)
if err != nil {
return nil, err
}
Expand All @@ -563,7 +585,7 @@ func tfValueToMap(input tftypes.Value) (any, error) { //nolint:gocyclo
}
dest := make([]any, len(destInterim))
for i, v := range destInterim {
res, err := tfValueToMap(v)
res, err := tfValueToGoValue(v)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -611,6 +633,8 @@ func tfValueToMap(input tftypes.Value) (any, error) { //nolint:gocyclo
}
}

// getFatalDiagnostics traverses the given Terraform protov5 diagnostics type
// and constructs a Go error. If the provided diag slice is empty, returns nil.
func getFatalDiagnostics(diags []*tfprotov5.Diagnostic) error {
var errs error
var diagErrors []string
Expand All @@ -625,6 +649,9 @@ func getFatalDiagnostics(diags []*tfprotov5.Diagnostic) error {
return errs
}

// frameworkDiagnosticsToString constructs an error string from the provided
// Plugin Framework diagnostics instance. Only Error severity diagnostics are
// included.
func frameworkDiagnosticsToString(fwdiags fwdiag.Diagnostics) string {
frameworkErrorDiags := fwdiags.Errors()
diagErrors := make([]string, 0, len(frameworkErrorDiags))
Expand All @@ -634,6 +661,8 @@ func frameworkDiagnosticsToString(fwdiags fwdiag.Diagnostics) string {
return strings.Join(diagErrors, "\n")
}

// protov5DynamicValueFromMap constructs a protov5 DynamicValue given the
// map[string]any using the terraform type as reference.
func protov5DynamicValueFromMap(data map[string]any, terraformType tftypes.Type) (*tfprotov5.DynamicValue, error) {
jsonBytes, err := json.Marshal(data)
if err != nil {
Expand Down

0 comments on commit 2c2b7b1

Please sign in to comment.