crossplane / upjet

A code generation framework and runtime for Crossplane providers
Apache License 2.0
320 stars 90 forks source link

Add a new late-init configuration to skip already filled field in spec.initProvider #407

Closed sergenyalcin closed 6 months ago

sergenyalcin commented 6 months ago

Description of your changes

This PR adds a new late-init API to skip already filled field in spec.initProvider.

Even though a field is specified in initProvider, it is late-init for forProvider. This can cause problems in some cases because forProvider is more powerful. With this new configuration API, the late-init operation of the field in forProvider can be skipped for fields set in initProvider.

I have:

How has this code been tested

Tested in provider-aws by using this configuration. The example configuration for aws ec2.Subnet resource:

    p.AddResourceConfigurator("aws_subnet", func(r *config.Resource) {
        r.LateInitializer = config.LateInitializer{
            ConditionalIgnoredFields: []string{
                "cidr_block",
            },
        }
    })

Generated LateInitialize function:

func (tr *Subnet) LateInitialize(attrs []byte) (bool, error) {
    params := &SubnetParameters_2{}
    if err := json.TFParser.Unmarshal(attrs, params); err != nil {
        return false, errors.Wrap(err, "failed to unmarshal Terraform state parameters for late-initialization")
    }
    opts := []resource.GenericLateInitializerOption{resource.WithZeroValueJSONOmitEmptyFilter(resource.CNameWildcard)}
    initParams, err := tr.GetInitParameters()
    if err != nil {
        return false, errors.Wrapf(err, "cannot get init parameters for resource '%q'", tr.GetName())
    }
    opts = append(opts, resource.WithConditionalFilter("CidrBlock", initParams))

    li := resource.NewGenericLateInitializer(opts...)
    return li.LateInitialize(&tr.Spec.ForProvider, params)
}