diff --git a/pkg/migration/converter.go b/pkg/migration/converter.go index eb48e25d..6019060a 100644 --- a/pkg/migration/converter.go +++ b/pkg/migration/converter.go @@ -21,6 +21,7 @@ import ( xpmetav1 "github.com/crossplane/crossplane/apis/pkg/meta/v1" xpmetav1alpha1 "github.com/crossplane/crossplane/apis/pkg/meta/v1alpha1" xppkgv1 "github.com/crossplane/crossplane/apis/pkg/v1" + xppkgv1beta1 "github.com/crossplane/crossplane/apis/pkg/v1beta1" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -35,9 +36,9 @@ const ( errFromUnstructuredConfMeta = "failed to convert from unstructured.Unstructured to Crossplane Configuration metadata" errFromUnstructuredConfPackage = "failed to convert from unstructured.Unstructured to Crossplane Configuration package" errFromUnstructuredProvider = "failed to convert from unstructured.Unstructured to Crossplane Provider package" - // errFromUnstructuredLock = "failed to convert from unstructured.Unstructured to Crossplane package lock" - errToUnstructured = "failed to convert from the managed resource type to unstructured.Unstructured" - errRawExtensionUnmarshal = "failed to unmarshal runtime.RawExtension" + errFromUnstructuredLock = "failed to convert from unstructured.Unstructured to Crossplane package lock" + errToUnstructured = "failed to convert from the managed resource type to unstructured.Unstructured" + errRawExtensionUnmarshal = "failed to unmarshal runtime.RawExtension" errFmtPavedDelete = "failed to delete fieldpath %q from paved" ) @@ -251,10 +252,10 @@ func getCategory(u unstructured.Unstructured) Category { } } -/*func toPackageLock(u unstructured.Unstructured) (*xppkgv1beta1.Lock, error) { +func toPackageLock(u unstructured.Unstructured) (*xppkgv1beta1.Lock, error) { lock := &xppkgv1beta1.Lock{} if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, lock); err != nil { return nil, errors.Wrap(err, errFromUnstructuredLock) } return lock, nil -}*/ +} diff --git a/pkg/migration/package_lock_steps.go b/pkg/migration/package_lock_steps.go new file mode 100644 index 00000000..910aecef --- /dev/null +++ b/pkg/migration/package_lock_steps.go @@ -0,0 +1,66 @@ +// Copyright 2023 Upbound Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package migration + +import ( + "fmt" + + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func (pg *PlanGenerator) convertPackageLock(o UnstructuredWithMetadata) error { + // TODO: if a lock converter does not convert the given lock, + // we will have a false positive. Better to compute and check + // a diff here. + if len(pg.registry.packageLockConverters) == 0 { + return nil + } + + lock, err := toPackageLock(o.Object) + if err != nil { + return err + } + for _, lockConv := range pg.registry.packageLockConverters { + if err := lockConv.PackageLockV1Beta1(lock); err != nil { + return errors.Wrapf(err, "failed to call converter on package lock: %s", lock.GetName()) + } + } + target := &UnstructuredWithMetadata{ + Object: ToSanitizedUnstructured(lock), + Metadata: o.Metadata, + } + if err := pg.stepEditPackageLock(o, target); err != nil { + return err + } + return nil +} + +func (pg *PlanGenerator) stepEditPackageLock(source UnstructuredWithMetadata, t *UnstructuredWithMetadata) error { + // add step for editing the package lock + s := pg.stepConfiguration(stepEditPackageLock) + t.Metadata.Path = fmt.Sprintf("%s/%s.yaml", s.Name, getVersionedName(t.Object)) + s.Patch.Files = append(s.Patch.Files, t.Metadata.Path) + patchMap, err := computeJSONMergePathDoc(source.Object, t.Object) + if err != nil { + return err + } + return errors.Wrap(pg.target.Put(UnstructuredWithMetadata{ + Object: unstructured.Unstructured{ + Object: addNameGVK(t.Object, patchMap), + }, + Metadata: t.Metadata, + }), errEditConfigurationPackageFmt) +} diff --git a/pkg/migration/plan_generator.go b/pkg/migration/plan_generator.go index 3ac6ea84..08e7a2bb 100644 --- a/pkg/migration/plan_generator.go +++ b/pkg/migration/plan_generator.go @@ -48,6 +48,7 @@ const ( errConfigurationMetadataMigrateFmt = "failed to migrate the configuration metadata: %s" errConfigurationPackageMigrateFmt = "failed to migrate the configuration package: %s" errProviderMigrateFmt = "failed to migrate the Provider package: %s" + errLockMigrateFmt = "failed to migrate the package lock: %s" errComposedTemplateBase = "failed to migrate the base of a composed template" errComposedTemplateMigrate = "failed to migrate the composed templates of the composition" errResourceOutput = "failed to output migrated resource" @@ -256,6 +257,9 @@ func (pg *PlanGenerator) convert() error { //nolint: gocyclo } } case xppkgv1beta1.LockGroupVersionKind: + if err := pg.convertPackageLock(o); err != nil { + return errors.Wrapf(err, errLockMigrateFmt, o.Object.GetName()) + } default: if o.Metadata.Category == CategoryComposite { if err := pg.stepPauseComposite(&o); err != nil { diff --git a/pkg/migration/plan_generator_test.go b/pkg/migration/plan_generator_test.go index 826d65ea..ad7b30fd 100644 --- a/pkg/migration/plan_generator_test.go +++ b/pkg/migration/plan_generator_test.go @@ -27,6 +27,7 @@ import ( xpmetav1 "github.com/crossplane/crossplane/apis/pkg/meta/v1" xpmetav1alpha1 "github.com/crossplane/crossplane/apis/pkg/meta/v1alpha1" xppkgv1 "github.com/crossplane/crossplane/apis/pkg/v1" + xppkgv1beta1 "github.com/crossplane/crossplane/apis/pkg/v1beta1" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -212,6 +213,7 @@ func TestGeneratePlan(t *testing.T) { "testdata/plan/providerv1.yaml": {}, "testdata/plan/configurationv1.yaml": {}, "testdata/plan/configurationpkgv1.yaml": {}, + "testdata/plan/lockv1beta1.yaml": {}, }), target: newTestTarget(), registry: getRegistry( @@ -230,7 +232,8 @@ func TestGeneratePlan(t *testing.T) { withProviderPackageConverter(providerPackageConverter{ re: regexp.MustCompile(`xpkg.upbound.io/upbound/provider-aws:.+`), converter: &monolithicProviderToSSOPConverter{}, - })), + }), + withPackageLockConverter(&packageLockConverter{})), }, want: want{ migrationPlanPath: "testdata/plan/generated/configurationv1_providerv1_migration_plan.yaml", @@ -245,6 +248,7 @@ func TestGeneratePlan(t *testing.T) { "activate-ssop/provider-family-aws.providers.pkg.crossplane.io_v1.yaml", "activate-ssop/provider-aws-ec2.providers.pkg.crossplane.io_v1.yaml", "activate-ssop/provider-aws-eks.providers.pkg.crossplane.io_v1.yaml", + "edit-package-lock/lock.locks.pkg.crossplane.io_v1beta1.yaml", }, }, }, @@ -433,6 +437,12 @@ func withProviderPackageConverter(c providerPackageConverter) registryOption { } } +func withPackageLockConverter(c PackageLockConverter) registryOption { + return func(r *Registry) { + r.RegisterPackageLockConverter(c) + } +} + func withPreProcessor(c Category, pp UnstructuredPreProcessor) registryOption { return func(r *Registry) { r.RegisterPreProcessor(c, pp) @@ -546,6 +556,18 @@ func (c *monolithicProviderToSSOPConverter) ProviderPackageV1(_ xppkgv1.Provider }, nil } +type packageLockConverter struct{} + +func (p *packageLockConverter) PackageLockV1Beta1(lock *xppkgv1beta1.Lock) error { + lock.Packages = append(lock.Packages, xppkgv1beta1.LockPackage{ + Name: "test-provider", + Type: xppkgv1beta1.ProviderPackageType, + Source: "xpkg.upbound.io/upbound/test-provider", + Version: "vX.Y.Z", + }) + return nil +} + type preProcessor struct { results []string } diff --git a/pkg/migration/plan_steps.go b/pkg/migration/plan_steps.go index c2193382..f12fa784 100644 --- a/pkg/migration/plan_steps.go +++ b/pkg/migration/plan_steps.go @@ -19,14 +19,11 @@ import ( "sort" "strings" - "k8s.io/apimachinery/pkg/util/rand" - - "k8s.io/apimachinery/pkg/util/jsonmergepatch" - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/json" + "k8s.io/apimachinery/pkg/util/jsonmergepatch" + "k8s.io/apimachinery/pkg/util/rand" ) type step int diff --git a/pkg/migration/testdata/plan/generated/configurationv1_providerv1_migration_plan.yaml b/pkg/migration/testdata/plan/generated/configurationv1_providerv1_migration_plan.yaml index a70677c1..057f9648 100644 --- a/pkg/migration/testdata/plan/generated/configurationv1_providerv1_migration_plan.yaml +++ b/pkg/migration/testdata/plan/generated/configurationv1_providerv1_migration_plan.yaml @@ -20,6 +20,13 @@ spec: name: disable-dependency-resolution type: Patch + - patch: + type: merge + files: + - edit-package-lock/lock.locks.pkg.crossplane.io_v1beta1.yaml + name: edit-package-lock + type: Patch + - delete: options: finalizerPolicy: Remove diff --git a/pkg/migration/testdata/plan/generated/edit-package-lock/lock.locks.pkg.crossplane.io_v1beta1.yaml b/pkg/migration/testdata/plan/generated/edit-package-lock/lock.locks.pkg.crossplane.io_v1beta1.yaml new file mode 100644 index 00000000..3a0cfdb5 --- /dev/null +++ b/pkg/migration/testdata/plan/generated/edit-package-lock/lock.locks.pkg.crossplane.io_v1beta1.yaml @@ -0,0 +1,14 @@ +apiVersion: pkg.crossplane.io/v1beta1 +kind: Lock +metadata: + name: lock +packages: + - name: provider-aws + type: Provider + source: xpkg.upbound.io/upbound/provider-aws + version: v0.36.0 + - name: test-provider + type: Provider + source: xpkg.upbound.io/upbound/test-provider + version: vX.Y.Z + diff --git a/pkg/migration/testdata/plan/lockv1beta1.yaml b/pkg/migration/testdata/plan/lockv1beta1.yaml new file mode 100644 index 00000000..ac24f14e --- /dev/null +++ b/pkg/migration/testdata/plan/lockv1beta1.yaml @@ -0,0 +1,13 @@ +apiVersion: pkg.crossplane.io/v1beta1 +kind: Lock +metadata: + creationTimestamp: "2023-05-15T12:37:16Z" + generation: 9 + name: lock + resourceVersion: "10366" + uid: b1aabaaa-56bb-4356-ae45-1e3131cb9743 +packages: + - name: provider-aws + type: Provider + source: xpkg.upbound.io/upbound/provider-aws + version: v0.36.0