2023-10-24 09:39:18 -04:00
/ *
Copyright ( c ) Edgeless Systems GmbH
SPDX - License - Identifier : AGPL - 3.0 - only
* /
package cmd
import (
"context"
"errors"
"fmt"
"path/filepath"
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/internal/compatibility"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants"
2023-12-06 04:01:39 -05:00
"github.com/edgelesssys/constellation/v2/internal/constellation/helm"
2023-12-08 10:27:04 -05:00
"github.com/edgelesssys/constellation/v2/internal/constellation/state"
2023-10-24 09:39:18 -04:00
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
"github.com/spf13/cobra"
)
// runHelmApply handles installing or upgrading helm charts for the cluster.
2023-12-05 10:23:31 -05:00
func ( a * applyCmd ) runHelmApply ( cmd * cobra . Command , conf * config . Config , stateFile * state . State , upgradeDir string ,
2023-10-24 09:39:18 -04:00
) error {
2024-02-08 09:20:01 -05:00
a . log . Debug ( "Installing or upgrading Helm charts" )
2023-10-24 09:39:18 -04:00
var masterSecret uri . MasterSecret
if err := a . fileHandler . ReadJSON ( constants . MasterSecretFilename , & masterSecret ) ; err != nil {
return fmt . Errorf ( "reading master secret: %w" , err )
}
options := helm . Options {
2023-12-06 04:01:39 -05:00
CSP : conf . GetProvider ( ) ,
AttestationVariant : conf . GetAttestationConfig ( ) . GetVariant ( ) ,
K8sVersion : conf . KubernetesVersion ,
MicroserviceVersion : conf . MicroserviceVersion ,
DeployCSIDriver : conf . DeployCSIDriver ( ) ,
Force : a . flags . force ,
Conformance : a . flags . conformance ,
HelmWaitMode : a . flags . helmWaitMode ,
ApplyTimeout : a . flags . helmTimeout ,
AllowDestructive : helm . DenyDestructive ,
2024-07-03 13:38:55 -04:00
ServiceCIDR : conf . ServiceCIDR ,
2023-10-24 09:39:18 -04:00
}
2024-03-06 14:48:40 -05:00
if conf . Provider . OpenStack != nil {
var deployYawolLoadBalancer bool
if conf . Provider . OpenStack . DeployYawolLoadBalancer != nil {
deployYawolLoadBalancer = * conf . Provider . OpenStack . DeployYawolLoadBalancer
}
options . OpenStackValues = & helm . OpenStackValues {
DeployYawolLoadBalancer : deployYawolLoadBalancer ,
FloatingIPPoolID : conf . Provider . OpenStack . FloatingIPPoolID ,
YawolFlavorID : conf . Provider . OpenStack . YawolFlavorID ,
YawolImageID : conf . Provider . OpenStack . YawolImageID ,
}
}
2023-10-24 09:39:18 -04:00
2024-02-08 09:20:01 -05:00
a . log . Debug ( "Getting service account URI" )
2023-10-24 09:39:18 -04:00
serviceAccURI , err := cloudcmd . GetMarshaledServiceAccountURI ( conf , a . fileHandler )
if err != nil {
return err
}
2024-02-08 09:20:01 -05:00
a . log . Debug ( "Preparing Helm charts" )
2024-03-06 14:48:40 -05:00
executor , includesUpgrades , err := a . applier . PrepareHelmCharts ( options , stateFile , serviceAccURI , masterSecret )
2023-10-24 09:39:18 -04:00
if errors . Is ( err , helm . ErrConfirmationMissing ) {
if ! a . 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 ( "Skipping upgrade." )
return nil
}
}
options . AllowDestructive = helm . AllowDestructive
2024-03-06 14:48:40 -05:00
executor , includesUpgrades , err = a . applier . PrepareHelmCharts ( options , stateFile , serviceAccURI , masterSecret )
2023-10-24 09:39:18 -04:00
}
var upgradeErr * compatibility . InvalidUpgradeError
if err != nil {
if ! errors . As ( err , & upgradeErr ) {
return fmt . Errorf ( "preparing Helm charts: %w" , err )
}
cmd . PrintErrln ( err )
}
2024-02-08 09:20:01 -05:00
a . log . Debug ( "Backing up Helm charts" )
2023-12-05 10:23:31 -05:00
if err := a . backupHelmCharts ( cmd . Context ( ) , executor , includesUpgrades , upgradeDir ) ; err != nil {
2023-10-24 09:39:18 -04:00
return err
}
2024-02-08 09:20:01 -05:00
a . log . Debug ( "Applying Helm charts" )
2023-10-24 09:39:18 -04:00
if ! a . flags . skipPhases . contains ( skipInitPhase ) {
a . spinner . Start ( "Installing Kubernetes components " , false )
} else {
a . spinner . Start ( "Upgrading Kubernetes components " , false )
}
if err := executor . Apply ( cmd . Context ( ) ) ; err != nil {
return fmt . Errorf ( "applying Helm charts: %w" , err )
}
a . spinner . Stop ( )
if a . flags . skipPhases . contains ( skipInitPhase ) {
cmd . Println ( "Successfully upgraded Constellation services." )
}
return nil
}
// backupHelmCharts saves the Helm charts for the upgrade to disk and creates a backup of existing CRDs and CRs.
func ( a * applyCmd ) backupHelmCharts (
2023-12-05 10:23:31 -05:00
ctx context . Context , executor helm . Applier , includesUpgrades bool , upgradeDir string ,
2023-10-24 09:39:18 -04:00
) error {
// Save the Helm charts for the upgrade to disk
chartDir := filepath . Join ( upgradeDir , "helm-charts" )
if err := executor . SaveCharts ( chartDir , a . fileHandler ) ; err != nil {
return fmt . Errorf ( "saving Helm charts to disk: %w" , err )
}
2024-04-03 09:49:03 -04:00
a . log . Debug ( fmt . Sprintf ( "Helm charts saved to %q" , a . flags . pathPrefixer . PrefixPrintablePath ( chartDir ) ) )
2023-10-24 09:39:18 -04:00
if includesUpgrades {
2024-02-08 09:20:01 -05:00
a . log . Debug ( "Creating backup of CRDs and CRs" )
2023-12-05 10:23:31 -05:00
crds , err := a . applier . BackupCRDs ( ctx , a . fileHandler , upgradeDir )
2023-10-24 09:39:18 -04:00
if err != nil {
return fmt . Errorf ( "creating CRD backup: %w" , err )
}
2023-12-05 10:23:31 -05:00
if err := a . applier . BackupCRs ( ctx , a . fileHandler , crds , upgradeDir ) ; err != nil {
2023-10-24 09:39:18 -04:00
return fmt . Errorf ( "creating CR backup: %w" , err )
}
}
return nil
}