Skip to content

Commit

Permalink
terraform-provider: require kubernetes and microservice version (#2791)
Browse files Browse the repository at this point in the history
  • Loading branch information
elchead authored Jan 4, 2024
1 parent 26a9639 commit f41ce43
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 133 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/e2e-test-provider-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ jobs:
fi
fi
# take the middle (2nd) supported Kubernetes version (default)
kubernetes_version="$(../build/constellation config kubernetes-versions | awk 'NR==3{print $1}')"
cat > _override.tf <<EOF
terraform {
required_providers {
Expand All @@ -197,6 +200,8 @@ jobs:
locals {
name = "${{ steps.create-prefix.outputs.prefix }}"
version = "${image_version}"
microservice_version= "${prefixed_version}"
kubernetes_version = "${kubernetes_version}"
}
module "${{ inputs.cloudProvider }}_iam" {
source = "${iam_src}"
Expand Down
4 changes: 2 additions & 2 deletions terraform-provider-constellation/docs/resources/cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,12 @@ resource "constellation_cluster" "azure_example" {
### Required

- `attestation` (Attributes) Attestation comprises the measurements and SEV-SNP specific parameters. The output of the [constellation_attestation](../data-sources/attestation.md) data source provides sensible defaults. (see [below for nested schema](#nestedatt--attestation))
- `constellation_microservice_version` (String) The version of Constellation's microservices used within the cluster.
- `csp` (String) CSP (Cloud Service Provider) to use. (e.g. `azure`)
See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.
- `image` (Attributes) Constellation OS Image to use on the nodes. (see [below for nested schema](#nestedatt--image))
- `init_secret` (String) Secret used for initialization of the cluster.
- `kubernetes_version` (String) The Kubernetes version to use for the cluster. The supported versions are [v1.26.12 v1.27.9 v1.28.5].
- `master_secret` (String) Hex-encoded 32-byte master secret for the cluster.
- `master_secret_salt` (String) Hex-encoded 32-byte master secret salt for the cluster.
- `measurement_salt` (String) Hex-encoded 32-byte measurement salt for the cluster.
Expand All @@ -79,11 +81,9 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview

- `api_server_cert_sans` (List of String) List of Subject Alternative Names (SANs) for the API server certificate. Usually, this will be the out-of-cluster endpoint and the in-cluster endpoint, if existing.
- `azure` (Attributes) Azure-specific configuration. (see [below for nested schema](#nestedatt--azure))
- `constellation_microservice_version` (String) The version of Constellation's microservices used within the cluster. When not set, the provider version is used.
- `extra_microservices` (Attributes) Extra microservice settings. (see [below for nested schema](#nestedatt--extra_microservices))
- `gcp` (Attributes) GCP-specific configuration. (see [below for nested schema](#nestedatt--gcp))
- `in_cluster_endpoint` (String) The endpoint of the cluster. When not set, the out-of-cluster endpoint is used.
- `kubernetes_version` (String) The Kubernetes version to use for the cluster. When not set, version v1.27.9 is used. The supported versions are [v1.26.12 v1.27.9 v1.28.5].
- `license_id` (String) Constellation license ID. When not set, the community license is used.

### Read-Only
Expand Down
40 changes: 22 additions & 18 deletions terraform-provider-constellation/examples/full/aws/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ terraform {
}

locals {
name = "constell"
version = "vX.Y.Z"
csp = "aws"
attestation_variant = "aws-sev-snp"
region = "us-east-2"
zone = "us-east-2c"
name = "constell"
version = "vX.Y.Z"
kubernetes_version = "vX.Y.Z"
microservice_version = "vX.Y.Z"
csp = "aws"
attestation_variant = "aws-sev-snp"
region = "us-east-2"
zone = "us-east-2c"

master_secret = random_bytes.master_secret.hex
master_secret_salt = random_bytes.master_secret_salt.hex
Expand Down Expand Up @@ -90,18 +92,20 @@ data "constellation_image" "bar" {
}

resource "constellation_cluster" "aws_example" {
csp = local.csp
name = module.aws_infrastructure.name
uid = module.aws_infrastructure.uid
image = data.constellation_image.bar.image
attestation = data.constellation_attestation.foo.attestation
init_secret = module.aws_infrastructure.init_secret
master_secret = local.master_secret
master_secret_salt = local.master_secret_salt
measurement_salt = local.measurement_salt
out_of_cluster_endpoint = module.aws_infrastructure.out_of_cluster_endpoint
in_cluster_endpoint = module.aws_infrastructure.in_cluster_endpoint
api_server_cert_sans = module.aws_infrastructure.api_server_cert_sans
csp = local.csp
name = module.aws_infrastructure.name
uid = module.aws_infrastructure.uid
image = data.constellation_image.bar.image
attestation = data.constellation_attestation.foo.attestation
kubernetes_version = local.kubernetes_version
constellation_microservice_version = local.microservice_version
init_secret = module.aws_infrastructure.init_secret
master_secret = local.master_secret
master_secret_salt = local.master_secret_salt
measurement_salt = local.measurement_salt
out_of_cluster_endpoint = module.aws_infrastructure.out_of_cluster_endpoint
in_cluster_endpoint = module.aws_infrastructure.in_cluster_endpoint
api_server_cert_sans = module.aws_infrastructure.api_server_cert_sans
network_config = {
ip_cidr_node = module.aws_infrastructure.ip_cidr_node
ip_cidr_service = "10.96.0.0/12"
Expand Down
38 changes: 21 additions & 17 deletions terraform-provider-constellation/examples/full/azure/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ terraform {
}

locals {
name = "constell"
version = "vX.Y.Z"
csp = "azure"
attestation_variant = "azure-sev-snp"
location = "northeurope"
name = "constell"
version = "vX.Y.Z"
kubernetes_version = "vX.Y.Z"
microservice_version = "vX.Y.Z"
csp = "azure"
attestation_variant = "azure-sev-snp"
location = "northeurope"

master_secret = random_bytes.master_secret.hex
master_secret_salt = random_bytes.master_secret_salt.hex
Expand Down Expand Up @@ -85,18 +87,20 @@ data "constellation_image" "bar" {
}

resource "constellation_cluster" "azure_example" {
csp = local.csp
name = module.azure_infrastructure.name
uid = module.azure_infrastructure.uid
image = data.constellation_image.bar.image
attestation = data.constellation_attestation.foo.attestation
init_secret = module.azure_infrastructure.init_secret
master_secret = local.master_secret
master_secret_salt = local.master_secret_salt
measurement_salt = local.measurement_salt
out_of_cluster_endpoint = module.azure_infrastructure.out_of_cluster_endpoint
in_cluster_endpoint = module.azure_infrastructure.in_cluster_endpoint
api_server_cert_sans = module.azure_infrastructure.api_server_cert_sans
csp = local.csp
name = module.azure_infrastructure.name
uid = module.azure_infrastructure.uid
image = data.constellation_image.bar.image
attestation = data.constellation_attestation.foo.attestation
kubernetes_version = local.kubernetes_version
constellation_microservice_version = local.microservice_version
init_secret = module.azure_infrastructure.init_secret
master_secret = local.master_secret
master_secret_salt = local.master_secret_salt
measurement_salt = local.measurement_salt
out_of_cluster_endpoint = module.azure_infrastructure.out_of_cluster_endpoint
in_cluster_endpoint = module.azure_infrastructure.in_cluster_endpoint
api_server_cert_sans = module.azure_infrastructure.api_server_cert_sans
azure = {
tenant_id = module.azure_iam.tenant_id
subscription_id = module.azure_iam.subscription_id
Expand Down
42 changes: 23 additions & 19 deletions terraform-provider-constellation/examples/full/gcp/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ terraform {
}

locals {
name = "constell"
version = "vX.Y.Z"
csp = "gcp"
attestation_variant = "gcp-sev-es"
region = "europe-west3"
zone = "europe-west3-b"
project_id = "constellation-331613"
name = "constell"
version = "vX.Y.Z"
kubernetes_version = "vX.Y.Z"
microservice_version = "vX.Y.Z"
csp = "gcp"
attestation_variant = "gcp-sev-es"
region = "europe-west3"
zone = "europe-west3-b"
project_id = "constellation-331613"

master_secret = random_bytes.master_secret.hex
master_secret_salt = random_bytes.master_secret_salt.hex
Expand Down Expand Up @@ -89,18 +91,20 @@ data "constellation_image" "bar" {
}

resource "constellation_cluster" "gcp_example" {
csp = local.csp
name = module.gcp_infrastructure.name
uid = module.gcp_infrastructure.uid
image = data.constellation_image.bar.image
attestation = data.constellation_attestation.foo.attestation
init_secret = module.gcp_infrastructure.init_secret
master_secret = local.master_secret
master_secret_salt = local.master_secret_salt
measurement_salt = local.measurement_salt
out_of_cluster_endpoint = module.gcp_infrastructure.out_of_cluster_endpoint
in_cluster_endpoint = module.gcp_infrastructure.in_cluster_endpoint
api_server_cert_sans = module.gcp_infrastructure.api_server_cert_sans
csp = local.csp
name = module.gcp_infrastructure.name
uid = module.gcp_infrastructure.uid
image = data.constellation_image.bar.image
attestation = data.constellation_attestation.foo.attestation
kubernetes_version = local.kubernetes_version
constellation_microservice_version = local.microservice_version
init_secret = module.gcp_infrastructure.init_secret
master_secret = local.master_secret
master_secret_salt = local.master_secret_salt
measurement_salt = local.measurement_salt
out_of_cluster_endpoint = module.gcp_infrastructure.out_of_cluster_endpoint
in_cluster_endpoint = module.gcp_infrastructure.in_cluster_endpoint
api_server_cert_sans = module.gcp_infrastructure.api_server_cert_sans
gcp = {
project_id = module.gcp_infrastructure.project
service_account_key = module.gcp_iam.service_account_key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ go_test(
"//internal/config",
"//internal/constants",
"//internal/semver",
"//internal/versions",
"//terraform-provider-constellation/internal/data",
"@com_github_hashicorp_terraform_plugin_framework//attr",
"@com_github_hashicorp_terraform_plugin_framework//providerserver",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
},
"image": newImageAttributeSchema(attributeInput),
"kubernetes_version": schema.StringAttribute{
MarkdownDescription: fmt.Sprintf("The Kubernetes version to use for the cluster. When not set, version %s is used. The supported versions are %s.", versions.Default, versions.SupportedK8sVersions()),
Description: fmt.Sprintf("The Kubernetes version to use for the cluster. When not set, version %s is used. The supported versions are %s.", versions.Default, versions.SupportedK8sVersions()),
Optional: true,
MarkdownDescription: fmt.Sprintf("The Kubernetes version to use for the cluster. The supported versions are %s.", versions.SupportedK8sVersions()),
Description: fmt.Sprintf("The Kubernetes version to use for the cluster. The supported versions are %s.", versions.SupportedK8sVersions()),
Required: true,
},
"constellation_microservice_version": schema.StringAttribute{
MarkdownDescription: "The version of Constellation's microservices used within the cluster. When not set, the provider version is used.",
Description: "The version of Constellation's microservices used within the cluster. When not set, the provider version is used.",
Optional: true,
MarkdownDescription: "The version of Constellation's microservices used within the cluster.",
Description: "The version of Constellation's microservices used within the cluster.",
Required: true,
},
"out_of_cluster_endpoint": schema.StringAttribute{
MarkdownDescription: "The endpoint of the cluster. Typically, this is the public IP of a loadbalancer.",
Expand Down Expand Up @@ -470,13 +470,13 @@ func (r *ClusterResource) ModifyPlan(ctx context.Context, req resource.ModifyPla
}

// Warn the user about possibly destructive changes in case microservice changes are to be applied.
currVer, diags := r.getMicroserviceVersion(ctx, &currentState)
currVer, diags := r.getMicroserviceVersion(&currentState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

plannedVer, diags := r.getMicroserviceVersion(ctx, &plannedState)
plannedVer, diags := r.getMicroserviceVersion(&plannedState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
Expand Down Expand Up @@ -718,14 +718,14 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
}

// parse Constellation microservice version
microserviceVersion, convertDiags := r.getMicroserviceVersion(ctx, data)
microserviceVersion, convertDiags := r.getMicroserviceVersion(data)
diags.Append(convertDiags...)
if diags.HasError() {
return diags
}

// parse Kubernetes version
k8sVersion, getDiags := r.getK8sVersion(ctx, data)
k8sVersion, getDiags := r.getK8sVersion(data)
diags.Append(getDiags...)
if diags.HasError() {
return diags
Expand Down Expand Up @@ -1163,44 +1163,30 @@ func (r *ClusterResource) convertSecrets(data ClusterResourceModel) (secretInput

// getK8sVersion returns the Kubernetes version from the Terraform state if set, and the default
// version otherwise.
func (r *ClusterResource) getK8sVersion(ctx context.Context, data *ClusterResourceModel) (versions.ValidK8sVersion, diag.Diagnostics) {
func (r *ClusterResource) getK8sVersion(data *ClusterResourceModel) (versions.ValidK8sVersion, diag.Diagnostics) {
diags := diag.Diagnostics{}
var k8sVersion versions.ValidK8sVersion
var err error
if data.KubernetesVersion.ValueString() != "" {
k8sVersion, err = versions.NewValidK8sVersion(data.KubernetesVersion.ValueString(), true)
if err != nil {
diags.AddAttributeError(
path.Root("kubernetes_vesion"),
"Invalid Kubernetes version",
fmt.Sprintf("Parsing Kubernetes version: %s", err))
return "", diags
}
} else {
tflog.Info(ctx, fmt.Sprintf("No Kubernetes version specified. Using default version %s.", versions.Default))
k8sVersion = versions.Default
k8sVersion, err := versions.NewValidK8sVersion(data.KubernetesVersion.ValueString(), true)
if err != nil {
diags.AddAttributeError(
path.Root("kubernetes_version"),
"Invalid Kubernetes version",
fmt.Sprintf("Parsing Kubernetes version: %s", err))
return "", diags
}
return k8sVersion, diags
}

// getK8sVersion returns the Microservice version from the Terraform state if set, and the default
// version otherwise.
func (r *ClusterResource) getMicroserviceVersion(ctx context.Context, data *ClusterResourceModel) (semver.Semver, diag.Diagnostics) {
func (r *ClusterResource) getMicroserviceVersion(data *ClusterResourceModel) (semver.Semver, diag.Diagnostics) {
diags := diag.Diagnostics{}
var ver semver.Semver
var err error
if data.MicroserviceVersion.ValueString() != "" {
ver, err = semver.New(data.MicroserviceVersion.ValueString())
if err != nil {
diags.AddAttributeError(
path.Root("constellation_microservice_version"),
"Invalid microservice version",
fmt.Sprintf("Parsing microservice version: %s", err))
return semver.Semver{}, diags
}
} else {
tflog.Info(ctx, fmt.Sprintf("No Microservice version specified. Using default version %s.", r.providerData.Version))
ver = r.providerData.Version
ver, err := semver.New(data.MicroserviceVersion.ValueString())
if err != nil {
diags.AddAttributeError(
path.Root("constellation_microservice_version"),
"Invalid microservice version",
fmt.Sprintf("Parsing microservice version: %s", err))
return semver.Semver{}, diags
}
if err := config.ValidateMicroserviceVersion(r.providerData.Version, ver); err != nil {
diags.AddAttributeError(
Expand Down
Loading

0 comments on commit f41ce43

Please sign in to comment.