github.com/crossplane/upjet@v1.3.0/pkg/migration/configurationmetadata_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  	"strconv"
    10  
    11  	xpmetav1 "github.com/crossplane/crossplane/apis/pkg/meta/v1"
    12  	xpmetav1alpha1 "github.com/crossplane/crossplane/apis/pkg/meta/v1alpha1"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  const (
    17  	// configuration migration steps follow any existing API migration steps
    18  	stepBackupMRs = iota + stepAPIEnd + 1
    19  	stepBackupComposites
    20  	stepBackupClaims
    21  	stepOrphanMRs
    22  	stepNewFamilyProvider
    23  	stepCheckHealthFamilyProvider
    24  	stepNewServiceScopedProvider
    25  	stepCheckHealthNewServiceScopedProvider
    26  	stepConfigurationPackageDisableDepResolution
    27  	stepEditPackageLock
    28  	stepDeleteMonolithicProvider
    29  	stepActivateFamilyProviderRevision
    30  	stepCheckInstallationFamilyProviderRevision
    31  	stepActivateServiceScopedProviderRevision
    32  	stepCheckInstallationServiceScopedProviderRevision
    33  	stepEditConfigurationMetadata
    34  	stepBuildConfiguration
    35  	stepPushConfiguration
    36  	stepEditConfigurationPackage
    37  	stepConfigurationPackageEnableDepResolution
    38  	stepRevertOrphanMRs
    39  	stepConfigurationEnd
    40  )
    41  
    42  func getConfigurationMigrationSteps() []step {
    43  	steps := make([]step, 0, stepConfigurationEnd-stepAPIEnd-1)
    44  	for i := stepAPIEnd + 1; i < stepConfigurationEnd; i++ {
    45  		steps = append(steps, i)
    46  	}
    47  	return steps
    48  }
    49  
    50  const (
    51  	errConfigurationMetadataOutput = "failed to output configuration YAML document"
    52  )
    53  
    54  func (pg *PlanGenerator) convertConfigurationMetadata(o UnstructuredWithMetadata) error {
    55  	isConverted := false
    56  	conf, err := toConfigurationMetadata(o.Object)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	for _, confConv := range pg.registry.configurationMetaConverters {
    61  		if confConv.re == nil || confConv.converter == nil || !confConv.re.MatchString(o.Object.GetName()) {
    62  			continue
    63  		}
    64  
    65  		switch o.Object.GroupVersionKind().Version {
    66  		case "v1alpha1":
    67  			err = confConv.converter.ConfigurationMetadataV1Alpha1(conf.(*xpmetav1alpha1.Configuration))
    68  		default:
    69  			err = confConv.converter.ConfigurationMetadataV1(conf.(*xpmetav1.Configuration))
    70  		}
    71  		if err != nil {
    72  			return errors.Wrapf(err, "failed to call converter on Configuration: %s", conf.GetName())
    73  		}
    74  		// TODO: if a configuration converter only converts a specific version,
    75  		// (or does not convert the given configuration),
    76  		// we will have a false positive. Better to compute and check
    77  		// a diff here.
    78  		isConverted = true
    79  	}
    80  	if !isConverted {
    81  		return nil
    82  	}
    83  	return pg.stepEditConfigurationMetadata(o, &UnstructuredWithMetadata{
    84  		Object:   ToSanitizedUnstructured(conf),
    85  		Metadata: o.Metadata,
    86  	})
    87  }
    88  
    89  func (pg *PlanGenerator) stepConfiguration(s step) *Step {
    90  	return pg.stepConfigurationWithSubStep(s, false)
    91  }
    92  
    93  func (pg *PlanGenerator) configurationSubStep(s step) string {
    94  	ss := -1
    95  	subStep := pg.subSteps[s]
    96  	if subStep != "" {
    97  		s, err := strconv.Atoi(subStep)
    98  		if err == nil {
    99  			ss = s
   100  		}
   101  	}
   102  	pg.subSteps[s] = strconv.Itoa(ss + 1)
   103  	return pg.subSteps[s]
   104  }
   105  
   106  func (pg *PlanGenerator) stepConfigurationWithSubStep(s step, newSubStep bool) *Step { //nolint:gocyclo // easy to follow all steps here
   107  	stepKey := strconv.Itoa(int(s))
   108  	if newSubStep {
   109  		stepKey = fmt.Sprintf("%s.%s", stepKey, pg.configurationSubStep(s))
   110  	}
   111  	if pg.Plan.Spec.stepMap[stepKey] != nil {
   112  		return pg.Plan.Spec.stepMap[stepKey]
   113  	}
   114  
   115  	pg.Plan.Spec.stepMap[stepKey] = &Step{}
   116  	switch s { //nolint:exhaustive
   117  	case stepOrphanMRs:
   118  		setPatchStep("deletion-policy-orphan", pg.Plan.Spec.stepMap[stepKey])
   119  	case stepRevertOrphanMRs:
   120  		setPatchStep("deletion-policy-delete", pg.Plan.Spec.stepMap[stepKey])
   121  	case stepNewFamilyProvider:
   122  		setApplyStep("new-ssop", pg.Plan.Spec.stepMap[stepKey])
   123  	case stepNewServiceScopedProvider:
   124  		setApplyStep("new-ssop", pg.Plan.Spec.stepMap[stepKey])
   125  	case stepConfigurationPackageDisableDepResolution:
   126  		setPatchStep("disable-dependency-resolution", pg.Plan.Spec.stepMap[stepKey])
   127  	case stepConfigurationPackageEnableDepResolution:
   128  		setPatchStep("enable-dependency-resolution", pg.Plan.Spec.stepMap[stepKey])
   129  	case stepEditConfigurationPackage:
   130  		setPatchStep("edit-configuration-package", pg.Plan.Spec.stepMap[stepKey])
   131  	case stepEditPackageLock:
   132  		setPatchStep("edit-package-lock", pg.Plan.Spec.stepMap[stepKey])
   133  	case stepDeleteMonolithicProvider:
   134  		setDeleteStep("delete-monolithic-provider", pg.Plan.Spec.stepMap[stepKey])
   135  	case stepActivateFamilyProviderRevision:
   136  		setPatchStep("activate-ssop", pg.Plan.Spec.stepMap[stepKey])
   137  	case stepActivateServiceScopedProviderRevision:
   138  		setPatchStep("activate-ssop", pg.Plan.Spec.stepMap[stepKey])
   139  	case stepEditConfigurationMetadata:
   140  		setExecStep("edit-configuration-metadata", pg.Plan.Spec.stepMap[stepKey])
   141  	case stepBackupMRs:
   142  		setExecStep("backup-managed-resources", pg.Plan.Spec.stepMap[stepKey])
   143  	case stepBackupComposites:
   144  		setExecStep("backup-composite-resources", pg.Plan.Spec.stepMap[stepKey])
   145  	case stepBackupClaims:
   146  		setExecStep("backup-claim-resources", pg.Plan.Spec.stepMap[stepKey])
   147  	case stepCheckHealthFamilyProvider:
   148  		setExecStep("wait-for-healthy", pg.Plan.Spec.stepMap[stepKey])
   149  	case stepCheckHealthNewServiceScopedProvider:
   150  		setExecStep("wait-for-healthy", pg.Plan.Spec.stepMap[stepKey])
   151  	case stepCheckInstallationFamilyProviderRevision:
   152  		setExecStep("wait-for-installed", pg.Plan.Spec.stepMap[stepKey])
   153  	case stepCheckInstallationServiceScopedProviderRevision:
   154  		setExecStep("wait-for-installed", pg.Plan.Spec.stepMap[stepKey])
   155  	case stepBuildConfiguration:
   156  		setExecStep("build-configuration", pg.Plan.Spec.stepMap[stepKey])
   157  	case stepPushConfiguration:
   158  		setExecStep("push-configuration", pg.Plan.Spec.stepMap[stepKey])
   159  	default:
   160  		panic(fmt.Sprintf(errInvalidStepFmt, s))
   161  	}
   162  	return pg.Plan.Spec.stepMap[stepKey]
   163  }
   164  
   165  func (pg *PlanGenerator) stepEditConfigurationMetadata(source UnstructuredWithMetadata, target *UnstructuredWithMetadata) error {
   166  	s := pg.stepConfiguration(stepEditConfigurationMetadata)
   167  	target.Metadata.Path = fmt.Sprintf("%s/%s.yaml", s.Name, getVersionedName(target.Object))
   168  	s.Exec.Args = []string{"-c", fmt.Sprintf("cp %s %s", target.Metadata.Path, source.Metadata.Path)}
   169  	return errors.Wrap(pg.target.Put(*target), errConfigurationMetadataOutput)
   170  }