mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-08-06 14:04:17 -04:00
cli: remove/refactor upgrade package (#2266)
* Move IAM migration client to cloudcmd package * Move Terraform Cluster upgrade client to cloudcmd package * Use hcl for creating Terraform IAM variables files * Unify terraform upgrade code * Rename some cloudcmd files for better clarity --------- Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
3d5d291891
commit
0a911806d1
29 changed files with 1197 additions and 1194 deletions
|
@ -83,7 +83,9 @@ go_library(
|
|||
"@com_github_hashicorp_hc_install//product",
|
||||
"@com_github_hashicorp_hc_install//releases",
|
||||
"@com_github_hashicorp_hc_install//src",
|
||||
"@com_github_hashicorp_hcl_v2//:hcl",
|
||||
"@com_github_hashicorp_hcl_v2//gohcl",
|
||||
"@com_github_hashicorp_hcl_v2//hclsyntax",
|
||||
"@com_github_hashicorp_hcl_v2//hclwrite",
|
||||
"@com_github_hashicorp_terraform_exec//tfexec",
|
||||
"@com_github_hashicorp_terraform_json//:terraform-json",
|
||||
|
|
|
@ -47,18 +47,6 @@ const (
|
|||
terraformUpgradePlanFile = "plan.zip"
|
||||
)
|
||||
|
||||
// PrepareIAMUpgradeWorkspace prepares a Terraform workspace for a Constellation IAM upgrade.
|
||||
func PrepareIAMUpgradeWorkspace(file file.Handler, path, oldWorkingDir, newWorkingDir, backupDir string) error {
|
||||
if err := prepareUpgradeWorkspace(path, file, oldWorkingDir, newWorkingDir, backupDir); err != nil {
|
||||
return fmt.Errorf("prepare upgrade workspace: %w", err)
|
||||
}
|
||||
// copy the vars file from the old working dir to the new working dir
|
||||
if err := file.CopyFile(filepath.Join(oldWorkingDir, terraformVarsFile), filepath.Join(newWorkingDir, terraformVarsFile)); err != nil {
|
||||
return fmt.Errorf("copying vars file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ErrTerraformWorkspaceExistsWithDifferentVariables is returned when existing Terraform files differ from the version the CLI wants to extract.
|
||||
var ErrTerraformWorkspaceExistsWithDifferentVariables = errors.New("creating cluster: a Terraform workspace already exists with different variables")
|
||||
|
||||
|
@ -347,10 +335,12 @@ func (c *Client) PrepareWorkspace(path string, vars Variables) error {
|
|||
return c.writeVars(vars)
|
||||
}
|
||||
|
||||
// PrepareUpgradeWorkspace prepares a Terraform workspace for a Constellation version upgrade.
|
||||
// It copies the Terraform state from the old working dir and the embedded Terraform files into the new working dir.
|
||||
func (c *Client) PrepareUpgradeWorkspace(path, oldWorkingDir, newWorkingDir, backupDir string, vars Variables) error {
|
||||
if err := prepareUpgradeWorkspace(path, c.file, oldWorkingDir, newWorkingDir, backupDir); err != nil {
|
||||
// PrepareUpgradeWorkspace prepares a Terraform workspace for an upgrade.
|
||||
// It copies the Terraform state from the old working dir and the embedded Terraform files
|
||||
// into the working dir of the Terraform client.
|
||||
// Additionally, a backup of the old working dir is created in the backup dir.
|
||||
func (c *Client) PrepareUpgradeWorkspace(path, oldWorkingDir, backupDir string, vars Variables) error {
|
||||
if err := prepareUpgradeWorkspace(path, c.file, oldWorkingDir, c.workingDir, backupDir); err != nil {
|
||||
return fmt.Errorf("prepare upgrade workspace: %w", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,10 @@ package terraform
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/gohcl"
|
||||
"github.com/hashicorp/hcl/v2/hclsyntax"
|
||||
"github.com/hashicorp/hcl/v2/hclwrite"
|
||||
)
|
||||
|
||||
|
@ -30,6 +31,19 @@ type ClusterVariables interface {
|
|||
GetCreateMAA() bool
|
||||
}
|
||||
|
||||
// VariablesFromBytes parses the given bytes into the given variables struct.
|
||||
func VariablesFromBytes[T any](b []byte, vars *T) error {
|
||||
file, err := hclsyntax.ParseConfig(b, "", hcl.Pos{Line: 1, Column: 1})
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing variables: %w", err)
|
||||
}
|
||||
|
||||
if err := gohcl.DecodeBody(file.Body, nil, vars); err != nil {
|
||||
return fmt.Errorf("decoding variables: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AWSClusterVariables is user configuration for creating a cluster with Terraform on AWS.
|
||||
type AWSClusterVariables struct {
|
||||
// Name of the cluster.
|
||||
|
@ -87,18 +101,16 @@ type AWSNodeGroup struct {
|
|||
// AWSIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure.
|
||||
type AWSIAMVariables struct {
|
||||
// Region is the AWS location to use. (e.g. us-east-2)
|
||||
Region string
|
||||
Region string `hcl:"region" cty:"region"`
|
||||
// Prefix is the name prefix of the resources to use.
|
||||
Prefix string
|
||||
Prefix string `hcl:"name_prefix" cty:"name_prefix"`
|
||||
}
|
||||
|
||||
// String returns a string representation of the IAM-specific variables, formatted as Terraform variables.
|
||||
func (v *AWSIAMVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
writeLinef(b, "name_prefix = %q", v.Prefix)
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
|
||||
return b.String()
|
||||
f := hclwrite.NewEmptyFile()
|
||||
gohcl.EncodeIntoBody(v, f.Body())
|
||||
return string(f.Bytes())
|
||||
}
|
||||
|
||||
// GCPClusterVariables is user configuration for creating resources with Terraform on GCP.
|
||||
|
@ -151,24 +163,20 @@ type GCPNodeGroup struct {
|
|||
// GCPIAMVariables is user configuration for creating the IAM confioguration with Terraform on GCP.
|
||||
type GCPIAMVariables struct {
|
||||
// Project is the ID of the GCP project to use.
|
||||
Project string
|
||||
Project string `hcl:"project_id" cty:"project_id"`
|
||||
// Region is the GCP region to use.
|
||||
Region string
|
||||
Region string `hcl:"region" cty:"region"`
|
||||
// Zone is the GCP zone to use.
|
||||
Zone string
|
||||
Zone string `hcl:"zone" cty:"zone"`
|
||||
// ServiceAccountID is the ID of the service account to use.
|
||||
ServiceAccountID string
|
||||
ServiceAccountID string `hcl:"service_account_id" cty:"service_account_id"`
|
||||
}
|
||||
|
||||
// String returns a string representation of the IAM-specific variables, formatted as Terraform variables.
|
||||
func (v *GCPIAMVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
writeLinef(b, "project_id = %q", v.Project)
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
writeLinef(b, "zone = %q", v.Zone)
|
||||
writeLinef(b, "service_account_id = %q", v.ServiceAccountID)
|
||||
|
||||
return b.String()
|
||||
f := hclwrite.NewEmptyFile()
|
||||
gohcl.EncodeIntoBody(v, f.Body())
|
||||
return string(f.Bytes())
|
||||
}
|
||||
|
||||
// AzureClusterVariables is user configuration for creating a cluster with Terraform on Azure.
|
||||
|
@ -229,21 +237,18 @@ type AzureNodeGroup struct {
|
|||
// AzureIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure.
|
||||
type AzureIAMVariables struct {
|
||||
// Region is the Azure region to use. (e.g. westus)
|
||||
Region string
|
||||
Region string `hcl:"region" cty:"region"`
|
||||
// ServicePrincipal is the name of the service principal to use.
|
||||
ServicePrincipal string
|
||||
ServicePrincipal string `hcl:"service_principal_name" cty:"service_principal_name"`
|
||||
// ResourceGroup is the name of the resource group to use.
|
||||
ResourceGroup string
|
||||
ResourceGroup string `hcl:"resource_group_name" cty:"resource_group_name"`
|
||||
}
|
||||
|
||||
// String returns a string representation of the IAM-specific variables, formatted as Terraform variables.
|
||||
func (v *AzureIAMVariables) String() string {
|
||||
b := &strings.Builder{}
|
||||
writeLinef(b, "service_principal_name = %q", v.ServicePrincipal)
|
||||
writeLinef(b, "region = %q", v.Region)
|
||||
writeLinef(b, "resource_group_name = %q", v.ResourceGroup)
|
||||
|
||||
return b.String()
|
||||
f := hclwrite.NewEmptyFile()
|
||||
gohcl.EncodeIntoBody(v, f.Body())
|
||||
return string(f.Bytes())
|
||||
}
|
||||
|
||||
// OpenStackClusterVariables is user configuration for creating a cluster with Terraform on OpenStack.
|
||||
|
@ -380,11 +385,6 @@ type QEMUNodeGroup struct {
|
|||
MemorySize int `hcl:"memory" cty:"memory"`
|
||||
}
|
||||
|
||||
func writeLinef(builder *strings.Builder, format string, a ...any) {
|
||||
builder.WriteString(fmt.Sprintf(format, a...))
|
||||
builder.WriteByte('\n')
|
||||
}
|
||||
|
||||
func toPtr[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
|
|
@ -86,8 +86,8 @@ func TestAWSIAMVariables(t *testing.T) {
|
|||
}
|
||||
|
||||
// test that the variables are correctly rendered
|
||||
want := `name_prefix = "my-prefix"
|
||||
region = "eu-central-1"
|
||||
want := `region = "eu-central-1"
|
||||
name_prefix = "my-prefix"
|
||||
`
|
||||
got := vars.String()
|
||||
assert.Equal(t, want, got)
|
||||
|
@ -162,9 +162,9 @@ func TestGCPIAMVariables(t *testing.T) {
|
|||
}
|
||||
|
||||
// test that the variables are correctly rendered
|
||||
want := `project_id = "my-project"
|
||||
region = "eu-central-1"
|
||||
zone = "eu-central-1a"
|
||||
want := `project_id = "my-project"
|
||||
region = "eu-central-1"
|
||||
zone = "eu-central-1a"
|
||||
service_account_id = "my-service-account"
|
||||
`
|
||||
got := vars.String()
|
||||
|
@ -226,9 +226,9 @@ func TestAzureIAMVariables(t *testing.T) {
|
|||
}
|
||||
|
||||
// test that the variables are correctly rendered
|
||||
want := `service_principal_name = "my-service-principal"
|
||||
region = "eu-central-1"
|
||||
resource_group_name = "my-resource-group"
|
||||
want := `region = "eu-central-1"
|
||||
service_principal_name = "my-service-principal"
|
||||
resource_group_name = "my-resource-group"
|
||||
`
|
||||
got := vars.String()
|
||||
assert.Equal(t, want, got)
|
||||
|
@ -337,3 +337,34 @@ custom_endpoint = "example.com"
|
|||
got := vars.String()
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestVariablesFromBytes(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
awsVars := AWSIAMVariables{
|
||||
Region: "test",
|
||||
}
|
||||
var loadedAWSVars AWSIAMVariables
|
||||
err := VariablesFromBytes([]byte(awsVars.String()), &loadedAWSVars)
|
||||
assert.NoError(err)
|
||||
assert.Equal(awsVars, loadedAWSVars)
|
||||
|
||||
azureVars := AzureIAMVariables{
|
||||
Region: "test",
|
||||
}
|
||||
var loadedAzureVars AzureIAMVariables
|
||||
err = VariablesFromBytes([]byte(azureVars.String()), &loadedAzureVars)
|
||||
assert.NoError(err)
|
||||
assert.Equal(azureVars, loadedAzureVars)
|
||||
|
||||
gcpVars := GCPIAMVariables{
|
||||
Region: "test",
|
||||
}
|
||||
var loadedGCPVars GCPIAMVariables
|
||||
err = VariablesFromBytes([]byte(gcpVars.String()), &loadedGCPVars)
|
||||
assert.NoError(err)
|
||||
assert.Equal(gcpVars, loadedGCPVars)
|
||||
|
||||
err = VariablesFromBytes([]byte("invalid"), &loadedGCPVars)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue