mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04: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" {
|
resource "constellation_cluster" "azure_example" {
|
||||||
csp = "azure"
|
csp = "azure"
|
||||||
constellation_microservice_version = "vX.Y.Z"
|
|
||||||
name = "constell"
|
name = "constell"
|
||||||
uid = "..."
|
uid = "..."
|
||||||
image = data.constellation_image.bar.image
|
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.
|
- `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))
|
- `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))
|
- `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))
|
- `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.
|
- `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" {
|
resource "constellation_cluster" "aws_example" {
|
||||||
csp = local.csp
|
csp = local.csp
|
||||||
constellation_microservice_version = local.version
|
name = module.aws_infrastructure.name
|
||||||
name = module.aws_infrastructure.name
|
uid = module.aws_infrastructure.uid
|
||||||
uid = module.aws_infrastructure.uid
|
image = data.constellation_image.bar.image
|
||||||
image = data.constellation_image.bar.image
|
attestation = data.constellation_attestation.foo.attestation
|
||||||
attestation = data.constellation_attestation.foo.attestation
|
init_secret = module.aws_infrastructure.init_secret
|
||||||
init_secret = module.aws_infrastructure.init_secret
|
master_secret = local.master_secret
|
||||||
master_secret = local.master_secret
|
master_secret_salt = local.master_secret_salt
|
||||||
master_secret_salt = local.master_secret_salt
|
measurement_salt = local.measurement_salt
|
||||||
measurement_salt = local.measurement_salt
|
out_of_cluster_endpoint = module.aws_infrastructure.out_of_cluster_endpoint
|
||||||
out_of_cluster_endpoint = module.aws_infrastructure.out_of_cluster_endpoint
|
in_cluster_endpoint = module.aws_infrastructure.in_cluster_endpoint
|
||||||
in_cluster_endpoint = module.aws_infrastructure.in_cluster_endpoint
|
|
||||||
network_config = {
|
network_config = {
|
||||||
ip_cidr_node = module.aws_infrastructure.ip_cidr_node
|
ip_cidr_node = module.aws_infrastructure.ip_cidr_node
|
||||||
ip_cidr_service = "10.96.0.0/12"
|
ip_cidr_service = "10.96.0.0/12"
|
||||||
|
@ -84,18 +84,17 @@ data "constellation_image" "bar" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "constellation_cluster" "azure_example" {
|
resource "constellation_cluster" "azure_example" {
|
||||||
csp = local.csp
|
csp = local.csp
|
||||||
constellation_microservice_version = local.version
|
name = module.azure_infrastructure.name
|
||||||
name = module.azure_infrastructure.name
|
uid = module.azure_infrastructure.uid
|
||||||
uid = module.azure_infrastructure.uid
|
image = data.constellation_image.bar.image
|
||||||
image = data.constellation_image.bar.image
|
attestation = data.constellation_attestation.foo.attestation
|
||||||
attestation = data.constellation_attestation.foo.attestation
|
init_secret = module.azure_infrastructure.init_secret
|
||||||
init_secret = module.azure_infrastructure.init_secret
|
master_secret = local.master_secret
|
||||||
master_secret = local.master_secret
|
master_secret_salt = local.master_secret_salt
|
||||||
master_secret_salt = local.master_secret_salt
|
measurement_salt = local.measurement_salt
|
||||||
measurement_salt = local.measurement_salt
|
out_of_cluster_endpoint = module.azure_infrastructure.out_of_cluster_endpoint
|
||||||
out_of_cluster_endpoint = module.azure_infrastructure.out_of_cluster_endpoint
|
in_cluster_endpoint = module.azure_infrastructure.in_cluster_endpoint
|
||||||
in_cluster_endpoint = module.azure_infrastructure.in_cluster_endpoint
|
|
||||||
azure = {
|
azure = {
|
||||||
tenant_id = module.azure_iam.tenant_id
|
tenant_id = module.azure_iam.tenant_id
|
||||||
subscription_id = module.azure_iam.subscription_id
|
subscription_id = module.azure_iam.subscription_id
|
||||||
|
@ -88,18 +88,17 @@ data "constellation_image" "bar" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "constellation_cluster" "gcp_example" {
|
resource "constellation_cluster" "gcp_example" {
|
||||||
csp = local.csp
|
csp = local.csp
|
||||||
constellation_microservice_version = local.version
|
name = module.gcp_infrastructure.name
|
||||||
name = module.gcp_infrastructure.name
|
uid = module.gcp_infrastructure.uid
|
||||||
uid = module.gcp_infrastructure.uid
|
image = data.constellation_image.bar.image
|
||||||
image = data.constellation_image.bar.image
|
attestation = data.constellation_attestation.foo.attestation
|
||||||
attestation = data.constellation_attestation.foo.attestation
|
init_secret = module.gcp_infrastructure.init_secret
|
||||||
init_secret = module.gcp_infrastructure.init_secret
|
master_secret = local.master_secret
|
||||||
master_secret = local.master_secret
|
master_secret_salt = local.master_secret_salt
|
||||||
master_secret_salt = local.master_secret_salt
|
measurement_salt = local.measurement_salt
|
||||||
measurement_salt = local.measurement_salt
|
out_of_cluster_endpoint = module.gcp_infrastructure.out_of_cluster_endpoint
|
||||||
out_of_cluster_endpoint = module.gcp_infrastructure.out_of_cluster_endpoint
|
in_cluster_endpoint = module.gcp_infrastructure.in_cluster_endpoint
|
||||||
in_cluster_endpoint = module.gcp_infrastructure.in_cluster_endpoint
|
|
||||||
gcp = {
|
gcp = {
|
||||||
project_id = module.gcp_infrastructure.project
|
project_id = module.gcp_infrastructure.project
|
||||||
service_account_key = module.gcp_iam.service_account_key
|
service_account_key = module.gcp_iam.service_account_key
|
||||||
|
@ -16,7 +16,6 @@ resource "random_bytes" "measurement_salt" {
|
|||||||
|
|
||||||
resource "constellation_cluster" "azure_example" {
|
resource "constellation_cluster" "azure_example" {
|
||||||
csp = "azure"
|
csp = "azure"
|
||||||
constellation_microservice_version = "vX.Y.Z"
|
|
||||||
name = "constell"
|
name = "constell"
|
||||||
uid = "..."
|
uid = "..."
|
||||||
image = data.constellation_image.bar.image
|
image = data.constellation_image.bar.image
|
||||||
|
@ -8,4 +8,5 @@ go_library(
|
|||||||
],
|
],
|
||||||
importpath = "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data",
|
importpath = "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data",
|
||||||
visibility = ["//terraform-provider-constellation:__subpackages__"],
|
visibility = ["//terraform-provider-constellation:__subpackages__"],
|
||||||
|
deps = ["//internal/semver"],
|
||||||
)
|
)
|
||||||
|
@ -6,8 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||||||
|
|
||||||
package data
|
package data
|
||||||
|
|
||||||
|
import "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
|
|
||||||
// ProviderData is the data that get's passed down from the provider
|
// ProviderData is the data that get's passed down from the provider
|
||||||
// configuration to the resources and data sources.
|
// configuration to the resources and data sources.
|
||||||
type ProviderData struct {
|
type ProviderData struct {
|
||||||
Version string
|
Version semver.Semver
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ func (d *AttestationDataSource) Configure(_ context.Context, req datasource.Conf
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.version = providerData.Version
|
d.version = providerData.Version.String()
|
||||||
|
|
||||||
d.client = http.DefaultClient
|
d.client = http.DefaultClient
|
||||||
d.fetcher = attestationconfigapi.NewFetcher()
|
d.fetcher = attestationconfigapi.NewFetcher()
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
"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/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||||
@ -60,7 +61,8 @@ func NewClusterResource() resource.Resource {
|
|||||||
|
|
||||||
// ClusterResource defines the resource implementation.
|
// ClusterResource defines the resource implementation.
|
||||||
type ClusterResource struct {
|
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.
|
// ClusterResourceModel describes the resource data model.
|
||||||
@ -155,8 +157,8 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
"constellation_microservice_version": schema.StringAttribute{
|
"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.",
|
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 default version is used.",
|
Description: "The version of Constellation's microservices used within the cluster. When not set, the provider version is used.",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
"out_of_cluster_endpoint": schema.StringAttribute{
|
"out_of_cluster_endpoint": schema.StringAttribute{
|
||||||
@ -330,11 +332,20 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Configure configures the resource.
|
// 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.
|
// Prevent panic if the provider has not been configured.
|
||||||
if req.ProviderData == nil {
|
if req.ProviderData == nil {
|
||||||
return
|
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 {
|
newDialer := func(validator atls.Validator) *dialer.Dialer {
|
||||||
return dialer.New(nil, validator, &net.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.
|
// 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",
|
resp.Diagnostics.AddWarning("Microservice version change",
|
||||||
"Changing the microservice version can be a destructive operation.\n"+
|
"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"+
|
"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
|
// parse Constellation microservice version
|
||||||
microserviceVersion, err := semver.New(data.MicroserviceVersion.ValueString())
|
microserviceVersion, convertDiags := r.getMicroserviceVersion(ctx, data)
|
||||||
if err != nil {
|
diags.Append(convertDiags...)
|
||||||
diags.AddAttributeError(
|
if diags.HasError() {
|
||||||
path.Root("constellation_microservice_version"),
|
|
||||||
"Invalid microservice version",
|
|
||||||
fmt.Sprintf("Parsing microservice version: %s", err))
|
|
||||||
return diags
|
return diags
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1008,6 +1028,28 @@ func (r *ClusterResource) getK8sVersion(ctx context.Context, data *ClusterResour
|
|||||||
return k8sVersion, 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) {
|
||||||
|
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
|
// tfContextLogger is a logging adapter between the tflog package and
|
||||||
// Constellation's logger.
|
// Constellation's logger.
|
||||||
type tfContextLogger struct {
|
type tfContextLogger struct {
|
||||||
|
@ -136,7 +136,7 @@ func (d *ImageDataSource) Configure(_ context.Context, req datasource.ConfigureR
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.version = providerData.Version
|
d.version = providerData.Version.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads from the data source.
|
// Read reads from the data source.
|
||||||
|
@ -11,7 +11,9 @@ package provider
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
datastruct "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data"
|
datastruct "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
"github.com/hashicorp/terraform-plugin-framework/provider"
|
"github.com/hashicorp/terraform-plugin-framework/provider"
|
||||||
@ -69,8 +71,16 @@ func (p *ConstellationProvider) Configure(ctx context.Context, req provider.Conf
|
|||||||
return
|
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{
|
config := datastruct.ProviderData{
|
||||||
Version: p.version,
|
Version: ver,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the clients available during data source and resource "Configure" methods.
|
// Make the clients available during data source and resource "Configure" methods.
|
||||||
|
Loading…
Reference in New Issue
Block a user