gokuberneteskubebuildercrossplane

How to format the way provider resources get generated with Crossplane?


Im looking to build a crossplane provider for my organization however im running to issues with the code generation.

Is there a way to manipulate how the resource names get generated? The Upjet code generations tools do not seem to respect the naming format for certain resources.

for example:

We have a terraform resource with this format. provider_load_balancer after adding the resource and running make generate the resource gets generated. However, the following gets generated.

├── apis
│   ├── generate.go
│   ├── load
│   │   └── v1alpha1
│   │       ├── zz_balancer_types.go
│   │       ├── zz_generated.deepcopy.go
│   │       ├── zz_generated.managed.go
│   │       ├── zz_generated.managedlist.go
│   │       ├── zz_generated_terraformed.go
│   │       └── zz_groupversion_info.go

├── examples-generated
│   ├── load
│   │   └── balancer.yaml

The CRDS, yamls and file structure get generated incorrectly. Ideally, the directories and CRDS should not split the resource name but rather have them as one string loadbalancer

Below we see even the deepcopy methods get generated with the wrong name. These Should be loadbalancer not balancer

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Balancer) DeepCopyInto(out *Balancer) {
    *out = *in
    out.TypeMeta = in.TypeMeta
    in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
    in.Spec.DeepCopyInto(&out.Spec)
    in.Status.DeepCopyInto(&out.Status)
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Balancer.
func (in *Balancer) DeepCopy() *Balancer {
    if in == nil {
        return nil
    }
    out := new(Balancer)
    in.DeepCopyInto(out)
    return out
}

Any ideas about what I can do here?


Solution

  • You can customize the group for an individual generated resource by adding a ResourceConfigurator for it. This is mentioned briefly in the GitHub provider example in the upjet docs.

       cat <<EOF > config/repository/config.go
       package repository
    
       import "github.com/upbound/upjet/pkg/config"
    
       // Configure configures individual resources by adding custom ResourceConfigurators.
       func Configure(p *config.Provider) {
           p.AddResourceConfigurator("github_repository", func(r *config.Resource) {
               // We need to override the default group that upjet generated for
               // this resource, which would be "github"
               r.ShortGroup = "repository"
           })
       }
       EOF
    

    For a more significant example of customization, have a look at provider-aws, which uses a custom mapping and trimming function to map from certain terraform resource names into specific Groups and Kinds.

    // GroupKindOverrides overrides the group and kind of the resource if it matches
    // any entry in the GroupMap.
    func GroupKindOverrides() config.ResourceOption {
        return func(r *config.Resource) {
            if f, ok := GroupMap[r.Name]; ok {
                r.ShortGroup, r.Kind = f(r.Name)
            }
        }
    }
    
    // KindOverrides overrides the kind of the resources given in KindMap.
    func KindOverrides() config.ResourceOption {
        return func(r *config.Resource) {
            if k, ok := KindMap[r.Name]; ok {
                r.Kind = k
            }
        }
    }
    

    This is then added into config/provider.go to customize the behavior of the generator.

    // GetProvider returns provider configuration
    func GetProvider() *config.Provider {
        modulePath := "github.com/upbound/provider-aws"
        pc := config.NewProvider([]byte(providerSchema), "aws",
            modulePath, providerMetadata,
            config.WithShortName("aws"),
            config.WithRootGroup("aws.upbound.io"),
    ...
            config.WithDefaultResourceOptions(
                GroupKindOverrides(),
                KindOverrides(),        
    ...
            ),
            config.WithMainTemplate(hack.MainTemplate),
        )
    ...