cli: unify terraform variable creation (#2119)

Before we defined the variables twice.
Once for upgrades, once for create.
Also move default node group names into a constant
This commit is contained in:
Otto Bittner 2023-07-21 10:04:29 +02:00 committed by GitHub
parent f9391ed903
commit cf822f7eee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 464 additions and 451 deletions

View file

@ -19,6 +19,17 @@ type Variables interface {
fmt.Stringer
}
// ClusterVariables should be used in places where a cluster is created.
type ClusterVariables interface {
Variables
// TODO (derpsteb): Rename this function once we have introduced an interface for config.Config.
// GetCreateMAA does not follow Go's naming convention because we need to keep the CreateMAA property public for now.
// There are functions creating Variables objects outside of this package.
// These functions can only be moved into this package once we have introduced an interface for config.Config,
// since we do not want to introduce a dependency on config.Config in this package.
GetCreateMAA() bool
}
// CommonVariables is user configuration for creating a cluster with Terraform.
type CommonVariables struct {
// Name of the cluster.
@ -64,6 +75,19 @@ type AWSClusterVariables struct {
NodeGroups map[string]AWSNodeGroup `hcl:"node_groups" cty:"node_groups"`
}
// GetCreateMAA gets the CreateMAA variable.
// TODO (derpsteb): Rename this function once we have introduced an interface for config.Config.
func (a *AWSClusterVariables) GetCreateMAA() bool {
return false
}
// String returns a string representation of the variables, formatted as Terraform variables.
func (a *AWSClusterVariables) String() string {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(a, f.Body())
return string(f.Bytes())
}
// AWSNodeGroup is a node group to create on AWS.
type AWSNodeGroup struct {
// Role is the role of the node group.
@ -71,7 +95,8 @@ type AWSNodeGroup struct {
// StateDiskSizeGB is the size of the state disk to allocate to each node, in GB.
StateDiskSizeGB int `hcl:"disk_size" cty:"disk_size"`
// InitialCount is the initial number of nodes to create in the node group.
InitialCount int `hcl:"initial_count" cty:"initial_count"`
// During upgrades this value is not set.
InitialCount *int `hcl:"initial_count" cty:"initial_count"`
// Zone is the AWS availability-zone to use in the given region.
Zone string `hcl:"zone" cty:"zone"`
// InstanceType is the type of the EC2 instance to use.
@ -80,12 +105,6 @@ type AWSNodeGroup struct {
DiskType string `hcl:"disk_type" cty:"disk_type"`
}
func (v *AWSClusterVariables) String() string {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(v, f.Body())
return string(f.Bytes())
}
// 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)
@ -121,6 +140,19 @@ type GCPClusterVariables struct {
NodeGroups map[string]GCPNodeGroup `hcl:"node_groups" cty:"node_groups"`
}
// GetCreateMAA gets the CreateMAA variable.
// TODO (derpsteb): Rename this function once we have introduced an interface for config.Config.
func (g *GCPClusterVariables) GetCreateMAA() bool {
return false
}
// String returns a string representation of the variables, formatted as Terraform variables.
func (g *GCPClusterVariables) String() string {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(g, f.Body())
return string(f.Bytes())
}
// GCPNodeGroup is a node group to create on GCP.
type GCPNodeGroup struct {
// Role is the role of the node group.
@ -128,19 +160,13 @@ type GCPNodeGroup struct {
// StateDiskSizeGB is the size of the state disk to allocate to each node, in GB.
StateDiskSizeGB int `hcl:"disk_size" cty:"disk_size"`
// InitialCount is the initial number of nodes to create in the node group.
InitialCount int `hcl:"initial_count" cty:"initial_count"`
// During upgrades this value is not set.
InitialCount *int `hcl:"initial_count" cty:"initial_count"`
Zone string `hcl:"zone" cty:"zone"`
InstanceType string `hcl:"instance_type" cty:"instance_type"`
DiskType string `hcl:"disk_type" cty:"disk_type"`
}
// String returns a string representation of the variables, formatted as Terraform variables.
func (v *GCPClusterVariables) String() string {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(v, f.Body())
return string(f.Bytes())
}
// 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.
@ -188,10 +214,20 @@ type AzureClusterVariables struct {
NodeGroups map[string]AzureNodeGroup `hcl:"node_groups" cty:"node_groups"`
}
// GetCreateMAA gets the CreateMAA variable.
// TODO (derpsteb): Rename this function once we have introduced an interface for config.Config.
func (a *AzureClusterVariables) GetCreateMAA() bool {
if a.CreateMAA == nil {
return false
}
return *a.CreateMAA
}
// String returns a string representation of the variables, formatted as Terraform variables.
func (v *AzureClusterVariables) String() string {
func (a *AzureClusterVariables) String() string {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(v, f.Body())
gohcl.EncodeIntoBody(a, f.Body())
return string(f.Bytes())
}
@ -253,12 +289,26 @@ type OpenStackClusterVariables struct {
Debug bool `hcl:"debug" cty:"debug"`
}
// GetCreateMAA gets the CreateMAA variable.
// TODO (derpsteb): Rename this function once we have introduced an interface for config.Config.
func (o *OpenStackClusterVariables) GetCreateMAA() bool {
return false
}
// String returns a string representation of the variables, formatted as Terraform variables.
func (o *OpenStackClusterVariables) String() string {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(o, f.Body())
return string(f.Bytes())
}
// OpenStackNodeGroup is a node group to create on OpenStack.
type OpenStackNodeGroup struct {
// Role is the role of the node group.
Role string `hcl:"role" cty:"role"`
// InitialCount is the number of instances to create.
InitialCount int `hcl:"initial_count" cty:"initial_count"`
// InitialCount is optional for upgrades. OpenStack does not support upgrades yet but might in the future.
InitialCount *int `hcl:"initial_count" cty:"initial_count"`
// Zone is the OpenStack availability zone to use.
Zone string `hcl:"zone" cty:"zone"`
// StateDiskType is the OpenStack disk type to use for the state disk.
@ -267,13 +317,6 @@ type OpenStackNodeGroup struct {
StateDiskSizeGB int `hcl:"state_disk_size" cty:"state_disk_size"`
}
// String returns a string representation of the variables, formatted as Terraform variables.
func (v *OpenStackClusterVariables) String() string {
f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(v, f.Body())
return string(f.Bytes())
}
// TODO(malt3): Add support for OpenStack IAM variables.
// QEMUVariables is user configuration for creating a QEMU cluster with Terraform.
@ -313,10 +356,16 @@ type QEMUVariables struct {
KernelCmdline *string `hcl:"constellation_cmdline" cty:"constellation_cmdline"`
}
// GetCreateMAA gets the CreateMAA variable.
// TODO (derpsteb): Rename this function once we have introduced an interface for config.Config.
func (q *QEMUVariables) GetCreateMAA() bool {
return false
}
// String returns a string representation of the variables, formatted as Terraform variables.
func (v *QEMUVariables) String() string {
func (q *QEMUVariables) String() string {
// copy v object
vCopy := *v
vCopy := *q
switch vCopy.NVRAM {
case "production":
vCopy.NVRAM = "/usr/share/OVMF/constellation_vars.production.fd"
@ -333,7 +382,9 @@ type QEMUNodeGroup struct {
// Role is the role of the node group.
Role string `hcl:"role" cty:"role"`
// InitialCount is the number of instances to create.
InitialCount int `hcl:"initial_count" cty:"initial_count"`
// InitialCount is optional for upgrades.
// Upgrades are not implemented for QEMU. The type is similar to other NodeGroup types for consistency.
InitialCount *int `hcl:"initial_count" cty:"initial_count"`
// DiskSize is the size of the disk to allocate to each node, in GiB.
DiskSize int `hcl:"disk_size" cty:"disk_size"`
// CPUCount is the number of CPUs to allocate to each node.
@ -346,3 +397,7 @@ 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
}

View file

@ -10,6 +10,7 @@ import (
"testing"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/role"
"github.com/stretchr/testify/assert"
)
@ -18,18 +19,18 @@ func TestAWSClusterVariables(t *testing.T) {
vars := AWSClusterVariables{
Name: "cluster-name",
NodeGroups: map[string]AWSNodeGroup{
"control_plane_default": {
constants.ControlPlaneDefault: {
Role: role.ControlPlane.TFString(),
StateDiskSizeGB: 30,
InitialCount: 1,
InitialCount: toPtr(1),
Zone: "eu-central-1b",
InstanceType: "x1.foo",
DiskType: "foodisk",
},
"worker_default": {
constants.WorkerDefault: {
Role: role.Worker.TFString(),
StateDiskSizeGB: 30,
InitialCount: 2,
InitialCount: toPtr(2),
Zone: "eu-central-1c",
InstanceType: "x1.bar",
DiskType: "bardisk",
@ -99,18 +100,18 @@ func TestGCPClusterVariables(t *testing.T) {
ImageID: "image-0123456789abcdef",
Debug: true,
NodeGroups: map[string]GCPNodeGroup{
"control_plane_default": {
constants.ControlPlaneDefault: {
Role: "control-plane",
StateDiskSizeGB: 30,
InitialCount: 1,
InitialCount: toPtr(1),
Zone: "eu-central-1a",
InstanceType: "n2d-standard-4",
DiskType: "pd-ssd",
},
"worker_default": {
constants.WorkerDefault: {
Role: "worker",
StateDiskSizeGB: 10,
InitialCount: 1,
InitialCount: toPtr(1),
Zone: "eu-central-1b",
InstanceType: "n2d-standard-8",
DiskType: "pd-ssd",
@ -170,7 +171,7 @@ func TestAzureClusterVariables(t *testing.T) {
vars := AzureClusterVariables{
Name: "cluster-name",
NodeGroups: map[string]AzureNodeGroup{
"control_plane_default": {
constants.ControlPlaneDefault: {
Role: "ControlPlane",
InitialCount: to.Ptr(1),
InstanceType: "Standard_D2s_v3",
@ -240,9 +241,9 @@ func TestOpenStackClusterVariables(t *testing.T) {
OpenstackPassword: "my-password",
Debug: true,
NodeGroups: map[string]OpenStackNodeGroup{
"control_plane_default": {
constants.ControlPlaneDefault: {
Role: "control-plane",
InitialCount: 1,
InitialCount: toPtr(1),
Zone: "az-01",
StateDiskType: "performance-8",
StateDiskSizeGB: 30,
@ -281,7 +282,7 @@ func TestQEMUClusterVariables(t *testing.T) {
NodeGroups: map[string]QEMUNodeGroup{
"control-plane": {
Role: role.ControlPlane.TFString(),
InitialCount: 1,
InitialCount: toPtr(1),
DiskSize: 30,
CPUCount: 4,
MemorySize: 8192,
@ -326,7 +327,3 @@ constellation_cmdline = "console=ttyS0,115200n8"
got := vars.String()
assert.Equal(t, want, got)
}
func toPtr[T any](v T) *T {
return &v
}