2022-09-05 03:06:08 -04:00
/ *
Copyright ( c ) Edgeless Systems GmbH
SPDX - License - Identifier : AGPL - 3.0 - only
* /
2022-08-29 10:49:44 -04:00
package cmd
import (
"context"
2023-01-04 07:55:10 -05:00
"errors"
2022-12-19 10:52:15 -05:00
"fmt"
2023-05-22 07:31:20 -04:00
"path/filepath"
2022-12-19 10:52:15 -05:00
"time"
2022-08-29 10:49:44 -04:00
2023-07-21 04:04:29 -04:00
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
2023-05-03 05:11:53 -04:00
"github.com/edgelesssys/constellation/v2/cli/internal/clusterid"
2023-01-04 07:55:10 -05:00
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
2023-03-30 10:13:14 -04:00
"github.com/edgelesssys/constellation/v2/cli/internal/kubernetes"
2023-05-22 07:31:20 -04:00
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/cli/internal/upgrade"
2023-06-07 10:16:32 -04:00
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
2023-06-09 09:41:02 -04:00
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
2023-03-24 12:07:14 -04:00
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
2023-02-28 04:23:09 -05:00
"github.com/edgelesssys/constellation/v2/internal/compatibility"
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/internal/config"
2023-05-03 05:11:53 -04:00
"github.com/edgelesssys/constellation/v2/internal/constants"
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/internal/file"
2023-05-23 03:17:27 -04:00
"github.com/edgelesssys/constellation/v2/internal/imagefetcher"
2023-06-05 03:13:02 -04:00
"github.com/edgelesssys/constellation/v2/internal/versions"
2022-08-29 10:49:44 -04:00
"github.com/spf13/afero"
"github.com/spf13/cobra"
2023-03-14 13:34:58 -04:00
corev1 "k8s.io/api/core/v1"
2022-08-29 10:49:44 -04:00
)
2023-02-01 04:56:47 -05:00
func newUpgradeApplyCmd ( ) * cobra . Command {
2022-08-29 10:49:44 -04:00
cmd := & cobra . Command {
2023-02-09 09:54:12 -05:00
Use : "apply" ,
2023-02-01 04:56:47 -05:00
Short : "Apply an upgrade to a Constellation cluster" ,
Long : "Apply an upgrade to a Constellation cluster by applying the chosen configuration." ,
2022-08-29 10:49:44 -04:00
Args : cobra . NoArgs ,
2023-02-01 04:56:47 -05:00
RunE : runUpgradeApply ,
2022-08-29 10:49:44 -04:00
}
2023-01-17 08:01:56 -05:00
cmd . Flags ( ) . BoolP ( "yes" , "y" , false , "run upgrades without further confirmation\n" +
2023-03-14 13:34:58 -04:00
"WARNING: might delete your resources in case you are using cert-manager in your cluster. Please read the docs.\n" +
"WARNING: might unintentionally overwrite measurements in the running cluster." )
2023-06-06 09:22:06 -04:00
cmd . Flags ( ) . Duration ( "timeout" , 5 * time . Minute , "change helm upgrade timeout\n" +
2023-02-01 05:23:57 -05:00
"Might be useful for slow connections or big clusters." )
2022-12-19 10:52:15 -05:00
if err := cmd . Flags ( ) . MarkHidden ( "timeout" ) ; err != nil {
panic ( err )
}
2022-08-29 10:49:44 -04:00
return cmd
}
2023-03-20 06:03:36 -04:00
func runUpgradeApply ( cmd * cobra . Command , _ [ ] string ) error {
2022-12-19 10:52:15 -05:00
log , err := newCLILogger ( cmd )
if err != nil {
return fmt . Errorf ( "creating logger: %w" , err )
}
defer log . Sync ( )
2022-08-29 10:49:44 -04:00
fileHandler := file . NewHandler ( afero . NewOsFs ( ) )
2023-08-04 07:53:51 -04:00
upgrader , err := kubernetes . NewUpgrader (
cmd . Context ( ) , cmd . OutOrStdout ( ) ,
constants . UpgradeDir , constants . AdminConfFilename ,
fileHandler , log , kubernetes . UpgradeCmdKindApply ,
)
2022-08-29 10:49:44 -04:00
if err != nil {
return err
}
2023-06-01 07:55:46 -04:00
imagefetcher := imagefetcher . New ( )
2023-06-07 10:16:32 -04:00
configFetcher := attestationconfigapi . NewFetcher ( )
2023-05-22 07:31:20 -04:00
2023-07-26 11:29:03 -04:00
applyCmd := upgradeApplyCmd { upgrader : upgrader , log : log , imageFetcher : imagefetcher , configFetcher : configFetcher }
2023-03-03 03:38:23 -05:00
return applyCmd . upgradeApply ( cmd , fileHandler )
2022-08-29 10:49:44 -04:00
}
2023-02-09 09:54:12 -05:00
type upgradeApplyCmd struct {
2023-07-26 11:29:03 -04:00
upgrader cloudUpgrader
imageFetcher imageFetcher
configFetcher attestationconfigapi . Fetcher
log debugLog
2023-02-09 09:54:12 -05:00
}
2023-03-03 03:38:23 -05:00
func ( u * upgradeApplyCmd ) upgradeApply ( cmd * cobra . Command , fileHandler file . Handler ) error {
2023-02-01 04:56:47 -05:00
flags , err := parseUpgradeApplyFlags ( cmd )
2022-08-29 10:49:44 -04:00
if err != nil {
2023-01-04 07:55:10 -05:00
return fmt . Errorf ( "parsing flags: %w" , err )
2022-08-29 10:49:44 -04:00
}
2023-07-26 11:29:03 -04:00
2023-08-04 07:53:51 -04:00
conf , err := config . New ( fileHandler , constants . ConfigFilename , u . configFetcher , flags . force )
2023-02-07 06:56:25 -05:00
var configValidationErr * config . ValidationError
if errors . As ( err , & configValidationErr ) {
cmd . PrintErrln ( configValidationErr . LongMessage ( ) )
}
2022-08-29 10:49:44 -04:00
if err != nil {
2023-02-07 06:56:25 -05:00
return err
2022-08-29 10:49:44 -04:00
}
2023-07-26 11:29:03 -04:00
if upgradeRequiresIAMMigration ( conf . GetProvider ( ) ) {
cmd . Println ( "WARNING: This upgrade requires an IAM migration. Please make sure you have applied the IAM migration using `iam upgrade apply` before continuing." )
if ! flags . yes {
yes , err := askToConfirm ( cmd , "Did you upgrade the IAM resources?" )
if err != nil {
return fmt . Errorf ( "asking for confirmation: %w" , err )
}
if ! yes {
cmd . Println ( "Skipping upgrade." )
return nil
}
}
}
2022-08-29 10:49:44 -04:00
2023-06-05 03:13:02 -04:00
if err := handleInvalidK8sPatchVersion ( cmd , conf . KubernetesVersion , flags . yes ) ; err != nil {
return err
}
2023-05-03 05:11:53 -04:00
var idFile clusterid . File
2023-08-04 07:53:51 -04:00
if err := fileHandler . ReadJSON ( constants . ClusterIDsFilename , & idFile ) ; err != nil {
2023-05-03 05:11:53 -04:00
return fmt . Errorf ( "reading cluster ID file: %w" , err )
}
conf . UpdateMAAURL ( idFile . AttestationURL )
// If an image upgrade was just executed there won't be a diff. The function will return nil in that case.
if err := u . upgradeAttestConfigIfDiff ( cmd , conf . GetAttestationConfig ( ) , flags ) ; err != nil {
return fmt . Errorf ( "upgrading measurements: %w" , err )
}
2023-07-24 04:30:53 -04:00
// not moving existing Terraform migrator because of planned apply refactor
2023-08-04 07:53:51 -04:00
if err := u . migrateTerraform ( cmd , u . imageFetcher , conf , fileHandler , flags ) ; err != nil {
2023-05-22 07:31:20 -04:00
return fmt . Errorf ( "performing Terraform migrations: %w" , err )
}
2023-07-21 10:43:51 -04:00
// reload idFile after terraform migration
// it might have been updated by the migration
2023-08-04 07:53:51 -04:00
if err := fileHandler . ReadJSON ( constants . ClusterIDsFilename , & idFile ) ; err != nil {
2023-07-21 10:43:51 -04:00
return fmt . Errorf ( "reading updated cluster ID file: %w" , err )
}
// extend the clusterConfig cert SANs with any of the supported endpoints:
// - (legacy) public IP
// - fallback endpoint
// - custom (user-provided) endpoint
sans := append ( [ ] string { idFile . IP , conf . CustomEndpoint } , idFile . APIServerCertSANs ... )
if err := u . upgrader . ExtendClusterConfigCertSANs ( cmd . Context ( ) , sans ) ; err != nil {
return fmt . Errorf ( "extending cert SANs: %w" , err )
}
2023-05-22 07:31:20 -04:00
2023-05-19 07:57:31 -04:00
if conf . GetProvider ( ) == cloudprovider . Azure || conf . GetProvider ( ) == cloudprovider . GCP || conf . GetProvider ( ) == cloudprovider . AWS {
2023-06-30 10:46:05 -04:00
var upgradeErr * compatibility . InvalidUpgradeError
2023-07-24 04:30:53 -04:00
err = u . handleServiceUpgrade ( cmd , conf , idFile , flags )
2023-03-24 12:07:14 -04:00
switch {
2023-06-30 10:46:05 -04:00
case errors . As ( err , & upgradeErr ) :
2023-03-24 12:07:14 -04:00
cmd . PrintErrln ( err )
case err != nil :
return fmt . Errorf ( "upgrading services: %w" , err )
}
2022-12-19 10:52:15 -05:00
2023-06-21 09:49:42 -04:00
err = u . upgrader . UpgradeNodeVersion ( cmd . Context ( ) , conf , flags . force )
2023-03-24 12:07:14 -04:00
switch {
2023-03-30 10:13:14 -04:00
case errors . Is ( err , kubernetes . ErrInProgress ) :
2023-03-24 12:07:14 -04:00
cmd . PrintErrln ( "Skipping image and Kubernetes upgrades. Another upgrade is in progress." )
2023-06-30 10:46:05 -04:00
case errors . As ( err , & upgradeErr ) :
2023-03-24 12:07:14 -04:00
cmd . PrintErrln ( err )
case err != nil :
return fmt . Errorf ( "upgrading NodeVersion: %w" , err )
}
} else {
2023-05-19 07:57:31 -04:00
cmd . PrintErrln ( "WARNING: Skipping service and image upgrades, which are currently only supported for AWS, Azure, and GCP." )
2023-02-09 09:54:12 -05:00
}
2023-03-14 13:34:58 -04:00
return nil
}
2023-07-21 04:04:29 -04:00
func getImage ( ctx context . Context , conf * config . Config , fetcher imageFetcher ) ( string , error ) {
// Fetch variables to execute Terraform script with
provider := conf . GetProvider ( )
attestationVariant := conf . GetAttestationConfig ( ) . GetVariant ( )
region := conf . GetRegion ( )
return fetcher . FetchReference ( ctx , provider , attestationVariant , conf . Image , region )
}
2023-05-22 07:31:20 -04:00
// migrateTerraform checks if the Constellation version the cluster is being upgraded to requires a migration
// of cloud resources with Terraform. If so, the migration is performed.
2023-08-04 07:53:51 -04:00
func ( u * upgradeApplyCmd ) migrateTerraform (
cmd * cobra . Command , fetcher imageFetcher , conf * config . Config , fileHandler file . Handler , flags upgradeApplyFlags ,
) error {
2023-05-22 07:31:20 -04:00
u . log . Debugf ( "Planning Terraform migrations" )
2023-08-04 07:53:51 -04:00
if err := u . upgrader . CheckTerraformMigrations ( constants . UpgradeDir ) ; err != nil {
2023-05-22 07:31:20 -04:00
return fmt . Errorf ( "checking workspace: %w" , err )
}
2023-06-27 07:12:50 -04:00
// TODO(AB#3248): Remove this migration after we can assume that all existing clusters have been migrated.
var awsZone string
if conf . GetProvider ( ) == cloudprovider . AWS {
awsZone = conf . Provider . AWS . Zone
}
manualMigrations := terraformMigrationAWSNodeGroups ( conf . GetProvider ( ) , awsZone )
for _ , migration := range manualMigrations {
u . log . Debugf ( "Adding manual Terraform migration: %s" , migration . DisplayName )
u . upgrader . AddManualStateMigration ( migration )
}
2023-07-21 04:04:29 -04:00
imageRef , err := getImage ( cmd . Context ( ) , conf , fetcher )
if err != nil {
return fmt . Errorf ( "fetching image reference: %w" , err )
}
vars , err := cloudcmd . TerraformUpgradeVars ( conf , imageRef )
2023-05-22 07:31:20 -04:00
if err != nil {
return fmt . Errorf ( "parsing upgrade variables: %w" , err )
}
u . log . Debugf ( "Using Terraform variables:\n%v" , vars )
opts := upgrade . TerraformUpgradeOptions {
2023-08-04 07:53:51 -04:00
LogLevel : flags . terraformLogLevel ,
CSP : conf . GetProvider ( ) ,
Vars : vars ,
TFWorkspace : constants . TerraformWorkingDir ,
UpgradeWorkspace : constants . UpgradeDir ,
2023-05-22 07:31:20 -04:00
}
// Check if there are any Terraform migrations to apply
hasDiff , err := u . upgrader . PlanTerraformMigrations ( cmd . Context ( ) , opts )
if err != nil {
return fmt . Errorf ( "planning terraform migrations: %w" , err )
}
if hasDiff {
// If there are any Terraform migrations to apply, ask for confirmation
2023-06-19 07:02:01 -04:00
fmt . Fprintln ( cmd . OutOrStdout ( ) , "The upgrade requires a migration of Constellation cloud resources by applying an updated Terraform template. Please manually review the suggested changes below." )
2023-05-22 07:31:20 -04:00
if ! flags . yes {
ok , err := askToConfirm ( cmd , "Do you want to apply the Terraform migrations?" )
if err != nil {
return fmt . Errorf ( "asking for confirmation: %w" , err )
}
if ! ok {
cmd . Println ( "Aborting upgrade." )
2023-08-04 07:53:51 -04:00
if err := u . upgrader . CleanUpTerraformMigrations ( constants . UpgradeDir ) ; err != nil {
2023-05-22 07:31:20 -04:00
return fmt . Errorf ( "cleaning up workspace: %w" , err )
}
return fmt . Errorf ( "aborted by user" )
}
}
2023-08-04 07:53:51 -04:00
2023-05-22 07:31:20 -04:00
u . log . Debugf ( "Applying Terraform migrations" )
2023-08-04 07:53:51 -04:00
newIDFile , err := u . upgrader . ApplyTerraformMigrations ( cmd . Context ( ) , opts )
2023-05-22 07:31:20 -04:00
if err != nil {
return fmt . Errorf ( "applying terraform migrations: %w" , err )
}
2023-08-04 07:53:51 -04:00
if err := mergeClusterIDFile ( constants . ClusterIDsFilename , newIDFile , fileHandler ) ; err != nil {
return fmt . Errorf ( "merging cluster ID files: %w" , err )
}
2023-05-22 07:31:20 -04:00
cmd . Printf ( "Terraform migrations applied successfully and output written to: %s\n" +
2023-07-18 03:33:42 -04:00
"A backup of the pre-upgrade state has been written to: %s\n" ,
2023-08-04 07:53:51 -04:00
clusterIDsPath ( flags . workspace ) , filepath . Join ( opts . UpgradeWorkspace , u . upgrader . GetUpgradeID ( ) , constants . TerraformUpgradeBackupDir ) )
2023-05-22 07:31:20 -04:00
} else {
u . log . Debugf ( "No Terraform diff detected" )
}
return nil
}
2023-06-05 03:13:02 -04:00
// handleInvalidK8sPatchVersion checks if the Kubernetes patch version is supported and asks for confirmation if not.
func handleInvalidK8sPatchVersion ( cmd * cobra . Command , version string , yes bool ) error {
_ , err := versions . NewValidK8sVersion ( version , true )
valid := err == nil
if ! valid && ! yes {
confirmed , err := askToConfirm ( cmd , fmt . Sprintf ( "WARNING: The Kubernetes patch version %s is not supported. If you continue, Kubernetes upgrades will be skipped. Do you want to continue anyway?" , version ) )
if err != nil {
return fmt . Errorf ( "asking for confirmation: %w" , err )
}
if ! confirmed {
return fmt . Errorf ( "aborted by user" )
}
}
return nil
}
2023-05-22 07:31:20 -04:00
type imageFetcher interface {
2023-05-23 03:17:27 -04:00
FetchReference ( ctx context . Context ,
provider cloudprovider . Provider , attestationVariant variant . Variant ,
image , region string ,
) ( string , error )
2023-05-22 07:31:20 -04:00
}
2023-05-03 05:11:53 -04:00
// upgradeAttestConfigIfDiff checks if the locally configured measurements are different from the cluster's measurements.
2023-03-14 13:34:58 -04:00
// If so the function will ask the user to confirm (if --yes is not set) and upgrade the measurements only.
2023-05-03 05:11:53 -04:00
func ( u * upgradeApplyCmd ) upgradeAttestConfigIfDiff ( cmd * cobra . Command , newConfig config . AttestationCfg , flags upgradeApplyFlags ) error {
clusterAttestationConfig , _ , err := u . upgrader . GetClusterAttestationConfig ( cmd . Context ( ) , newConfig . GetVariant ( ) )
2023-07-10 08:03:45 -04:00
if err != nil {
return fmt . Errorf ( "getting cluster attestation config: %w" , err )
2023-03-14 13:34:58 -04:00
}
2023-07-10 08:03:45 -04:00
// If the current config is equal, or there is an error when comparing the configs, we skip the upgrade.
2023-07-12 05:53:00 -04:00
equal , err := newConfig . EqualTo ( clusterAttestationConfig )
if err != nil {
2023-07-10 08:03:45 -04:00
return fmt . Errorf ( "comparing attestation configs: %w" , err )
2023-03-14 13:34:58 -04:00
}
2023-07-12 05:53:00 -04:00
if equal {
return nil
}
2023-03-14 13:34:58 -04:00
if ! flags . yes {
2023-05-03 05:11:53 -04:00
ok , err := askToConfirm ( cmd , "You are about to change your cluster's attestation config. Are you sure you want to continue?" )
2023-03-14 13:34:58 -04:00
if err != nil {
return fmt . Errorf ( "asking for confirmation: %w" , err )
}
if ! ok {
2023-05-03 05:11:53 -04:00
cmd . Println ( "Skipping upgrade." )
2023-03-14 13:34:58 -04:00
return nil
}
}
2023-05-03 05:11:53 -04:00
if err := u . upgrader . UpdateAttestationConfig ( cmd . Context ( ) , newConfig ) ; err != nil {
return fmt . Errorf ( "updating attestation config: %w" , err )
2023-03-14 13:34:58 -04:00
}
2023-02-09 09:54:12 -05:00
return nil
2023-02-01 05:23:57 -05:00
}
2023-07-24 04:30:53 -04:00
func ( u * upgradeApplyCmd ) handleServiceUpgrade ( cmd * cobra . Command , conf * config . Config , idFile clusterid . File , flags upgradeApplyFlags ) error {
err := u . upgrader . UpgradeHelmServices ( cmd . Context ( ) , conf , idFile , flags . upgradeTimeout , helm . DenyDestructive , flags . force )
2023-02-01 05:23:57 -05:00
if errors . Is ( err , helm . ErrConfirmationMissing ) {
if ! flags . yes {
cmd . PrintErrln ( "WARNING: Upgrading cert-manager will destroy all custom resources you have manually created that are based on the current version of cert-manager." )
ok , askErr := askToConfirm ( cmd , "Do you want to upgrade cert-manager anyway?" )
if askErr != nil {
return fmt . Errorf ( "asking for confirmation: %w" , err )
}
if ! ok {
2023-05-03 05:11:53 -04:00
cmd . Println ( "Skipping upgrade." )
2023-02-01 05:23:57 -05:00
return nil
}
}
2023-07-24 04:30:53 -04:00
err = u . upgrader . UpgradeHelmServices ( cmd . Context ( ) , conf , idFile , flags . upgradeTimeout , helm . AllowDestructive , flags . force )
2023-02-01 05:23:57 -05:00
}
2023-03-03 03:38:23 -05:00
return err
2022-08-29 10:49:44 -04:00
}
2023-02-01 04:56:47 -05:00
func parseUpgradeApplyFlags ( cmd * cobra . Command ) ( upgradeApplyFlags , error ) {
2023-08-04 07:53:51 -04:00
workspace , err := cmd . Flags ( ) . GetString ( "workspace" )
2023-01-04 07:55:10 -05:00
if err != nil {
2023-02-01 04:56:47 -05:00
return upgradeApplyFlags { } , err
2023-01-04 07:55:10 -05:00
}
yes , err := cmd . Flags ( ) . GetBool ( "yes" )
if err != nil {
2023-02-01 04:56:47 -05:00
return upgradeApplyFlags { } , err
2023-01-04 07:55:10 -05:00
}
timeout , err := cmd . Flags ( ) . GetDuration ( "timeout" )
if err != nil {
2023-02-01 04:56:47 -05:00
return upgradeApplyFlags { } , err
2023-01-04 07:55:10 -05:00
}
2023-01-31 05:45:31 -05:00
force , err := cmd . Flags ( ) . GetBool ( "force" )
if err != nil {
2023-02-01 04:56:47 -05:00
return upgradeApplyFlags { } , fmt . Errorf ( "parsing force argument: %w" , err )
2023-01-31 05:45:31 -05:00
}
2023-05-22 07:31:20 -04:00
logLevelString , err := cmd . Flags ( ) . GetString ( "tf-log" )
if err != nil {
return upgradeApplyFlags { } , fmt . Errorf ( "parsing tf-log string: %w" , err )
}
logLevel , err := terraform . ParseLogLevel ( logLevelString )
if err != nil {
return upgradeApplyFlags { } , fmt . Errorf ( "parsing Terraform log level %s: %w" , logLevelString , err )
}
return upgradeApplyFlags {
2023-08-04 07:53:51 -04:00
workspace : workspace ,
2023-05-22 07:31:20 -04:00
yes : yes ,
upgradeTimeout : timeout ,
force : force ,
terraformLogLevel : logLevel ,
} , nil
2023-01-04 07:55:10 -05:00
}
2023-08-04 07:53:51 -04:00
func mergeClusterIDFile ( clusterIDPath string , newIDFile clusterid . File , fileHandler file . Handler ) error {
idFile := & clusterid . File { }
if err := fileHandler . ReadJSON ( clusterIDPath , idFile ) ; err != nil {
return fmt . Errorf ( "reading %s: %w" , clusterIDPath , err )
}
if err := fileHandler . WriteJSON ( clusterIDPath , idFile . Merge ( newIDFile ) , file . OptOverwrite ) ; err != nil {
return fmt . Errorf ( "writing %s: %w" , clusterIDPath , err )
}
return nil
}
2023-02-01 04:56:47 -05:00
type upgradeApplyFlags struct {
2023-08-04 07:53:51 -04:00
workspace string
2023-05-22 07:31:20 -04:00
yes bool
upgradeTimeout time . Duration
force bool
terraformLogLevel terraform . LogLevel
2023-01-04 07:55:10 -05:00
}
2022-08-29 10:49:44 -04:00
type cloudUpgrader interface {
2023-06-21 09:49:42 -04:00
UpgradeNodeVersion ( ctx context . Context , conf * config . Config , force bool ) error
2023-07-24 04:30:53 -04:00
UpgradeHelmServices ( ctx context . Context , config * config . Config , idFile clusterid . File , timeout time . Duration , allowDestructive bool , force bool ) error
2023-05-03 05:11:53 -04:00
UpdateAttestationConfig ( ctx context . Context , newConfig config . AttestationCfg ) error
2023-07-21 10:43:51 -04:00
ExtendClusterConfigCertSANs ( ctx context . Context , alternativeNames [ ] string ) error
2023-05-03 05:11:53 -04:00
GetClusterAttestationConfig ( ctx context . Context , variant variant . Variant ) ( config . AttestationCfg , * corev1 . ConfigMap , error )
2023-05-22 07:31:20 -04:00
PlanTerraformMigrations ( ctx context . Context , opts upgrade . TerraformUpgradeOptions ) ( bool , error )
2023-08-04 07:53:51 -04:00
ApplyTerraformMigrations ( ctx context . Context , opts upgrade . TerraformUpgradeOptions ) ( clusterid . File , error )
CheckTerraformMigrations ( upgradeWorkspace string ) error
CleanUpTerraformMigrations ( upgradeWorkspace string ) error
2023-06-27 07:12:50 -04:00
AddManualStateMigration ( migration terraform . StateMigration )
2023-08-04 07:53:51 -04:00
GetUpgradeID ( ) string
2022-08-29 10:49:44 -04:00
}