Base migration framework by ulucinar · Pull Request #119 · crossplane/upjet (original) (raw)
Description of your changes
Fixes https://github.com/upbound/team-extensions/issues/29
This PR introduces the base framework for migrating from community providers to official providers.
I have:
- Read and followed Crossplane's contribution process.
- Run
make reviewableto ensure this PR is ready for review. - Add tests for conversion functions, plan generator, etc.
- Added
backport release-x.ylabels to auto-backport this PR if necessary.
How has this code been tested
Manually tested using the implemented sample converter and the following manifests:
apiVersion: apiextensions.crossplane.io/v1 kind: CompositeResourceDefinition metadata: name: xmyresources.test.com spec: claimNames: kind: MyResource plural: myresources group: test.com names: kind: XMyResource plural: xmyresources versions:
- name: v1alpha1 referenceable: true schema: openAPIV3Schema: properties: spec: properties: parameters: properties: tagValue: type: string required: - tagValue type: object required: - parameters type: object type: object served: true
apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: labels: purpose: example name: example spec: compositeTypeRef: apiVersion: test.com/v1alpha1 kind: XMyResource resources: - base: apiVersion: ec2.aws.crossplane.io/v1beta1 kind: VPC spec: forProvider: cidrBlock: "192.168.0.0/16" ipv6Pool: pool1 region: "West Europe" tags: - key: key1 value: val1 - key: key2 value: val2 - key: key3 value: val3 name: vpc patches: - fromFieldPath: "spec.parameters.tagValue" toFieldPath: spec.forProvider.tags[0].value - fromFieldPath: "spec.parameters.tagValue" toFieldPath: spec.forProvider.tags[1].value - fromFieldPath: "spec.parameters.tagValue" toFieldPath: spec.forProvider.tags[2].value
apiVersion: test.com/v1alpha1 kind: MyResource metadata: name: my-resource namespace: upbound-system spec: compositionRef: name: example parameters: tagValue: demo-test
apiVersion: ec2.aws.crossplane.io/v1beta1 kind: VPC metadata: name: test-vpc spec: forProvider: cidrBlock: 192.168.0.0/16 ipv6Pool: pool1 region: West Europe tags: - key: key1 value: val1 - key: key2 value: val2 - key: key3 value: val3 status: atProvider: vpcId: vpc-0391605a3bf7977dd
And the following sample converter for community provider VPC resources (under pkg/migration/converters/vpc_converter.go):
func resources(mg resource.Managed) ([]resource.Managed, error) { source := mg.(*srcv1beta1.VPC) target := &targetv1beta1.VPC{} if _, err := migration.CopyInto(source, target, targetv1beta1.VPC_GroupVersionKind, "spec.forProvider.tags"); err != nil { return nil, errors.Wrap(err, "failed to copy source into target") } target.Spec.ForProvider.Tags = make(map[string]*string, len(source.Spec.ForProvider.Tags)) for _, t := range source.Spec.ForProvider.Tags { v := t.Value target.Spec.ForProvider.Tags[t.Key] = &v } return []resource.Managed{ target, }, nil }
func composedTemplates(cmp v1.ComposedTemplate, convertedBase ...*v1.ComposedTemplate) error {
for i, cb := range convertedBase {
for j, p := range cb.Patches {
if p.ToFieldPath == nil || !strings.HasPrefix(*p.ToFieldPath, "spec.forProvider.tags") {
continue
}
u, err := migration.FromRawExtension(cmp.Base)
if err != nil {
return errors.Wrap(err, "failed to convert ComposedTemplate with VPC base")
}
paved := fieldpath.Pave(u.Object)
key, err := paved.GetString(strings.ReplaceAll(*p.ToFieldPath, ".value", ".key"))
if err != nil {
return errors.Wrap(err, "failed to get value from paved")
}
s := fmt.Sprintf(spec.forProvider.tags["%s"], key)
convertedBase[i].Patches[j].ToFieldPath = &s
}
}
return nil
}
The converted resources are as follows:
apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: labels: purpose: example name: example spec: compositeTypeRef: apiVersion: test.com/v1alpha1 kind: XMyResource resources:
- base:
apiVersion: ec2.aws.upbound.io/v1beta1
kind: VPC
spec:
forProvider:
cidrBlock: 192.168.0.0/16
region: West Europe
tags:
key1: val1
key2: val2
key3: val3
name: vpc
patches:
- fromFieldPath: spec.parameters.tagValue toFieldPath: spec.forProvider.tags["key1"]
- fromFieldPath: spec.parameters.tagValue toFieldPath: spec.forProvider.tags["key2"]
- fromFieldPath: spec.parameters.tagValue toFieldPath: spec.forProvider.tags["key3"]
apiVersion: ec2.aws.upbound.io/v1beta1 kind: VPC metadata: name: test-vpc spec: forProvider: cidrBlock: 192.168.0.0/16 region: West Europe tags: key1: val1 key2: val2 key3: val3