mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-28 00:49:26 -05:00
terraform-provider: lock-step microservice version (#2733)
This commit is contained in:
parent
615e731855
commit
9414f29b51
@ -31,7 +31,6 @@ resource "random_bytes" "measurement_salt" {
|
||||
|
||||
resource "constellation_cluster" "azure_example" {
|
||||
csp = "azure"
|
||||
constellation_microservice_version = "vX.Y.Z"
|
||||
name = "constell"
|
||||
uid = "..."
|
||||
image = data.constellation_image.bar.image
|
||||
@ -79,7 +78,7 @@ resource "constellation_cluster" "azure_example" {
|
||||
|
||||
- `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 default version is used.
|
||||
- `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.
|
||||
|
@ -89,18 +89,17 @@ data "constellation_image" "bar" {
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "aws_example" {
|
||||
csp = local.csp
|
||||
constellation_microservice_version = local.version
|
||||
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
|
||||
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
|
||||
network_config = {
|
||||
ip_cidr_node = module.aws_infrastructure.ip_cidr_node
|
||||
ip_cidr_service = "10.96.0.0/12"
|
||||
|
@ -84,18 +84,17 @@ data "constellation_image" "bar" {
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "azure_example" {
|
||||
csp = local.csp
|
||||
constellation_microservice_version = local.version
|
||||
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
|
||||
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
|
||||
azure = {
|
||||
tenant_id = module.azure_iam.tenant_id
|
||||
subscription_id = module.azure_iam.subscription_id
|
||||
|
@ -88,18 +88,17 @@ data "constellation_image" "bar" {
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "gcp_example" {
|
||||
csp = local.csp
|
||||
constellation_microservice_version = local.version
|
||||
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
|
||||
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
|
||||
gcp = {
|
||||
project_id = module.gcp_infrastructure.project
|
||||
service_account_key = module.gcp_iam.service_account_key
|
||||
|
@ -16,7 +16,6 @@ resource "random_bytes" "measurement_salt" {
|
||||
|
||||
resource "constellation_cluster" "azure_example" {
|
||||
csp = "azure"
|
||||
constellation_microservice_version = "vX.Y.Z"
|
||||
name = "constell"
|
||||
uid = "..."
|
||||
image = data.constellation_image.bar.image
|
||||
|
@ -8,4 +8,5 @@ go_library(
|
||||
],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data",
|
||||
visibility = ["//terraform-provider-constellation:__subpackages__"],
|
||||
deps = ["//internal/semver"],
|
||||
)
|
||||
|
@ -6,8 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
package data
|
||||
|
||||
import "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
|
||||
// ProviderData is the data that get's passed down from the provider
|
||||
// configuration to the resources and data sources.
|
||||
type ProviderData struct {
|
||||
Version string
|
||||
Version semver.Semver
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ func (d *AttestationDataSource) Configure(_ context.Context, req datasource.Conf
|
||||
)
|
||||
return
|
||||
}
|
||||
d.version = providerData.Version
|
||||
d.version = providerData.Version.String()
|
||||
|
||||
d.client = http.DefaultClient
|
||||
d.fetcher = attestationconfigapi.NewFetcher()
|
||||
|
@ -35,6 +35,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
datastruct "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
@ -60,7 +61,8 @@ func NewClusterResource() resource.Resource {
|
||||
|
||||
// ClusterResource defines the resource implementation.
|
||||
type ClusterResource struct {
|
||||
newApplier func(ctx context.Context, validator atls.Validator) *constellation.Applier
|
||||
providerData datastruct.ProviderData
|
||||
newApplier func(ctx context.Context, validator atls.Validator) *constellation.Applier
|
||||
}
|
||||
|
||||
// ClusterResourceModel describes the resource data model.
|
||||
@ -155,8 +157,8 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
||||
Optional: true,
|
||||
},
|
||||
"constellation_microservice_version": schema.StringAttribute{
|
||||
MarkdownDescription: "The version of Constellation's microservices used within the cluster. When not set, the provider default version is used.",
|
||||
Description: "The version of Constellation's microservices used within the cluster. When not set, the provider default version is used.",
|
||||
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,
|
||||
},
|
||||
"out_of_cluster_endpoint": schema.StringAttribute{
|
||||
@ -330,11 +332,20 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
||||
}
|
||||
|
||||
// Configure configures the resource.
|
||||
func (r *ClusterResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
|
||||
func (r *ClusterResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
// Prevent panic if the provider has not been configured.
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
var ok bool
|
||||
r.providerData, ok = req.ProviderData.(datastruct.ProviderData)
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Resource Configure Type",
|
||||
fmt.Sprintf("Expected datastruct.ProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
newDialer := func(validator atls.Validator) *dialer.Dialer {
|
||||
return dialer.New(nil, validator, &net.Dialer{})
|
||||
@ -365,7 +376,19 @@ 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.
|
||||
if currentState.MicroserviceVersion.ValueString() != plannedState.MicroserviceVersion.ValueString() {
|
||||
currVer, diags := r.getMicroserviceVersion(ctx, ¤tState)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
plannedVer, diags := r.getMicroserviceVersion(ctx, &plannedState)
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
if currVer.Compare(plannedVer) != 0 { // if versions are not equal
|
||||
resp.Diagnostics.AddWarning("Microservice version change",
|
||||
"Changing the microservice version can be a destructive operation.\n"+
|
||||
"Upgrading cert-manager will destroy all custom resources you have manually created that are based on the current version of cert-manager.\n"+
|
||||
@ -575,12 +598,9 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
|
||||
}
|
||||
|
||||
// parse Constellation microservice version
|
||||
microserviceVersion, 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))
|
||||
microserviceVersion, convertDiags := r.getMicroserviceVersion(ctx, data)
|
||||
diags.Append(convertDiags...)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
|
||||
@ -1008,6 +1028,28 @@ func (r *ClusterResource) getK8sVersion(ctx context.Context, data *ClusterResour
|
||||
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) {
|
||||
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
|
||||
}
|
||||
return ver, diags
|
||||
}
|
||||
|
||||
// tfContextLogger is a logging adapter between the tflog package and
|
||||
// Constellation's logger.
|
||||
type tfContextLogger struct {
|
||||
|
@ -136,7 +136,7 @@ func (d *ImageDataSource) Configure(_ context.Context, req datasource.ConfigureR
|
||||
return
|
||||
}
|
||||
|
||||
d.version = providerData.Version
|
||||
d.version = providerData.Version.String()
|
||||
}
|
||||
|
||||
// Read reads from the data source.
|
||||
|
@ -11,7 +11,9 @@ package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
datastruct "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider"
|
||||
@ -69,8 +71,16 @@ func (p *ConstellationProvider) Configure(ctx context.Context, req provider.Conf
|
||||
return
|
||||
}
|
||||
|
||||
ver, err := semver.New(p.version)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Invalid provider version",
|
||||
fmt.Sprintf("Expected a valid semantic version, got %s: %s", p.version, err),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
config := datastruct.ProviderData{
|
||||
Version: p.version,
|
||||
Version: ver,
|
||||
}
|
||||
|
||||
// Make the clients available during data source and resource "Configure" methods.
|
||||
|
Loading…
Reference in New Issue
Block a user