constellation/cli/internal/cloudcmd/iamupgrade.go
Moritz Sanft 95cf4bdf21
cli: perform upgrades in-place in Terraform workspace (#2317)
* perform upgrades in-place in terraform workspace

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update buildfiles

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* add iam upgrade apply test

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* update buildfiles

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix linter

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* make config fetcher stubbable

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* change workspace restoring behaviour

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* allow overwriting existing Terraform files

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* allow overwrites of TF variables

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix iam upgrade apply

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* fix embed directive

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* make loader test less brittle

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* pass upgrade ID to user

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* naming nit

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* use upgradeDir

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* tidy

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

---------

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>
2023-09-14 11:51:20 +02:00

85 lines
3.1 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cloudcmd
import (
"context"
"fmt"
"io"
"path/filepath"
"strings"
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
)
// UpgradeRequiresIAMMigration returns true if the given cloud provider requires an IAM migration.
func UpgradeRequiresIAMMigration(provider cloudprovider.Provider) bool {
switch provider {
default:
return false
}
}
// IAMUpgrader handles upgrades to IAM resources required by Constellation.
type IAMUpgrader struct {
tf tfIAMUpgradeClient
existingWorkspace string
upgradeWorkspace string
fileHandler file.Handler
logLevel terraform.LogLevel
}
// NewIAMUpgrader creates and initializes a new IAMUpgrader.
// existingWorkspace is the directory holding the existing Terraform resources.
// upgradeWorkspace is the directory to use for holding temporary files and resources required to apply the upgrade.
func NewIAMUpgrader(ctx context.Context, existingWorkspace, upgradeWorkspace string,
logLevel terraform.LogLevel, fileHandler file.Handler,
) (*IAMUpgrader, error) {
tfClient, err := terraform.New(ctx, constants.TerraformIAMWorkingDir)
if err != nil {
return nil, fmt.Errorf("setting up terraform client: %w", err)
}
return &IAMUpgrader{
tf: tfClient,
existingWorkspace: existingWorkspace,
upgradeWorkspace: upgradeWorkspace,
fileHandler: fileHandler,
logLevel: logLevel,
}, nil
}
// PlanIAMUpgrade prepares the upgrade workspace and plans the possible Terraform migrations for Constellation's IAM resources (service accounts, permissions etc.).
// In case of possible migrations, the diff is written to outWriter and this function returns true.
func (u *IAMUpgrader) PlanIAMUpgrade(ctx context.Context, outWriter io.Writer, vars terraform.Variables, csp cloudprovider.Provider) (bool, error) {
return planUpgrade(
ctx, u.tf, u.fileHandler, outWriter, u.logLevel, vars,
filepath.Join("terraform", "iam", strings.ToLower(csp.String())),
filepath.Join(u.upgradeWorkspace, constants.TerraformIAMUpgradeBackupDir),
)
}
// RestoreIAMWorkspace rolls back the existing workspace to the backup directory created when planning an upgrade,
// when the user decides to not apply an upgrade after planning it.
// Note that this will not apply the restored state from the backup.
func (u *IAMUpgrader) RestoreIAMWorkspace() error {
return restoreBackup(u.fileHandler, u.existingWorkspace, filepath.Join(u.upgradeWorkspace, constants.TerraformIAMUpgradeBackupDir))
}
// ApplyIAMUpgrade applies the Terraform IAM migrations planned by PlanIAMUpgrade.
// On success, the workspace of the Upgrader replaces the existing Terraform workspace.
func (u *IAMUpgrader) ApplyIAMUpgrade(ctx context.Context, csp cloudprovider.Provider) error {
if _, err := u.tf.ApplyIAM(ctx, csp, u.logLevel); err != nil {
return fmt.Errorf("terraform apply: %w", err)
}
return nil
}