mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-03-05 21:26:04 -05:00
terraform-provider: validate image and microservice version (#2766)
This commit is contained in:
parent
519efe637d
commit
436e7c6d3b
@ -846,7 +846,7 @@ func (c *Config) Validate(force bool) error {
|
||||
// Because of this we can't print the offending field name in the error message, resulting in
|
||||
// suboptimal UX. Adding the field name to the struct validation of Semver would make it
|
||||
// impossible to use Semver for other fields.
|
||||
if err := validateMicroserviceVersion(constants.BinaryVersion(), c.MicroserviceVersion); err != nil {
|
||||
if err := ValidateMicroserviceVersion(constants.BinaryVersion(), c.MicroserviceVersion); err != nil {
|
||||
msg := "microserviceVersion: " + msgFromCompatibilityError(err, constants.BinaryVersion().String(), c.MicroserviceVersion.String())
|
||||
return &ValidationError{validationErrMsgs: []string{msg}}
|
||||
}
|
||||
|
@ -690,7 +690,8 @@ func msgFromCompatibilityError(err error, binaryVersion, fieldValue string) stri
|
||||
}
|
||||
}
|
||||
|
||||
func validateMicroserviceVersion(binaryVersion, version consemver.Semver) error {
|
||||
// ValidateMicroserviceVersion checks that the version of the microservice is compatible with the binary version.
|
||||
func ValidateMicroserviceVersion(binaryVersion, version consemver.Semver) error {
|
||||
// Major versions always have to match.
|
||||
if binaryVersion.Major() != version.Major() {
|
||||
return compatibility.ErrMajorMismatch
|
||||
|
@ -75,7 +75,7 @@ func TestValidateMicroserviceVersion(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
err := validateMicroserviceVersion(tc.cli, tc.services)
|
||||
err := ValidateMicroserviceVersion(tc.cli, tc.services)
|
||||
if tc.wantError {
|
||||
assert.Error(err)
|
||||
return
|
||||
|
@ -93,7 +93,11 @@ go_test(
|
||||
"//internal/attestation/variant",
|
||||
"//internal/config",
|
||||
"//internal/constants",
|
||||
"//internal/semver",
|
||||
"//terraform-provider-constellation/internal/data",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//attr",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//providerserver",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//types/basetypes",
|
||||
"@com_github_hashicorp_terraform_plugin_go//tfprotov6",
|
||||
"@com_github_hashicorp_terraform_plugin_testing//helper/resource",
|
||||
"@com_github_hashicorp_terraform_plugin_testing//terraform",
|
||||
|
@ -722,20 +722,11 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
|
||||
}
|
||||
|
||||
// parse OS image version
|
||||
var image imageAttribute
|
||||
convertDiags = data.Image.As(ctx, &image, basetypes.ObjectAsOptions{})
|
||||
image, imageSemver, convertDiags := r.getImageVersion(ctx, data)
|
||||
diags.Append(convertDiags...)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
imageSemver, err := semver.New(image.Version)
|
||||
if err != nil {
|
||||
diags.AddAttributeError(
|
||||
path.Root("image").AtName("version"),
|
||||
"Invalid image version",
|
||||
fmt.Sprintf("Parsing image version (%s): %s", image.Version, err))
|
||||
return diags
|
||||
}
|
||||
|
||||
// parse license ID
|
||||
licenseID := data.LicenseID.ValueString()
|
||||
@ -948,6 +939,29 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
|
||||
return diags
|
||||
}
|
||||
|
||||
func (r *ClusterResource) getImageVersion(ctx context.Context, data *ClusterResourceModel) (imageAttribute, semver.Semver, diag.Diagnostics) {
|
||||
var image imageAttribute
|
||||
diags := data.Image.As(ctx, &image, basetypes.ObjectAsOptions{})
|
||||
if diags.HasError() {
|
||||
return imageAttribute{}, semver.Semver{}, diags
|
||||
}
|
||||
imageSemver, err := semver.New(image.Version)
|
||||
if err != nil {
|
||||
diags.AddAttributeError(
|
||||
path.Root("image").AtName("version"),
|
||||
"Invalid image version",
|
||||
fmt.Sprintf("Parsing image version (%s): %s", image.Version, err))
|
||||
return imageAttribute{}, semver.Semver{}, diags
|
||||
}
|
||||
if err := compatibility.BinaryWith(r.providerData.Version.String(), imageSemver.String()); err != nil {
|
||||
diags.AddAttributeError(
|
||||
path.Root("image").AtName("version"),
|
||||
"Invalid image version",
|
||||
fmt.Sprintf("Image version (%s) incompatible with provider version (%s): %s", image.Version, r.providerData.Version.String(), err))
|
||||
}
|
||||
return image, imageSemver, diags
|
||||
}
|
||||
|
||||
// initRPCPayload groups the data required to run the init RPC.
|
||||
type initRPCPayload struct {
|
||||
csp cloudprovider.Provider // cloud service provider the cluster runs on.
|
||||
@ -1178,6 +1192,12 @@ func (r *ClusterResource) getMicroserviceVersion(ctx context.Context, data *Clus
|
||||
tflog.Info(ctx, fmt.Sprintf("No Microservice version specified. Using default version %s.", r.providerData.Version))
|
||||
ver = r.providerData.Version
|
||||
}
|
||||
if err := config.ValidateMicroserviceVersion(r.providerData.Version, ver); err != nil {
|
||||
diags.AddAttributeError(
|
||||
path.Root("constellation_microservice_version"),
|
||||
"Invalid microservice version",
|
||||
fmt.Sprintf("Microservice version (%s) incompatible with provider version (%s): %s", ver, r.providerData.Version, err))
|
||||
}
|
||||
return ver, diags
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,104 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/data"
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/terraform"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMicroserviceConstraint(t *testing.T) {
|
||||
sut := &ClusterResource{
|
||||
providerData: data.ProviderData{
|
||||
Version: semver.NewFromInt(2, 15, 0, ""),
|
||||
},
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
version string
|
||||
expectedErrorCount int
|
||||
}{
|
||||
{
|
||||
name: "outdated by 2 minor versions is invalid",
|
||||
version: "v2.13.0",
|
||||
expectedErrorCount: 1,
|
||||
},
|
||||
{
|
||||
name: "outdated by 1 minor is allowed for upgrade",
|
||||
version: "v2.14.0",
|
||||
expectedErrorCount: 0,
|
||||
},
|
||||
{
|
||||
name: "same version is valid",
|
||||
version: "v2.15.0",
|
||||
expectedErrorCount: 0,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, diags := sut.getMicroserviceVersion(context.Background(), &ClusterResourceModel{
|
||||
MicroserviceVersion: basetypes.NewStringValue(tc.version),
|
||||
})
|
||||
require.Equal(t, tc.expectedErrorCount, diags.ErrorsCount())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestViolatedImageConstraint(t *testing.T) {
|
||||
sut := &ClusterResource{
|
||||
providerData: data.ProviderData{
|
||||
Version: semver.NewFromInt(2, 15, 0, ""),
|
||||
},
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
version string
|
||||
expectedErrorCount int
|
||||
}{
|
||||
{
|
||||
name: "outdated by 2 minor versions is invalid",
|
||||
version: "v2.13.0",
|
||||
expectedErrorCount: 1,
|
||||
},
|
||||
{
|
||||
name: "outdated by 1 minor is allowed for upgrade",
|
||||
version: "v2.14.0",
|
||||
expectedErrorCount: 0,
|
||||
},
|
||||
{
|
||||
name: "same version is valid",
|
||||
version: "v2.15.0",
|
||||
expectedErrorCount: 0,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
img := imageAttribute{
|
||||
Version: tc.version,
|
||||
}
|
||||
|
||||
input, diags := basetypes.NewObjectValueFrom(context.Background(), map[string]attr.Type{
|
||||
"version": basetypes.StringType{},
|
||||
"reference": basetypes.StringType{},
|
||||
"short_path": basetypes.StringType{},
|
||||
}, img)
|
||||
require.Equal(t, 0, diags.ErrorsCount())
|
||||
_, _, diags2 := sut.getImageVersion(context.Background(), &ClusterResourceModel{
|
||||
Image: input,
|
||||
})
|
||||
require.Equal(t, tc.expectedErrorCount, diags2.ErrorsCount())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccClusterResourceImports(t *testing.T) {
|
||||
// Set the path to the Terraform binary for acceptance testing when running under Bazel.
|
||||
bazelPreCheck := func() { bazelSetTerraformBinaryPath(t) }
|
||||
|
Loading…
x
Reference in New Issue
Block a user