github.com/crossplane/upjet@v1.3.0/pkg/migration/configurationpackage_steps.go (about) 1 // SPDX-FileCopyrightText: 2023 The Crossplane Authors <https://crossplane.io> 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package migration 6 7 import ( 8 "fmt" 9 10 v1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 11 "github.com/crossplane/crossplane-runtime/pkg/fieldpath" 12 "github.com/pkg/errors" 13 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 14 ) 15 16 const ( 17 errSetDeletionPolicyFmt = "failed to put the patch file to set the deletion policy to %q: %s" 18 errEditConfigurationPackageFmt = `failed to put the edited Configuration package: %s` 19 ) 20 21 func (pg *PlanGenerator) convertConfigurationPackage(o UnstructuredWithMetadata) error { 22 pkg, err := toConfigurationPackageV1(o.Object) 23 if err != nil { 24 return err 25 } 26 27 // add step for disabling the dependency resolution 28 // for the configuration package 29 s := pg.stepConfiguration(stepConfigurationPackageDisableDepResolution) 30 p := fmt.Sprintf("%s/%s.yaml", s.Name, getVersionedName(o.Object)) 31 s.Patch.Files = append(s.Patch.Files, p) 32 if err := pg.target.Put(UnstructuredWithMetadata{ 33 Object: unstructured.Unstructured{ 34 Object: addNameGVK(o.Object, map[string]any{ 35 "spec": map[string]any{ 36 "skipDependencyResolution": true, 37 }, 38 }), 39 }, 40 Metadata: Metadata{ 41 Path: p, 42 }, 43 }); err != nil { 44 return err 45 } 46 47 // add step for enabling the dependency resolution 48 // for the configuration package 49 s = pg.stepConfiguration(stepConfigurationPackageEnableDepResolution) 50 p = fmt.Sprintf("%s/%s.yaml", s.Name, getVersionedName(o.Object)) 51 s.Patch.Files = append(s.Patch.Files, p) 52 if err := pg.target.Put(UnstructuredWithMetadata{ 53 Object: unstructured.Unstructured{ 54 Object: addNameGVK(o.Object, map[string]any{ 55 "spec": map[string]any{ 56 "skipDependencyResolution": false, 57 }, 58 }), 59 }, 60 Metadata: Metadata{ 61 Path: p, 62 }, 63 }); err != nil { 64 return err 65 } 66 67 // add the step for editing the configuration package 68 for _, pkgConv := range pg.registry.configurationPackageConverters { 69 if pkgConv.re == nil || pkgConv.converter == nil || !pkgConv.re.MatchString(pkg.Spec.Package) { 70 continue 71 } 72 err := pkgConv.converter.ConfigurationPackageV1(pkg) 73 if err != nil { 74 return errors.Wrapf(err, "failed to call converter on Configuration package: %s", pkg.Spec.Package) 75 } 76 // TODO: if a converter only converts a specific version, 77 // (or does not convert the given configuration), 78 // we will have a false positive. Better to compute and check 79 // a diff here. 80 target := &UnstructuredWithMetadata{ 81 Object: ToSanitizedUnstructured(pkg), 82 Metadata: o.Metadata, 83 } 84 if err := pg.stepEditConfigurationPackage(o, target); err != nil { 85 return err 86 } 87 } 88 return nil 89 } 90 91 func (pg *PlanGenerator) stepEditConfigurationPackage(source UnstructuredWithMetadata, t *UnstructuredWithMetadata) error { 92 if !pg.stepEnabled(stepEditConfigurationPackage) { 93 return nil 94 } 95 s := pg.stepConfigurationWithSubStep(stepEditConfigurationPackage, true) 96 t.Metadata.Path = fmt.Sprintf("%s/%s.yaml", s.Name, getVersionedName(t.Object)) 97 s.Patch.Files = append(s.Patch.Files, t.Metadata.Path) 98 patchMap, err := computeJSONMergePathDoc(source.Object, t.Object) 99 if err != nil { 100 return err 101 } 102 return errors.Wrapf(pg.target.Put(UnstructuredWithMetadata{ 103 Object: unstructured.Unstructured{ 104 Object: addNameGVK(t.Object, patchMap), 105 }, 106 Metadata: t.Metadata, 107 }), errEditConfigurationPackageFmt, t.Object.GetName()) 108 } 109 110 func (pg *PlanGenerator) stepOrhanMR(u UnstructuredWithMetadata) (bool, error) { 111 return pg.stepSetDeletionPolicy(u, stepOrphanMRs, v1.DeletionOrphan, true) 112 } 113 114 func (pg *PlanGenerator) stepRevertOrhanMR(u UnstructuredWithMetadata) (bool, error) { 115 return pg.stepSetDeletionPolicy(u, stepRevertOrphanMRs, v1.DeletionDelete, false) 116 } 117 118 func (pg *PlanGenerator) stepSetDeletionPolicy(u UnstructuredWithMetadata, step step, policy v1.DeletionPolicy, checkCurrentPolicy bool) (bool, error) { 119 if !pg.stepEnabled(step) { 120 return false, nil 121 } 122 pv := fieldpath.Pave(u.Object.Object) 123 p, err := pv.GetString("spec.deletionPolicy") 124 if err != nil && !fieldpath.IsNotFound(err) { 125 return false, errors.Wrapf(err, "failed to get the current deletion policy from MR: %s", u.Object.GetName()) 126 } 127 if checkCurrentPolicy && err == nil && v1.DeletionPolicy(p) == policy { 128 return false, nil 129 } 130 s := pg.stepConfiguration(step) 131 u.Metadata.Path = fmt.Sprintf("%s/%s.yaml", s.Name, getVersionedName(u.Object)) 132 s.Patch.Files = append(s.Patch.Files, u.Metadata.Path) 133 return true, errors.Wrapf(pg.target.Put(UnstructuredWithMetadata{ 134 Object: unstructured.Unstructured{ 135 Object: addNameGVK(u.Object, map[string]any{ 136 "spec": map[string]any{ 137 "deletionPolicy": string(policy), 138 }, 139 }), 140 }, 141 Metadata: u.Metadata, 142 }), errSetDeletionPolicyFmt, policy, u.Object.GetName()) 143 }