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"
"time"
2022-08-29 10:49:44 -04:00
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
2023-01-04 07:55:10 -05:00
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
2023-01-03 03:58:35 -05:00
"github.com/edgelesssys/constellation/v2/cli/internal/image"
2022-11-15 09:40:49 -05:00
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
2022-09-21 07:47:57 -04:00
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/file"
2022-08-29 10:49:44 -04:00
"github.com/spf13/afero"
"github.com/spf13/cobra"
)
func newUpgradeExecuteCmd ( ) * cobra . Command {
cmd := & cobra . Command {
Use : "execute" ,
Short : "Execute an upgrade of a Constellation cluster" ,
Long : "Execute an upgrade of a Constellation cluster by applying the chosen configuration." ,
Args : cobra . NoArgs ,
RunE : runUpgradeExecute ,
}
2023-01-17 08:01:56 -05:00
cmd . Flags ( ) . Bool ( "helm" , false , "execute helm upgrade\n" +
"This feature is still in development an may change without announcement. Upgrades all helm charts deployed during constellation-init." )
cmd . Flags ( ) . BoolP ( "yes" , "y" , false , "run upgrades without further confirmation\n" +
"WARNING: might delete your resources in case you are using cert-manager in your cluster. Please read the docs." )
cmd . Flags ( ) . Duration ( "timeout" , 3 * time . Minute , "change helm upgrade timeout\n" +
"This feature is still in development an may change without announcement. Might be useful for slow connections or big clusters." )
2022-12-19 10:52:15 -05:00
if err := cmd . Flags ( ) . MarkHidden ( "helm" ) ; err != nil {
panic ( err )
}
if err := cmd . Flags ( ) . MarkHidden ( "timeout" ) ; err != nil {
panic ( err )
}
2022-08-29 10:49:44 -04:00
return cmd
}
func runUpgradeExecute ( cmd * cobra . Command , args [ ] 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 ( ) )
2022-11-29 05:39:07 -05:00
imageFetcher := image . New ( )
2022-12-19 10:52:15 -05:00
upgrader , err := cloudcmd . NewUpgrader ( cmd . OutOrStdout ( ) , log )
2022-08-29 10:49:44 -04:00
if err != nil {
return err
}
2022-11-29 05:39:07 -05:00
return upgradeExecute ( cmd , imageFetcher , upgrader , fileHandler )
2022-08-29 10:49:44 -04:00
}
2022-11-29 05:39:07 -05:00
func upgradeExecute ( cmd * cobra . Command , imageFetcher imageFetcher , upgrader cloudUpgrader , fileHandler file . Handler ) error {
2023-01-04 07:55:10 -05:00
flags , err := parseUpgradeExecuteFlags ( 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-01-04 07:55:10 -05:00
conf , err := config . New ( fileHandler , flags . configPath )
2022-08-29 10:49:44 -04:00
if err != nil {
2022-11-15 09:40:49 -05:00
return displayConfigValidationErrors ( cmd . ErrOrStderr ( ) , err )
2022-08-29 10:49:44 -04:00
}
2023-01-04 07:55:10 -05:00
if flags . helmFlag {
err = upgrader . UpgradeHelmServices ( cmd . Context ( ) , conf , flags . upgradeTimeout , helm . DenyDestructive )
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 {
cmd . Println ( "Aborting upgrade." )
return nil
}
}
err = upgrader . UpgradeHelmServices ( cmd . Context ( ) , conf , flags . upgradeTimeout , helm . AllowDestructive )
2022-12-19 10:52:15 -05:00
}
2023-01-04 07:55:10 -05:00
if err != nil {
2022-12-19 10:52:15 -05:00
return fmt . Errorf ( "upgrading helm: %w" , err )
}
2023-01-04 07:55:10 -05:00
2022-12-19 10:52:15 -05:00
return nil
}
2022-08-29 10:49:44 -04:00
// TODO: validate upgrade config? Should be basic things like checking image is not an empty string
// More sophisticated validation, like making sure we don't downgrade the cluster, should be done by `constellation upgrade plan`
2022-11-29 05:39:07 -05:00
// this config modification is temporary until we can remove the upgrade section from the config
conf . Image = conf . Upgrade . Image
imageReference , err := imageFetcher . FetchReference ( cmd . Context ( ) , conf )
if err != nil {
return err
}
return upgrader . Upgrade ( cmd . Context ( ) , imageReference , conf . Upgrade . Image , conf . Upgrade . Measurements )
2022-08-29 10:49:44 -04:00
}
2023-01-04 07:55:10 -05:00
func parseUpgradeExecuteFlags ( cmd * cobra . Command ) ( upgradeExecuteFlags , error ) {
configPath , err := cmd . Flags ( ) . GetString ( "config" )
if err != nil {
return upgradeExecuteFlags { } , err
}
helmFlag , err := cmd . Flags ( ) . GetBool ( "helm" )
if err != nil {
return upgradeExecuteFlags { } , err
}
yes , err := cmd . Flags ( ) . GetBool ( "yes" )
if err != nil {
return upgradeExecuteFlags { } , err
}
timeout , err := cmd . Flags ( ) . GetDuration ( "timeout" )
if err != nil {
return upgradeExecuteFlags { } , err
}
return upgradeExecuteFlags { configPath : configPath , helmFlag : helmFlag , yes : yes , upgradeTimeout : timeout } , nil
}
type upgradeExecuteFlags struct {
configPath string
helmFlag bool
yes bool
upgradeTimeout time . Duration
}
2022-08-29 10:49:44 -04:00
type cloudUpgrader interface {
2022-11-29 05:39:07 -05:00
Upgrade ( ctx context . Context , imageReference , imageVersion string , measurements measurements . M ) error
2023-01-04 07:55:10 -05:00
UpgradeHelmServices ( ctx context . Context , config * config . Config , timeout time . Duration , allowDestructive bool ) error
2022-11-29 05:39:07 -05:00
}
type imageFetcher interface {
FetchReference ( ctx context . Context , config * config . Config ) ( string , error )
2022-08-29 10:49:44 -04:00
}