mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-25 07:29:38 -05:00
terraform: azure node groups (#1955)
* init * migration working * make tf variables with default value optional in go through ptr type * fix CI build * pr feedback * add azure targets tf * skip migration for empty targets * make instance_count optional * change role naming to dashed + add validation * make node_group.zones optional * Update cli/internal/terraform/terraform/azure/main.tf Co-authored-by: Malte Poll <1780588+malt3@users.noreply.github.com> * malte feedback --------- Co-authored-by: Malte Poll <1780588+malt3@users.noreply.github.com>
This commit is contained in:
parent
224c74f883
commit
487fa1e397
@ -29,6 +29,7 @@ go_library(
|
|||||||
"//internal/config",
|
"//internal/config",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/imagefetcher",
|
"//internal/imagefetcher",
|
||||||
|
"//internal/role",
|
||||||
"@com_github_azure_azure_sdk_for_go//profiles/latest/attestation/attestation",
|
"@com_github_azure_azure_sdk_for_go//profiles/latest/attestation/attestation",
|
||||||
"@com_github_azure_azure_sdk_for_go_sdk_azcore//policy",
|
"@com_github_azure_azure_sdk_for_go_sdk_azcore//policy",
|
||||||
"@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity",
|
"@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity",
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/imagefetcher"
|
"github.com/edgelesssys/constellation/v2/internal/imagefetcher"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Creator creates cloud resources.
|
// Creator creates cloud resources.
|
||||||
@ -214,25 +215,35 @@ func (c *Creator) createGCP(ctx context.Context, cl terraformClient, opts Create
|
|||||||
|
|
||||||
func (c *Creator) createAzure(ctx context.Context, cl terraformClient, opts CreateOptions) (idFile clusterid.File, retErr error) {
|
func (c *Creator) createAzure(ctx context.Context, cl terraformClient, opts CreateOptions) (idFile clusterid.File, retErr error) {
|
||||||
vars := terraform.AzureClusterVariables{
|
vars := terraform.AzureClusterVariables{
|
||||||
CommonVariables: terraform.CommonVariables{
|
Name: opts.Config.Name,
|
||||||
Name: opts.Config.Name,
|
NodeGroups: map[string]terraform.AzureNodeGroup{
|
||||||
CountControlPlanes: opts.ControlPlaneCount,
|
"control_plane_default": {
|
||||||
CountWorkers: opts.WorkerCount,
|
Role: role.ControlPlane.TFString(),
|
||||||
StateDiskSizeGB: opts.Config.StateDiskSizeGB,
|
InstanceCount: toPtr(opts.ControlPlaneCount),
|
||||||
|
InstanceType: opts.InsType,
|
||||||
|
DiskSizeGB: opts.Config.StateDiskSizeGB,
|
||||||
|
DiskType: opts.Config.Provider.Azure.StateDiskType,
|
||||||
|
Zones: nil, // TODO(elchead): support zones AB#3225
|
||||||
|
},
|
||||||
|
"worker_default": {
|
||||||
|
Role: role.Worker.TFString(),
|
||||||
|
InstanceCount: toPtr(opts.WorkerCount),
|
||||||
|
InstanceType: opts.InsType,
|
||||||
|
DiskSizeGB: opts.Config.StateDiskSizeGB,
|
||||||
|
DiskType: opts.Config.Provider.Azure.StateDiskType,
|
||||||
|
Zones: nil,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Location: opts.Config.Provider.Azure.Location,
|
Location: opts.Config.Provider.Azure.Location,
|
||||||
ResourceGroup: opts.Config.Provider.Azure.ResourceGroup,
|
|
||||||
UserAssignedIdentity: opts.Config.Provider.Azure.UserAssignedIdentity,
|
|
||||||
InstanceType: opts.InsType,
|
|
||||||
StateDiskType: opts.Config.Provider.Azure.StateDiskType,
|
|
||||||
ImageID: opts.image,
|
ImageID: opts.image,
|
||||||
SecureBoot: *opts.Config.Provider.Azure.SecureBoot,
|
CreateMAA: toPtr(opts.Config.GetAttestationConfig().GetVariant().Equal(variant.AzureSEVSNP{})),
|
||||||
CreateMAA: opts.Config.GetAttestationConfig().GetVariant().Equal(variant.AzureSEVSNP{}),
|
Debug: toPtr(opts.Config.IsDebugCluster()),
|
||||||
Debug: opts.Config.IsDebugCluster(),
|
ConfidentialVM: toPtr(opts.Config.GetAttestationConfig().GetVariant().Equal(variant.AzureSEVSNP{})),
|
||||||
|
SecureBoot: opts.Config.Provider.Azure.SecureBoot,
|
||||||
|
UserAssignedIdentity: opts.Config.Provider.Azure.UserAssignedIdentity,
|
||||||
|
ResourceGroup: opts.Config.Provider.Azure.ResourceGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
vars.ConfidentialVM = opts.Config.GetAttestationConfig().GetVariant().Equal(variant.AzureSEVSNP{})
|
|
||||||
|
|
||||||
vars = normalizeAzureURIs(vars)
|
vars = normalizeAzureURIs(vars)
|
||||||
|
|
||||||
if err := cl.PrepareWorkspace(path.Join("terraform", strings.ToLower(cloudprovider.Azure.String())), &vars); err != nil {
|
if err := cl.PrepareWorkspace(path.Join("terraform", strings.ToLower(cloudprovider.Azure.String())), &vars); err != nil {
|
||||||
@ -245,7 +256,7 @@ func (c *Creator) createAzure(ctx context.Context, cl terraformClient, opts Crea
|
|||||||
return clusterid.File{}, err
|
return clusterid.File{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if vars.CreateMAA {
|
if vars.CreateMAA != nil && *vars.CreateMAA {
|
||||||
// Patch the attestation policy to allow the cluster to boot while having secure boot disabled.
|
// Patch the attestation policy to allow the cluster to boot while having secure boot disabled.
|
||||||
if err := c.policyPatcher.Patch(ctx, tfOutput.AttestationURL); err != nil {
|
if err := c.policyPatcher.Patch(ctx, tfOutput.AttestationURL); err != nil {
|
||||||
return clusterid.File{}, err
|
return clusterid.File{}, err
|
||||||
@ -442,3 +453,7 @@ func (c *Creator) createQEMU(ctx context.Context, cl terraformClient, lv libvirt
|
|||||||
UID: tfOutput.UID,
|
UID: tfOutput.UID,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toPtr[T any](v T) *T {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
@ -156,6 +156,10 @@ func (u *upgradeApplyCmd) migrateTerraform(cmd *cobra.Command, file file.Handler
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing upgrade variables: %w", err)
|
return fmt.Errorf("parsing upgrade variables: %w", err)
|
||||||
}
|
}
|
||||||
|
if len(targets) == 0 {
|
||||||
|
u.log.Debugf("No targets specified. Skipping Terraform migration")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
u.log.Debugf("Using migration targets:\n%v", targets)
|
u.log.Debugf("Using migration targets:\n%v", targets)
|
||||||
u.log.Debugf("Using Terraform variables:\n%v", vars)
|
u.log.Debugf("Using Terraform variables:\n%v", vars)
|
||||||
|
|
||||||
@ -240,7 +244,7 @@ func parseTerraformUpgradeVars(cmd *cobra.Command, conf *config.Config, fetcher
|
|||||||
}
|
}
|
||||||
return targets, vars, nil
|
return targets, vars, nil
|
||||||
case cloudprovider.Azure:
|
case cloudprovider.Azure:
|
||||||
targets := []string{"azurerm_attestation_provider.attestation_provider"}
|
targets := []string{"azurerm_attestation_provider.attestation_provider", "module.scale_set_group", "module.scale_set_control_plane", "module.scale_set_worker"}
|
||||||
|
|
||||||
// Azure Terraform provider is very strict about it's casing
|
// Azure Terraform provider is very strict about it's casing
|
||||||
imageRef = strings.Replace(imageRef, "CommunityGalleries", "communityGalleries", 1)
|
imageRef = strings.Replace(imageRef, "CommunityGalleries", "communityGalleries", 1)
|
||||||
@ -248,16 +252,28 @@ func parseTerraformUpgradeVars(cmd *cobra.Command, conf *config.Config, fetcher
|
|||||||
imageRef = strings.Replace(imageRef, "Versions", "versions", 1)
|
imageRef = strings.Replace(imageRef, "Versions", "versions", 1)
|
||||||
|
|
||||||
vars := &terraform.AzureClusterVariables{
|
vars := &terraform.AzureClusterVariables{
|
||||||
CommonVariables: commonVariables,
|
Name: conf.Name,
|
||||||
Location: conf.Provider.Azure.Location,
|
|
||||||
ResourceGroup: conf.Provider.Azure.ResourceGroup,
|
ResourceGroup: conf.Provider.Azure.ResourceGroup,
|
||||||
UserAssignedIdentity: conf.Provider.Azure.UserAssignedIdentity,
|
UserAssignedIdentity: conf.Provider.Azure.UserAssignedIdentity,
|
||||||
InstanceType: conf.Provider.Azure.InstanceType,
|
|
||||||
StateDiskType: conf.Provider.Azure.StateDiskType,
|
|
||||||
ImageID: imageRef,
|
ImageID: imageRef,
|
||||||
SecureBoot: *conf.Provider.Azure.SecureBoot,
|
NodeGroups: map[string]terraform.AzureNodeGroup{
|
||||||
CreateMAA: conf.GetAttestationConfig().GetVariant().Equal(variant.AzureSEVSNP{}),
|
"control_plane_default": {
|
||||||
Debug: conf.IsDebugCluster(),
|
Role: "control-plane",
|
||||||
|
InstanceType: conf.Provider.Azure.InstanceType,
|
||||||
|
DiskSizeGB: conf.StateDiskSizeGB,
|
||||||
|
DiskType: conf.Provider.Azure.StateDiskType,
|
||||||
|
},
|
||||||
|
"worker_default": {
|
||||||
|
Role: "worker",
|
||||||
|
InstanceType: conf.Provider.Azure.InstanceType,
|
||||||
|
DiskSizeGB: conf.StateDiskSizeGB,
|
||||||
|
DiskType: conf.Provider.Azure.StateDiskType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Location: conf.Provider.Azure.Location,
|
||||||
|
SecureBoot: conf.Provider.Azure.SecureBoot,
|
||||||
|
CreateMAA: toPtr(conf.GetAttestationConfig().GetVariant().Equal(variant.AzureSEVSNP{})),
|
||||||
|
Debug: toPtr(conf.IsDebugCluster()),
|
||||||
}
|
}
|
||||||
return targets, vars, nil
|
return targets, vars, nil
|
||||||
case cloudprovider.GCP:
|
case cloudprovider.GCP:
|
||||||
@ -427,3 +443,7 @@ type cloudUpgrader interface {
|
|||||||
CheckTerraformMigrations(fileHandler file.Handler) error
|
CheckTerraformMigrations(fileHandler file.Handler) error
|
||||||
CleanUpTerraformMigrations(fileHandler file.Handler) error
|
CleanUpTerraformMigrations(fileHandler file.Handler) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toPtr[T any](v T) *T {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
@ -103,6 +103,7 @@ go_test(
|
|||||||
"//internal/cloud/cloudprovider",
|
"//internal/cloud/cloudprovider",
|
||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/file",
|
"//internal/file",
|
||||||
|
"@com_github_azure_azure_sdk_for_go_sdk_azcore//to",
|
||||||
"@com_github_hashicorp_terraform_exec//tfexec",
|
"@com_github_hashicorp_terraform_exec//tfexec",
|
||||||
"@com_github_hashicorp_terraform_json//:terraform-json",
|
"@com_github_hashicorp_terraform_json//:terraform-json",
|
||||||
"@com_github_spf13_afero//:afero",
|
"@com_github_spf13_afero//:afero",
|
||||||
|
@ -221,58 +221,46 @@ resource "azurerm_network_security_group" "security_group" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module "scale_set_control_plane" {
|
module "scale_set_group" {
|
||||||
source = "./modules/scale_set"
|
source = "./modules/scale_set"
|
||||||
|
for_each = var.node_groups
|
||||||
name = "${local.name}-control-plane"
|
base_name = local.name
|
||||||
instance_count = var.control_plane_count
|
node_group_name = each.key
|
||||||
state_disk_size = var.state_disk_size
|
role = each.value.role
|
||||||
state_disk_type = var.state_disk_type
|
zones = each.value.zones
|
||||||
resource_group = var.resource_group
|
|
||||||
location = var.location
|
|
||||||
instance_type = var.instance_type
|
|
||||||
confidential_vm = var.confidential_vm
|
|
||||||
secure_boot = var.secure_boot
|
|
||||||
tags = merge(
|
tags = merge(
|
||||||
local.tags,
|
local.tags,
|
||||||
{ constellation-role = "control-plane" },
|
|
||||||
{ constellation-init-secret-hash = local.initSecretHash },
|
{ constellation-init-secret-hash = local.initSecretHash },
|
||||||
{ constellation-maa-url = var.create_maa ? azurerm_attestation_provider.attestation_provider[0].attestation_uri : "" },
|
{ constellation-maa-url = var.create_maa ? azurerm_attestation_provider.attestation_provider[0].attestation_uri : "" },
|
||||||
)
|
)
|
||||||
image_id = var.image_id
|
|
||||||
|
instance_count = each.value.instance_count
|
||||||
|
state_disk_size = each.value.disk_size
|
||||||
|
state_disk_type = each.value.disk_type
|
||||||
|
location = var.location
|
||||||
|
instance_type = each.value.instance_type
|
||||||
|
confidential_vm = var.confidential_vm
|
||||||
|
secure_boot = var.secure_boot
|
||||||
|
resource_group = var.resource_group
|
||||||
user_assigned_identity = var.user_assigned_identity
|
user_assigned_identity = var.user_assigned_identity
|
||||||
|
image_id = var.image_id
|
||||||
network_security_group_id = azurerm_network_security_group.security_group.id
|
network_security_group_id = azurerm_network_security_group.security_group.id
|
||||||
subnet_id = azurerm_subnet.node_subnet.id
|
subnet_id = azurerm_subnet.node_subnet.id
|
||||||
backend_address_pool_ids = [
|
backend_address_pool_ids = each.value.role == "control-plane" ? [
|
||||||
azurerm_lb_backend_address_pool.all.id,
|
azurerm_lb_backend_address_pool.all.id,
|
||||||
module.loadbalancer_backend_control_plane.backendpool_id
|
module.loadbalancer_backend_control_plane.backendpool_id
|
||||||
]
|
] : [
|
||||||
}
|
|
||||||
|
|
||||||
module "scale_set_worker" {
|
|
||||||
source = "./modules/scale_set"
|
|
||||||
|
|
||||||
name = "${local.name}-worker"
|
|
||||||
instance_count = var.worker_count
|
|
||||||
state_disk_size = var.state_disk_size
|
|
||||||
state_disk_type = var.state_disk_type
|
|
||||||
resource_group = var.resource_group
|
|
||||||
location = var.location
|
|
||||||
instance_type = var.instance_type
|
|
||||||
confidential_vm = var.confidential_vm
|
|
||||||
secure_boot = var.secure_boot
|
|
||||||
tags = merge(
|
|
||||||
local.tags,
|
|
||||||
{ constellation-role = "worker" },
|
|
||||||
{ constellation-init-secret-hash = local.initSecretHash },
|
|
||||||
{ constellation-maa-url = var.create_maa ? azurerm_attestation_provider.attestation_provider[0].attestation_uri : "" },
|
|
||||||
)
|
|
||||||
image_id = var.image_id
|
|
||||||
user_assigned_identity = var.user_assigned_identity
|
|
||||||
network_security_group_id = azurerm_network_security_group.security_group.id
|
|
||||||
subnet_id = azurerm_subnet.node_subnet.id
|
|
||||||
backend_address_pool_ids = [
|
|
||||||
azurerm_lb_backend_address_pool.all.id,
|
azurerm_lb_backend_address_pool.all.id,
|
||||||
module.loadbalancer_backend_worker.backendpool_id,
|
module.loadbalancer_backend_worker.backendpool_id
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moved {
|
||||||
|
from = module.scale_set_control_plane
|
||||||
|
to = module.scale_set_group["control_plane_default"]
|
||||||
|
}
|
||||||
|
|
||||||
|
moved {
|
||||||
|
from = module.scale_set_worker
|
||||||
|
to = module.scale_set_group["worker_default"]
|
||||||
|
}
|
||||||
|
@ -11,6 +11,19 @@ terraform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
locals {
|
||||||
|
tags = merge(
|
||||||
|
var.tags,
|
||||||
|
{ constellation-role = var.role },
|
||||||
|
{ constellation-node-group = var.node_group_name },
|
||||||
|
)
|
||||||
|
group_uid = random_id.uid.hex
|
||||||
|
name = "${var.base_name}-${var.role}${local.group_uid}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "random_id" "uid" {
|
||||||
|
byte_length = 4
|
||||||
|
}
|
||||||
resource "random_password" "password" {
|
resource "random_password" "password" {
|
||||||
length = 16
|
length = 16
|
||||||
min_lower = 1
|
min_lower = 1
|
||||||
@ -20,7 +33,7 @@ resource "random_password" "password" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "azurerm_linux_virtual_machine_scale_set" "scale_set" {
|
resource "azurerm_linux_virtual_machine_scale_set" "scale_set" {
|
||||||
name = var.name
|
name = local.name
|
||||||
resource_group_name = var.resource_group
|
resource_group_name = var.resource_group
|
||||||
location = var.location
|
location = var.location
|
||||||
sku = var.instance_type
|
sku = var.instance_type
|
||||||
@ -34,8 +47,8 @@ resource "azurerm_linux_virtual_machine_scale_set" "scale_set" {
|
|||||||
upgrade_mode = "Manual"
|
upgrade_mode = "Manual"
|
||||||
secure_boot_enabled = var.secure_boot
|
secure_boot_enabled = var.secure_boot
|
||||||
source_image_id = var.image_id
|
source_image_id = var.image_id
|
||||||
tags = var.tags
|
tags = local.tags
|
||||||
|
zones = var.zones
|
||||||
identity {
|
identity {
|
||||||
type = "UserAssigned"
|
type = "UserAssigned"
|
||||||
identity_ids = [var.user_assigned_identity]
|
identity_ids = [var.user_assigned_identity]
|
||||||
@ -81,6 +94,7 @@ resource "azurerm_linux_virtual_machine_scale_set" "scale_set" {
|
|||||||
|
|
||||||
lifecycle {
|
lifecycle {
|
||||||
ignore_changes = [
|
ignore_changes = [
|
||||||
|
name, # required. Allow legacy scale sets to keep their old names
|
||||||
instances, # required. autoscaling modifies the instance count externally
|
instances, # required. autoscaling modifies the instance count externally
|
||||||
source_image_id, # required. update procedure modifies the image id externally
|
source_image_id, # required. update procedure modifies the image id externally
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,31 @@
|
|||||||
variable "name" {
|
variable "base_name" {
|
||||||
type = string
|
type = string
|
||||||
default = "constell"
|
description = "Base name of the instance group."
|
||||||
description = "Base name of the cluster."
|
}
|
||||||
|
|
||||||
|
variable "node_group_name" {
|
||||||
|
type = string
|
||||||
|
description = "Constellation name for the node group (used for configuration and CSP-independent naming)."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "role" {
|
||||||
|
type = string
|
||||||
|
description = "The role of the instance group."
|
||||||
|
validation {
|
||||||
|
condition = contains(["control-plane", "worker"], var.role)
|
||||||
|
error_message = "The role has to be 'control-plane' or 'worker'."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "tags" {
|
||||||
|
type = map(string)
|
||||||
|
description = "Tags to include in the scale_set."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "zones" {
|
||||||
|
type = list(string)
|
||||||
|
description = "List of availability zones."
|
||||||
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "instance_count" {
|
variable "instance_count" {
|
||||||
@ -61,11 +85,6 @@ variable "subnet_id" {
|
|||||||
description = "The ID of the subnet to use for the scale set."
|
description = "The ID of the subnet to use for the scale set."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "tags" {
|
|
||||||
type = map(string)
|
|
||||||
description = "The tags to add to the scale set."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "confidential_vm" {
|
variable "confidential_vm" {
|
||||||
type = bool
|
type = bool
|
||||||
default = true
|
default = true
|
||||||
|
@ -1,28 +1,22 @@
|
|||||||
variable "name" {
|
variable "name" {
|
||||||
type = string
|
type = string
|
||||||
default = "constell"
|
|
||||||
description = "Base name of the cluster."
|
description = "Base name of the cluster."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "control_plane_count" {
|
variable "node_groups" {
|
||||||
type = number
|
type = map(object({
|
||||||
description = "The number of control plane nodes to deploy."
|
role = string
|
||||||
}
|
instance_count = optional(number)
|
||||||
|
instance_type = string
|
||||||
variable "worker_count" {
|
disk_size = number
|
||||||
type = number
|
disk_type = string
|
||||||
description = "The number of worker nodes to deploy."
|
zones = optional(list(string))
|
||||||
}
|
}))
|
||||||
|
description = "A map of node group names to node group configurations."
|
||||||
variable "state_disk_size" {
|
validation {
|
||||||
type = number
|
condition = can([for group in var.node_groups : group.role == "control-plane" || group.role == "worker"])
|
||||||
default = 30
|
error_message = "The role has to be 'control-plane' or 'worker'."
|
||||||
description = "The size of the state disk in GB."
|
}
|
||||||
}
|
|
||||||
|
|
||||||
variable "resource_group" {
|
|
||||||
type = string
|
|
||||||
description = "The name of the Azure resource group to create the Constellation cluster in."
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "location" {
|
variable "location" {
|
||||||
@ -30,27 +24,23 @@ variable "location" {
|
|||||||
description = "The Azure location to deploy the cluster in."
|
description = "The Azure location to deploy the cluster in."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "user_assigned_identity" {
|
|
||||||
type = string
|
|
||||||
description = "The name of the user assigned identity to attache to the nodes of the cluster."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "instance_type" {
|
|
||||||
type = string
|
|
||||||
description = "The Azure instance type to deploy."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "state_disk_type" {
|
|
||||||
type = string
|
|
||||||
default = "Premium_LRS"
|
|
||||||
description = "The type of the state disk."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "image_id" {
|
variable "image_id" {
|
||||||
type = string
|
type = string
|
||||||
description = "The image to use for the cluster nodes."
|
description = "The image to use for the cluster nodes."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "create_maa" {
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
description = "Whether to create a Microsoft Azure attestation provider."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "debug" {
|
||||||
|
type = bool
|
||||||
|
default = false
|
||||||
|
description = "Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper."
|
||||||
|
}
|
||||||
|
|
||||||
variable "confidential_vm" {
|
variable "confidential_vm" {
|
||||||
type = bool
|
type = bool
|
||||||
default = true
|
default = true
|
||||||
@ -63,14 +53,11 @@ variable "secure_boot" {
|
|||||||
description = "Whether to deploy the cluster nodes with secure boot."
|
description = "Whether to deploy the cluster nodes with secure boot."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "create_maa" {
|
variable "resource_group" {
|
||||||
type = bool
|
type = string
|
||||||
default = false
|
description = "The name of the Azure resource group to create the Constellation cluster in."
|
||||||
description = "Whether to create a Microsoft Azure attestation provider."
|
|
||||||
}
|
}
|
||||||
|
variable "user_assigned_identity" {
|
||||||
variable "debug" {
|
type = string
|
||||||
type = bool
|
description = "The name of the user assigned identity to attache to the nodes of the cluster."
|
||||||
default = false
|
|
||||||
description = "Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper."
|
|
||||||
}
|
}
|
||||||
|
@ -162,47 +162,45 @@ func (v *GCPIAMVariables) String() string {
|
|||||||
|
|
||||||
// AzureClusterVariables is user configuration for creating a cluster with Terraform on Azure.
|
// AzureClusterVariables is user configuration for creating a cluster with Terraform on Azure.
|
||||||
type AzureClusterVariables struct {
|
type AzureClusterVariables struct {
|
||||||
// CommonVariables contains common variables.
|
// Name of the cluster.
|
||||||
CommonVariables
|
Name string `hcl:"name" cty:"name"`
|
||||||
|
|
||||||
// ResourceGroup is the name of the Azure resource group to use.
|
|
||||||
ResourceGroup string
|
|
||||||
// Location is the Azure location to use.
|
|
||||||
Location string
|
|
||||||
// UserAssignedIdentity is the name of the Azure user-assigned identity to use.
|
|
||||||
UserAssignedIdentity string
|
|
||||||
// InstanceType is the Azure instance type to use.
|
|
||||||
InstanceType string
|
|
||||||
// StateDiskType is the Azure disk type to use for the state disk.
|
|
||||||
StateDiskType string
|
|
||||||
// ImageID is the ID of the Azure image to use.
|
// ImageID is the ID of the Azure image to use.
|
||||||
ImageID string
|
ImageID string `hcl:"image_id" cty:"image_id"`
|
||||||
// ConfidentialVM sets the VM to be confidential.
|
|
||||||
ConfidentialVM bool
|
|
||||||
// SecureBoot sets the VM to use secure boot.
|
|
||||||
SecureBoot bool
|
|
||||||
// CreateMAA sets whether a Microsoft Azure attestation provider should be created.
|
// CreateMAA sets whether a Microsoft Azure attestation provider should be created.
|
||||||
CreateMAA bool
|
CreateMAA *bool `hcl:"create_maa" cty:"create_maa"`
|
||||||
// Debug is true if debug mode is enabled.
|
// Debug is true if debug mode is enabled.
|
||||||
Debug bool
|
Debug *bool `hcl:"debug" cty:"debug"`
|
||||||
|
// ResourceGroup is the name of the Azure resource group to use.
|
||||||
|
ResourceGroup string `hcl:"resource_group" cty:"resource_group"`
|
||||||
|
// Location is the Azure location to use.
|
||||||
|
Location string `hcl:"location" cty:"location"`
|
||||||
|
// UserAssignedIdentity is the name of the Azure user-assigned identity to use.
|
||||||
|
UserAssignedIdentity string `hcl:"user_assigned_identity" cty:"user_assigned_identity"`
|
||||||
|
// ConfidentialVM sets the VM to be confidential.
|
||||||
|
ConfidentialVM *bool `hcl:"confidential_vm" cty:"confidential_vm"`
|
||||||
|
// SecureBoot sets the VM to use secure boot.
|
||||||
|
SecureBoot *bool `hcl:"secure_boot" cty:"secure_boot"`
|
||||||
|
// NodeGroups is a map of node groups to create.
|
||||||
|
NodeGroups map[string]AzureNodeGroup `hcl:"node_groups" cty:"node_groups"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a string representation of the variables, formatted as Terraform variables.
|
// String returns a string representation of the variables, formatted as Terraform variables.
|
||||||
func (v *AzureClusterVariables) String() string {
|
func (v *AzureClusterVariables) String() string {
|
||||||
b := &strings.Builder{}
|
f := hclwrite.NewEmptyFile()
|
||||||
b.WriteString(v.CommonVariables.String())
|
gohcl.EncodeIntoBody(v, f.Body())
|
||||||
writeLinef(b, "resource_group = %q", v.ResourceGroup)
|
return string(f.Bytes())
|
||||||
writeLinef(b, "location = %q", v.Location)
|
}
|
||||||
writeLinef(b, "user_assigned_identity = %q", v.UserAssignedIdentity)
|
|
||||||
writeLinef(b, "instance_type = %q", v.InstanceType)
|
|
||||||
writeLinef(b, "state_disk_type = %q", v.StateDiskType)
|
|
||||||
writeLinef(b, "image_id = %q", v.ImageID)
|
|
||||||
writeLinef(b, "confidential_vm = %t", v.ConfidentialVM)
|
|
||||||
writeLinef(b, "secure_boot = %t", v.SecureBoot)
|
|
||||||
writeLinef(b, "create_maa = %t", v.CreateMAA)
|
|
||||||
writeLinef(b, "debug = %t", v.Debug)
|
|
||||||
|
|
||||||
return b.String()
|
// AzureNodeGroup is a node group to create on Azure.
|
||||||
|
type AzureNodeGroup struct {
|
||||||
|
// Role is the role of the node group.
|
||||||
|
Role string `hcl:"role" cty:"role"`
|
||||||
|
// InstanceCount is optional for upgrades.
|
||||||
|
InstanceCount *int `hcl:"instance_count" cty:"instance_count"`
|
||||||
|
InstanceType string `hcl:"instance_type" cty:"instance_type"`
|
||||||
|
DiskSizeGB int `hcl:"disk_size" cty:"disk_size"`
|
||||||
|
DiskType string `hcl:"disk_type" cty:"disk_type"`
|
||||||
|
Zones *[]string `hcl:"zones" cty:"zones"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AzureIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure.
|
// AzureIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure.
|
||||||
|
@ -9,6 +9,7 @@ package terraform
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -142,39 +143,44 @@ service_account_id = "my-service-account"
|
|||||||
|
|
||||||
func TestAzureClusterVariables(t *testing.T) {
|
func TestAzureClusterVariables(t *testing.T) {
|
||||||
vars := AzureClusterVariables{
|
vars := AzureClusterVariables{
|
||||||
CommonVariables: CommonVariables{
|
Name: "cluster-name",
|
||||||
Name: "cluster-name",
|
NodeGroups: map[string]AzureNodeGroup{
|
||||||
CountControlPlanes: 1,
|
"control_plane_default": {
|
||||||
CountWorkers: 2,
|
Role: "ControlPlane",
|
||||||
StateDiskSizeGB: 30,
|
InstanceCount: to.Ptr(1),
|
||||||
|
InstanceType: "Standard_D2s_v3",
|
||||||
|
DiskType: "StandardSSD_LRS",
|
||||||
|
DiskSizeGB: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
ConfidentialVM: to.Ptr(true),
|
||||||
ResourceGroup: "my-resource-group",
|
ResourceGroup: "my-resource-group",
|
||||||
Location: "eu-central-1",
|
|
||||||
UserAssignedIdentity: "my-user-assigned-identity",
|
UserAssignedIdentity: "my-user-assigned-identity",
|
||||||
InstanceType: "Standard_D2s_v3",
|
|
||||||
StateDiskType: "StandardSSD_LRS",
|
|
||||||
ImageID: "image-0123456789abcdef",
|
ImageID: "image-0123456789abcdef",
|
||||||
ConfidentialVM: true,
|
CreateMAA: to.Ptr(true),
|
||||||
SecureBoot: false,
|
Debug: to.Ptr(true),
|
||||||
CreateMAA: true,
|
Location: "eu-central-1",
|
||||||
Debug: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// test that the variables are correctly rendered
|
// test that the variables are correctly rendered
|
||||||
want := `name = "cluster-name"
|
want := `name = "cluster-name"
|
||||||
control_plane_count = 1
|
image_id = "image-0123456789abcdef"
|
||||||
worker_count = 2
|
create_maa = true
|
||||||
state_disk_size = 30
|
debug = true
|
||||||
resource_group = "my-resource-group"
|
resource_group = "my-resource-group"
|
||||||
location = "eu-central-1"
|
location = "eu-central-1"
|
||||||
user_assigned_identity = "my-user-assigned-identity"
|
user_assigned_identity = "my-user-assigned-identity"
|
||||||
instance_type = "Standard_D2s_v3"
|
confidential_vm = true
|
||||||
state_disk_type = "StandardSSD_LRS"
|
node_groups = {
|
||||||
image_id = "image-0123456789abcdef"
|
control_plane_default = {
|
||||||
confidential_vm = true
|
disk_size = 100
|
||||||
secure_boot = false
|
disk_type = "StandardSSD_LRS"
|
||||||
create_maa = true
|
instance_count = 1
|
||||||
debug = true
|
instance_type = "Standard_D2s_v3"
|
||||||
|
role = "ControlPlane"
|
||||||
|
zones = null
|
||||||
|
}
|
||||||
|
}
|
||||||
`
|
`
|
||||||
got := vars.String()
|
got := vars.String()
|
||||||
assert.Equal(t, want, got)
|
assert.Equal(t, want, got)
|
||||||
|
@ -25,6 +25,18 @@ const (
|
|||||||
Worker
|
Worker
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TFString returns the role as a string for Terraform.
|
||||||
|
func (r Role) TFString() string {
|
||||||
|
switch r {
|
||||||
|
case ControlPlane:
|
||||||
|
return "control-plane"
|
||||||
|
case Worker:
|
||||||
|
return "worker"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON marshals the Role to JSON string.
|
// MarshalJSON marshals the Role to JSON string.
|
||||||
func (r Role) MarshalJSON() ([]byte, error) {
|
func (r Role) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(r.String())
|
return json.Marshal(r.String())
|
||||||
|
Loading…
Reference in New Issue
Block a user