Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

terraform-provider: require kubernetes and microservice version #2791

Merged
merged 3 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be equal to version and thus obsolete?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no. version refers to the image_version is and is renamed to make this more clear in #2775

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