Extend OpenSearch instance parameters (#443)

* Extend OpenSearch instance parameters

* Fix bug in parameter modelling

* Improve monitoring_instance_id field documentation

* Fix unit test
This commit is contained in:
João Palet 2024-07-02 09:30:47 +01:00 committed by GitHub
parent 7e51a0a5d5
commit 78793f49ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 489 additions and 131 deletions

View file

@ -20,6 +20,7 @@ data "stackit_opensearch_instance" "example" {
```
<!-- schema generated by tfplugindocs -->
## Schema
### Required
@ -42,8 +43,22 @@ data "stackit_opensearch_instance" "example" {
- `version` (String) The service version.
<a id="nestedatt--parameters"></a>
### Nested Schema for `parameters`
Read-Only:
- `sgw_acl` (String)
- `enable_monitoring` (Boolean) Enable monitoring.
- `graphite` (String) If set, monitoring with Graphite will be enabled. Expects the host and port where the Graphite metrics should be sent to (host:port).
- `java_garbage_collector` (String) The garbage collector to use for OpenSearch.
- `java_heapspace` (Number) The amount of memory (in MB) allocated as heap by the JVM for OpenSearch.
- `java_maxmetaspace` (Number) The amount of memory (in MB) used by the JVM to store metadata for OpenSearch.
- `max_disk_threshold` (Number) The maximum disk threshold in MB. If the disk usage exceeds this threshold, the instance will be stopped.
- `metrics_frequency` (Number) The frequency in seconds at which metrics are emitted (in seconds).
- `metrics_prefix` (String) The prefix for the metrics. Could be useful when using Graphite monitoring to prefix the metrics with a certain value, like an API key.
- `monitoring_instance_id` (String) The ID of the STACKIT monitoring instance.
- `plugins` (List of String) List of plugins to install. Must be a supported plugin name. The plugins `repository-s3` and `repository-azure` are enabled by default and cannot be disabled.
- `sgw_acl` (String) Comma separated list of IP networks in CIDR notation which are allowed to access this instance.
- `syslog` (List of String) List of syslog servers to send logs to.
- `tls_ciphers` (List of String) List of TLS ciphers to use.
- `tls_protocols` (String) The TLS protocol to use.

View file

@ -25,6 +25,7 @@ resource "stackit_opensearch_instance" "example" {
```
<!-- schema generated by tfplugindocs -->
## Schema
### Required
@ -50,8 +51,22 @@ resource "stackit_opensearch_instance" "example" {
- `plan_id` (String) The selected plan ID.
<a id="nestedatt--parameters"></a>
### Nested Schema for `parameters`
Optional:
- `sgw_acl` (String)
- `enable_monitoring` (Boolean) Enable monitoring.
- `graphite` (String) If set, monitoring with Graphite will be enabled. Expects the host and port where the Graphite metrics should be sent to (host:port).
- `java_garbage_collector` (String) The garbage collector to use for OpenSearch.
- `java_heapspace` (Number) The amount of memory (in MB) allocated as heap by the JVM for OpenSearch.
- `java_maxmetaspace` (Number) The amount of memory (in MB) used by the JVM to store metadata for OpenSearch.
- `max_disk_threshold` (Number) The maximum disk threshold in MB. If the disk usage exceeds this threshold, the instance will be stopped.
- `metrics_frequency` (Number) The frequency in seconds at which metrics are emitted (in seconds).
- `metrics_prefix` (String) The prefix for the metrics. Could be useful when using Graphite monitoring to prefix the metrics with a certain value, like an API key.
- `monitoring_instance_id` (String) The ID of the STACKIT monitoring instance.
- `plugins` (List of String) List of plugins to install. Must be a supported plugin name. The plugins `repository-s3` and `repository-azure` are enabled by default and cannot be disabled.
- `sgw_acl` (String) Comma separated list of IP networks in CIDR notation which are allowed to access this instance.
- `syslog` (List of String) List of syslog servers to send logs to.
- `tls_ciphers` (List of String) List of TLS ciphers to use.
- `tls_protocols` (String) The TLS protocol to use.

View file

@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
@ -86,6 +87,23 @@ func (r *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
"plan_id": "The selected plan ID.",
}
parametersDescriptions := map[string]string{
"sgw_acl": "Comma separated list of IP networks in CIDR notation which are allowed to access this instance.",
"enable_monitoring": "Enable monitoring.",
"graphite": "If set, monitoring with Graphite will be enabled. Expects the host and port where the Graphite metrics should be sent to (host:port).",
"max_disk_threshold": "The maximum disk threshold in MB. If the disk usage exceeds this threshold, the instance will be stopped.",
"metrics_frequency": "The frequency in seconds at which metrics are emitted (in seconds).",
"metrics_prefix": "The prefix for the metrics. Could be useful when using Graphite monitoring to prefix the metrics with a certain value, like an API key.",
"monitoring_instance_id": "The ID of the STACKIT monitoring instance.",
"java_garbage_collector": "The garbage collector to use for OpenSearch.",
"java_heapspace": "The amount of memory (in MB) allocated as heap by the JVM for OpenSearch.",
"java_maxmetaspace": "The amount of memory (in MB) used by the JVM to store metadata for OpenSearch.",
"plugins": "List of plugins to install. Must be a supported plugin name. The plugins `repository-s3` and `repository-azure` are enabled by default and cannot be disabled.",
"syslog": "List of syslog servers to send logs to.",
"tls_ciphers": "List of TLS ciphers to use.",
"tls_protocols": "The TLS protocol to use.",
}
resp.Schema = schema.Schema{
Description: descriptions["main"],
Attributes: map[string]schema.Attribute{
@ -128,7 +146,63 @@ func (r *instanceDataSource) Schema(_ context.Context, _ datasource.SchemaReques
"parameters": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"sgw_acl": schema.StringAttribute{
Computed: true,
Description: parametersDescriptions["sgw_acl"],
Computed: true,
},
"enable_monitoring": schema.BoolAttribute{
Description: parametersDescriptions["enable_monitoring"],
Computed: true,
},
"graphite": schema.StringAttribute{
Description: parametersDescriptions["graphite"],
Computed: true,
},
"java_garbage_collector": schema.StringAttribute{
Description: parametersDescriptions["java_garbage_collector"],
Computed: true,
},
"java_heapspace": schema.Int64Attribute{
Description: parametersDescriptions["java_heapspace"],
Computed: true,
},
"java_maxmetaspace": schema.Int64Attribute{
Description: parametersDescriptions["java_maxmetaspace"],
Computed: true,
},
"max_disk_threshold": schema.Int64Attribute{
Description: parametersDescriptions["max_disk_threshold"],
Computed: true,
},
"metrics_frequency": schema.Int64Attribute{
Description: parametersDescriptions["metrics_frequency"],
Computed: true,
},
"metrics_prefix": schema.StringAttribute{
Description: parametersDescriptions["metrics_prefix"],
Computed: true,
},
"monitoring_instance_id": schema.StringAttribute{
Description: parametersDescriptions["monitoring_instance_id"],
Computed: true,
},
"plugins": schema.ListAttribute{
ElementType: types.StringType,
Description: parametersDescriptions["plugins"],
Computed: true,
},
"syslog": schema.ListAttribute{
ElementType: types.StringType,
Description: parametersDescriptions["syslog"],
Computed: true,
},
"tls_ciphers": schema.ListAttribute{
ElementType: types.StringType,
Description: parametersDescriptions["tls_ciphers"],
Computed: true,
},
"tls_protocols": schema.StringAttribute{
Description: parametersDescriptions["tls_protocols"],
Computed: true,
},
},
Computed: true,

View file

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"slices"
"strings"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
@ -52,12 +53,38 @@ type Model struct {
// Struct corresponding to DataSourceModel.Parameters
type parametersModel struct {
SgwAcl types.String `tfsdk:"sgw_acl"`
SgwAcl types.String `tfsdk:"sgw_acl"`
EnableMonitoring types.Bool `tfsdk:"enable_monitoring"`
Graphite types.String `tfsdk:"graphite"`
JavaGarbageCollector types.String `tfsdk:"java_garbage_collector"`
JavaHeapspace types.Int64 `tfsdk:"java_heapspace"`
JavaMaxmetaspace types.Int64 `tfsdk:"java_maxmetaspace"`
MaxDiskThreshold types.Int64 `tfsdk:"max_disk_threshold"`
MetricsFrequency types.Int64 `tfsdk:"metrics_frequency"`
MetricsPrefix types.String `tfsdk:"metrics_prefix"`
MonitoringInstanceId types.String `tfsdk:"monitoring_instance_id"`
Plugins types.List `tfsdk:"plugins"`
Syslog types.List `tfsdk:"syslog"`
TlsCiphers types.List `tfsdk:"tls_ciphers"`
TlsProtocols types.String `tfsdk:"tls_protocols"`
}
// Types corresponding to parametersModel
var parametersTypes = map[string]attr.Type{
"sgw_acl": basetypes.StringType{},
"sgw_acl": basetypes.StringType{},
"enable_monitoring": basetypes.BoolType{},
"graphite": basetypes.StringType{},
"java_garbage_collector": basetypes.StringType{},
"java_heapspace": basetypes.Int64Type{},
"java_maxmetaspace": basetypes.Int64Type{},
"max_disk_threshold": basetypes.Int64Type{},
"metrics_frequency": basetypes.Int64Type{},
"metrics_prefix": basetypes.StringType{},
"monitoring_instance_id": basetypes.StringType{},
"plugins": basetypes.ListType{ElemType: types.StringType},
"syslog": basetypes.ListType{ElemType: types.StringType},
"tls_ciphers": basetypes.ListType{ElemType: types.StringType},
"tls_protocols": basetypes.StringType{},
}
// NewInstanceResource is a helper function to simplify the provider implementation.
@ -124,6 +151,23 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
"plan_id": "The selected plan ID.",
}
parametersDescriptions := map[string]string{
"sgw_acl": "Comma separated list of IP networks in CIDR notation which are allowed to access this instance.",
"enable_monitoring": "Enable monitoring.",
"graphite": "If set, monitoring with Graphite will be enabled. Expects the host and port where the Graphite metrics should be sent to (host:port).",
"max_disk_threshold": "The maximum disk threshold in MB. If the disk usage exceeds this threshold, the instance will be stopped.",
"metrics_frequency": "The frequency in seconds at which metrics are emitted (in seconds).",
"metrics_prefix": "The prefix for the metrics. Could be useful when using Graphite monitoring to prefix the metrics with a certain value, like an API key.",
"monitoring_instance_id": "The ID of the STACKIT monitoring instance.",
"java_garbage_collector": "The garbage collector to use for OpenSearch.",
"java_heapspace": "The amount of memory (in MB) allocated as heap by the JVM for OpenSearch.",
"java_maxmetaspace": "The amount of memory (in MB) used by the JVM to store metadata for OpenSearch.",
"plugins": "List of plugins to install. Must be a supported plugin name. The plugins `repository-s3` and `repository-azure` are enabled by default and cannot be disabled.",
"syslog": "List of syslog servers to send logs to.",
"tls_ciphers": "List of TLS ciphers to use.",
"tls_protocols": "The TLS protocol to use.",
}
resp.Schema = schema.Schema{
Description: descriptions["main"],
Attributes: map[string]schema.Attribute{
@ -183,8 +227,77 @@ func (r *instanceResource) Schema(_ context.Context, _ resource.SchemaRequest, r
"parameters": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"sgw_acl": schema.StringAttribute{
Optional: true,
Computed: true,
Description: parametersDescriptions["sgw_acl"],
Optional: true,
Computed: true,
},
"enable_monitoring": schema.BoolAttribute{
Description: parametersDescriptions["enable_monitoring"],
Optional: true,
Computed: true,
},
"graphite": schema.StringAttribute{
Description: parametersDescriptions["graphite"],
Optional: true,
Computed: true,
},
"java_garbage_collector": schema.StringAttribute{
Description: parametersDescriptions["java_garbage_collector"],
Optional: true,
Computed: true,
},
"java_heapspace": schema.Int64Attribute{
Description: parametersDescriptions["java_heapspace"],
Optional: true,
Computed: true,
},
"java_maxmetaspace": schema.Int64Attribute{
Description: parametersDescriptions["java_maxmetaspace"],
Optional: true,
Computed: true,
},
"max_disk_threshold": schema.Int64Attribute{
Description: parametersDescriptions["max_disk_threshold"],
Optional: true,
Computed: true,
},
"metrics_frequency": schema.Int64Attribute{
Description: parametersDescriptions["metrics_frequency"],
Optional: true,
Computed: true,
},
"metrics_prefix": schema.StringAttribute{
Description: parametersDescriptions["metrics_prefix"],
Optional: true,
Computed: true,
},
"monitoring_instance_id": schema.StringAttribute{
Description: parametersDescriptions["monitoring_instance_id"],
Optional: true,
Computed: true,
},
"plugins": schema.ListAttribute{
ElementType: types.StringType,
Description: parametersDescriptions["plugins"],
Optional: true,
Computed: true,
},
"syslog": schema.ListAttribute{
ElementType: types.StringType,
Description: parametersDescriptions["syslog"],
Optional: true,
Computed: true,
},
"tls_ciphers": schema.ListAttribute{
ElementType: types.StringType,
Description: parametersDescriptions["tls_ciphers"],
Optional: true,
Computed: true,
},
"tls_protocols": schema.StringAttribute{
Description: parametersDescriptions["tls_protocols"],
Optional: true,
Computed: true,
},
},
Optional: true,
@ -235,8 +348,9 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
var parameters = &parametersModel{}
var parameters *parametersModel
if !(model.Parameters.IsNull() || model.Parameters.IsUnknown()) {
parameters = &parametersModel{}
diags = model.Parameters.As(ctx, parameters, basetypes.ObjectAsOptions{})
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
@ -346,8 +460,9 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
var parameters = &parametersModel{}
var parameters *parametersModel
if !(model.Parameters.IsNull() || model.Parameters.IsUnknown()) {
parameters := &parametersModel{}
diags = model.Parameters.As(ctx, parameters, basetypes.ObjectAsOptions{})
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
@ -488,7 +603,22 @@ func mapFields(instance *opensearch.Instance, model *Model) error {
func mapParameters(params map[string]interface{}) (types.Object, error) {
attributes := map[string]attr.Value{}
for attribute := range parametersTypes {
valueInterface, ok := params[attribute]
var valueInterface interface{}
var ok bool
// This replacement is necessary because Terraform does not allow hyphens in attribute names
// And the API uses hyphens in some of the attribute names, which would cause a mismatch
// The following attributes have hyphens in the API but underscores in the schema
hyphenAttributes := []string{
"tls_ciphers",
"tls_protocols",
}
if slices.Contains(hyphenAttributes, attribute) {
alteredAttribute := strings.ReplaceAll(attribute, "_", "-")
valueInterface, ok = params[alteredAttribute]
} else {
valueInterface, ok = params[attribute]
}
if !ok {
// All fields are optional, so this is ok
// Set the value as nil, will be handled accordingly
@ -584,15 +714,9 @@ func toCreatePayload(model *Model, parameters *parametersModel) (*opensearch.Cre
if model == nil {
return nil, fmt.Errorf("nil model")
}
if parameters == nil {
return &opensearch.CreateInstancePayload{
InstanceName: conversion.StringValueToPointer(model.Name),
PlanId: conversion.StringValueToPointer(model.PlanId),
}, nil
}
payloadParams := &opensearch.InstanceParameters{}
if parameters.SgwAcl.ValueString() != "" {
payloadParams.SgwAcl = conversion.StringValueToPointer(parameters.SgwAcl)
payloadParams, err := toInstanceParams(parameters)
if err != nil {
return nil, fmt.Errorf("convert parameters: %w", err)
}
return &opensearch.CreateInstancePayload{
InstanceName: conversion.StringValueToPointer(model.Name),
@ -605,20 +729,53 @@ func toUpdatePayload(model *Model, parameters *parametersModel) (*opensearch.Par
if model == nil {
return nil, fmt.Errorf("nil model")
}
if parameters == nil {
return &opensearch.PartialUpdateInstancePayload{
PlanId: conversion.StringValueToPointer(model.PlanId),
}, nil
payloadParams, err := toInstanceParams(parameters)
if err != nil {
return nil, fmt.Errorf("convert parameters: %w", err)
}
return &opensearch.PartialUpdateInstancePayload{
Parameters: &opensearch.InstanceParameters{
SgwAcl: conversion.StringValueToPointer(parameters.SgwAcl),
},
PlanId: conversion.StringValueToPointer(model.PlanId),
Parameters: payloadParams,
PlanId: conversion.StringValueToPointer(model.PlanId),
}, nil
}
func toInstanceParams(parameters *parametersModel) (*opensearch.InstanceParameters, error) {
if parameters == nil {
return nil, nil
}
payloadParams := &opensearch.InstanceParameters{}
payloadParams.SgwAcl = conversion.StringValueToPointer(parameters.SgwAcl)
payloadParams.EnableMonitoring = conversion.BoolValueToPointer(parameters.EnableMonitoring)
payloadParams.Graphite = conversion.StringValueToPointer(parameters.Graphite)
payloadParams.JavaGarbageCollector = conversion.StringValueToPointer(parameters.JavaGarbageCollector)
payloadParams.JavaHeapspace = conversion.Int64ValueToPointer(parameters.JavaHeapspace)
payloadParams.JavaMaxmetaspace = conversion.Int64ValueToPointer(parameters.JavaMaxmetaspace)
payloadParams.MaxDiskThreshold = conversion.Int64ValueToPointer(parameters.MaxDiskThreshold)
payloadParams.MetricsFrequency = conversion.Int64ValueToPointer(parameters.MetricsFrequency)
payloadParams.MetricsPrefix = conversion.StringValueToPointer(parameters.MetricsPrefix)
payloadParams.MonitoringInstanceId = conversion.StringValueToPointer(parameters.MonitoringInstanceId)
payloadParams.TlsProtocols = conversion.StringValueToPointer(parameters.TlsProtocols)
var err error
payloadParams.Plugins, err = conversion.StringListToPointer(parameters.Plugins)
if err != nil {
return nil, fmt.Errorf("convert plugins: %w", err)
}
payloadParams.Syslog, err = conversion.StringListToPointer(parameters.Syslog)
if err != nil {
return nil, fmt.Errorf("convert syslog: %w", err)
}
payloadParams.TlsCiphers, err = conversion.StringListToPointer(parameters.TlsCiphers)
if err != nil {
return nil, fmt.Errorf("convert tls_ciphers: %w", err)
}
return payloadParams, nil
}
func (r *instanceResource) loadPlanId(ctx context.Context, model *Model) error {
projectId := model.ProjectId.ValueString()
res, err := r.client.ListOfferings(ctx, projectId).Execute()

View file

@ -1,15 +1,77 @@
package opensearch
import (
"context"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/opensearch"
)
var fixtureModelParameters = types.ObjectValueMust(parametersTypes, map[string]attr.Value{
"sgw_acl": types.StringValue("acl"),
"enable_monitoring": types.BoolValue(true),
"graphite": types.StringValue("graphite"),
"java_garbage_collector": types.StringValue("gc"),
"java_heapspace": types.Int64Value(10),
"java_maxmetaspace": types.Int64Value(10),
"max_disk_threshold": types.Int64Value(10),
"metrics_frequency": types.Int64Value(10),
"metrics_prefix": types.StringValue("prefix"),
"monitoring_instance_id": types.StringValue("mid"),
"plugins": types.ListValueMust(types.StringType, []attr.Value{
types.StringValue("plugin"),
types.StringValue("plugin2"),
}),
"syslog": types.ListValueMust(types.StringType, []attr.Value{
types.StringValue("syslog"),
types.StringValue("syslog2"),
}),
"tls_ciphers": types.ListValueMust(types.StringType, []attr.Value{
types.StringValue("cipher"),
types.StringValue("cipher2"),
}),
"tls_protocols": types.StringValue("protocol"),
})
var fixtureNullModelParameters = types.ObjectValueMust(parametersTypes, map[string]attr.Value{
"sgw_acl": types.StringNull(),
"enable_monitoring": types.BoolNull(),
"graphite": types.StringNull(),
"java_garbage_collector": types.StringNull(),
"java_heapspace": types.Int64Null(),
"java_maxmetaspace": types.Int64Null(),
"max_disk_threshold": types.Int64Null(),
"metrics_frequency": types.Int64Null(),
"metrics_prefix": types.StringNull(),
"monitoring_instance_id": types.StringNull(),
"plugins": types.ListNull(types.StringType),
"syslog": types.ListNull(types.StringType),
"tls_ciphers": types.ListNull(types.StringType),
"tls_protocols": types.StringNull(),
})
var fixtureInstanceParameters = opensearch.InstanceParameters{
SgwAcl: utils.Ptr("acl"),
EnableMonitoring: utils.Ptr(true),
Graphite: utils.Ptr("graphite"),
JavaGarbageCollector: utils.Ptr("gc"),
JavaHeapspace: utils.Ptr(int64(10)),
JavaMaxmetaspace: utils.Ptr(int64(10)),
MaxDiskThreshold: utils.Ptr(int64(10)),
MetricsFrequency: utils.Ptr(int64(10)),
MetricsPrefix: utils.Ptr("prefix"),
MonitoringInstanceId: utils.Ptr("mid"),
Plugins: &[]string{"plugin", "plugin2"},
Syslog: &[]string{"syslog", "syslog2"},
TlsCiphers: &[]string{"cipher", "cipher2"},
TlsProtocols: utils.Ptr("protocol"),
}
func TestMapFields(t *testing.T) {
tests := []struct {
description string
@ -47,7 +109,21 @@ func TestMapFields(t *testing.T) {
Name: utils.Ptr("name"),
CfOrganizationGuid: utils.Ptr("org"),
Parameters: &map[string]interface{}{
"sgw_acl": "acl",
// Using "-" on purpose on some fields because that is the API response
"sgw_acl": "acl",
"enable_monitoring": true,
"graphite": "graphite",
"java_garbage_collector": "gc",
"java_heapspace": int64(10),
"java_maxmetaspace": int64(10),
"max_disk_threshold": int64(10),
"metrics_frequency": int64(10),
"metrics_prefix": "prefix",
"monitoring_instance_id": "mid",
"plugins": []string{"plugin", "plugin2"},
"syslog": []string{"syslog", "syslog2"},
"tls-ciphers": []string{"cipher", "cipher2"},
"tls-protocols": "protocol",
},
},
Model{
@ -61,9 +137,7 @@ func TestMapFields(t *testing.T) {
DashboardUrl: types.StringValue("dashboard"),
ImageUrl: types.StringValue("image"),
CfOrganizationGuid: types.StringValue("org"),
Parameters: types.ObjectValueMust(parametersTypes, map[string]attr.Value{
"sgw_acl": types.StringValue("acl"),
}),
Parameters: fixtureModelParameters,
},
true,
},
@ -125,61 +199,48 @@ func TestMapFields(t *testing.T) {
func TestToCreatePayload(t *testing.T) {
tests := []struct {
description string
input *Model
inputParameters *parametersModel
expected *opensearch.CreateInstancePayload
isValid bool
description string
input *Model
expected *opensearch.CreateInstancePayload
isValid bool
}{
{
"default_values",
&Model{},
&parametersModel{},
&opensearch.CreateInstancePayload{
Parameters: &opensearch.InstanceParameters{},
},
&opensearch.CreateInstancePayload{},
true,
},
{
"simple_values",
&Model{
Name: types.StringValue("name"),
PlanId: types.StringValue("plan"),
},
&parametersModel{
SgwAcl: types.StringValue("sgw"),
Name: types.StringValue("name"),
PlanId: types.StringValue("plan"),
Parameters: fixtureModelParameters,
},
&opensearch.CreateInstancePayload{
InstanceName: utils.Ptr("name"),
Parameters: &opensearch.InstanceParameters{
SgwAcl: utils.Ptr("sgw"),
},
PlanId: utils.Ptr("plan"),
Parameters: &fixtureInstanceParameters,
PlanId: utils.Ptr("plan"),
},
true,
},
{
"null_fields_and_int_conversions",
&Model{
Name: types.StringValue(""),
PlanId: types.StringValue(""),
},
&parametersModel{
SgwAcl: types.StringNull(),
Name: types.StringValue(""),
PlanId: types.StringValue(""),
Parameters: fixtureNullModelParameters,
},
&opensearch.CreateInstancePayload{
InstanceName: utils.Ptr(""),
Parameters: &opensearch.InstanceParameters{
SgwAcl: nil,
},
PlanId: utils.Ptr(""),
Parameters: &opensearch.InstanceParameters{},
PlanId: utils.Ptr(""),
},
true,
},
{
"nil_model",
nil,
&parametersModel{},
nil,
false,
},
@ -189,7 +250,6 @@ func TestToCreatePayload(t *testing.T) {
Name: types.StringValue("name"),
PlanId: types.StringValue("plan"),
},
nil,
&opensearch.CreateInstancePayload{
InstanceName: utils.Ptr("name"),
PlanId: utils.Ptr("plan"),
@ -199,7 +259,17 @@ func TestToCreatePayload(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
output, err := toCreatePayload(tt.input, tt.inputParameters)
var parameters *parametersModel
if tt.input != nil {
if !(tt.input.Parameters.IsNull() || tt.input.Parameters.IsUnknown()) {
parameters = &parametersModel{}
diags := tt.input.Parameters.As(context.Background(), parameters, basetypes.ObjectAsOptions{})
if diags.HasError() {
t.Fatalf("Error converting parameters: %v", diags.Errors())
}
}
}
output, err := toCreatePayload(tt.input, parameters)
if !tt.isValid && err == nil {
t.Fatalf("Should have failed")
}
@ -218,57 +288,44 @@ func TestToCreatePayload(t *testing.T) {
func TestToUpdatePayload(t *testing.T) {
tests := []struct {
description string
input *Model
inputParameters *parametersModel
expected *opensearch.PartialUpdateInstancePayload
isValid bool
description string
input *Model
expected *opensearch.PartialUpdateInstancePayload
isValid bool
}{
{
"default_values",
&Model{},
&parametersModel{},
&opensearch.PartialUpdateInstancePayload{
Parameters: &opensearch.InstanceParameters{},
},
&opensearch.PartialUpdateInstancePayload{},
true,
},
{
"simple_values",
&Model{
PlanId: types.StringValue("plan"),
},
&parametersModel{
SgwAcl: types.StringValue("sgw"),
PlanId: types.StringValue("plan"),
Parameters: fixtureModelParameters,
},
&opensearch.PartialUpdateInstancePayload{
Parameters: &opensearch.InstanceParameters{
SgwAcl: utils.Ptr("sgw"),
},
PlanId: utils.Ptr("plan"),
Parameters: &fixtureInstanceParameters,
PlanId: utils.Ptr("plan"),
},
true,
},
{
"null_fields_and_int_conversions",
&Model{
PlanId: types.StringValue(""),
},
&parametersModel{
SgwAcl: types.StringNull(),
PlanId: types.StringValue(""),
Parameters: fixtureNullModelParameters,
},
&opensearch.PartialUpdateInstancePayload{
Parameters: &opensearch.InstanceParameters{
SgwAcl: nil,
},
PlanId: utils.Ptr(""),
Parameters: &opensearch.InstanceParameters{},
PlanId: utils.Ptr(""),
},
true,
},
{
"nil_model",
nil,
&parametersModel{},
nil,
false,
},
@ -277,7 +334,6 @@ func TestToUpdatePayload(t *testing.T) {
&Model{
PlanId: types.StringValue("plan"),
},
nil,
&opensearch.PartialUpdateInstancePayload{
PlanId: utils.Ptr("plan"),
},
@ -286,7 +342,17 @@ func TestToUpdatePayload(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
output, err := toUpdatePayload(tt.input, tt.inputParameters)
var parameters *parametersModel
if tt.input != nil {
if !(tt.input.Parameters.IsNull() || tt.input.Parameters.IsUnknown()) {
parameters = &parametersModel{}
diags := tt.input.Parameters.As(context.Background(), parameters, basetypes.ObjectAsOptions{})
if diags.HasError() {
t.Fatalf("Error converting parameters: %v", diags.Errors())
}
}
}
output, err := toUpdatePayload(tt.input, parameters)
if !tt.isValid && err == nil {
t.Fatalf("Should have failed")
}

View file

@ -18,15 +18,42 @@ import (
// Instance resource data
var instanceResource = map[string]string{
"project_id": testutil.ProjectId,
"name": testutil.ResourceNameWithDateTime("opensearch"),
"plan_id": "9e4eac4b-b03d-4d7b-b01b-6d1224aa2d68",
"plan_name": "stackit-opensearch-1.2.10-replica",
"version": "2",
"sgw_acl": "192.168.0.0/24",
"project_id": testutil.ProjectId,
"name": testutil.ResourceNameWithDateTime("opensearch"),
"plan_id": "9e4eac4b-b03d-4d7b-b01b-6d1224aa2d68",
"plan_name": "stackit-opensearch-1.2.10-replica",
"version": "2",
"sgw_acl-1": "192.168.0.0/16",
"sgw_acl-2": "192.168.0.0/24",
"max_disk_threshold": "80",
"enable_monitoring": "false",
"syslog-0": "syslog.example.com:514",
}
func resourceConfig() string {
func parametersConfig(params map[string]string) string {
nonStringParams := []string{
"enable_monitoring",
"max_disk_threshold",
"metrics_frequency",
"java_heapspace",
"java_maxmetaspace",
"plugins",
"syslog",
"tls_ciphers",
}
parameters := "parameters = {"
for k, v := range params {
if utils.Contains(nonStringParams, k) {
parameters += fmt.Sprintf("%s = %s\n", k, v)
} else {
parameters += fmt.Sprintf("%s = %q\n", k, v)
}
}
parameters += "\n}"
return parameters
}
func resourceConfig(params map[string]string) string {
return fmt.Sprintf(`
%s
@ -35,6 +62,7 @@ func resourceConfig() string {
name = "%s"
plan_name = "%s"
version = "%s"
%s
}
resource "stackit_opensearch_credential" "credential" {
@ -47,34 +75,7 @@ func resourceConfig() string {
instanceResource["name"],
instanceResource["plan_name"],
instanceResource["version"],
)
}
func resourceConfigUpdate() string {
return fmt.Sprintf(`
%s
resource "stackit_opensearch_instance" "instance" {
project_id = "%s"
name = "%s"
plan_name = "%s"
version = "%s"
parameters = {
sgw_acl = "%s"
}
}
resource "stackit_opensearch_credential" "credential" {
project_id = stackit_opensearch_instance.instance.project_id
instance_id = stackit_opensearch_instance.instance.instance_id
}
`,
testutil.OpenSearchProviderConfig(),
instanceResource["project_id"],
instanceResource["name"],
instanceResource["plan_name"],
instanceResource["version"],
instanceResource["sgw_acl"],
parametersConfig(params),
)
}
@ -86,7 +87,13 @@ func TestAccOpenSearchResource(t *testing.T) {
// Creation
{
Config: resourceConfig(),
Config: resourceConfig(
map[string]string{
"sgw_acl": instanceResource["sgw_acl-1"],
"max_disk_threshold": instanceResource["max_disk_threshold"],
"enable_monitoring": instanceResource["enable_monitoring"],
"syslog": fmt.Sprintf(`[%q]`, instanceResource["syslog-0"]),
}),
Check: resource.ComposeAggregateTestCheckFunc(
// Instance data
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "project_id", instanceResource["project_id"]),
@ -95,7 +102,11 @@ func TestAccOpenSearchResource(t *testing.T) {
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "plan_name", instanceResource["plan_name"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "version", instanceResource["version"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "name", instanceResource["name"]),
resource.TestCheckResourceAttrSet("stackit_opensearch_instance.instance", "parameters.sgw_acl"),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.sgw_acl", instanceResource["sqw_acl-1"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.max_disk_threshold", instanceResource["max_disk_threshold"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.enable_monitoring", instanceResource["enable_monitoring"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.syslog.#", "1"),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.syslog.0", instanceResource["syslog-0"]),
// Credential data
resource.TestCheckResourceAttrPair(
@ -125,7 +136,13 @@ func TestAccOpenSearchResource(t *testing.T) {
instance_id = stackit_opensearch_credential.credential.instance_id
credential_id = stackit_opensearch_credential.credential.credential_id
}`,
resourceConfig(),
resourceConfig(
map[string]string{
"sgw_acl": instanceResource["sgw_acl-1"],
"max_disk_threshold": instanceResource["max_disk_threshold"],
"enable_monitoring": instanceResource["enable_monitoring"],
"syslog": fmt.Sprintf(`[%q]`, instanceResource["syslog-0"]),
}),
),
Check: resource.ComposeAggregateTestCheckFunc(
// Instance data
@ -136,7 +153,11 @@ func TestAccOpenSearchResource(t *testing.T) {
"data.stackit_opensearch_credential.credential", "credential_id"),
resource.TestCheckResourceAttr("data.stackit_opensearch_instance.instance", "plan_id", instanceResource["plan_id"]),
resource.TestCheckResourceAttr("data.stackit_opensearch_instance.instance", "name", instanceResource["name"]),
resource.TestCheckResourceAttrSet("data.stackit_opensearch_instance.instance", "parameters.sgw_acl"),
resource.TestCheckResourceAttr("data.stackit_opensearch_instance.instance", "parameters.sgw_acl", instanceResource["sqw_acl-1"]),
resource.TestCheckResourceAttr("data.stackit_opensearch_instance.instance", "parameters.max_disk_threshold", instanceResource["max_disk_threshold"]),
resource.TestCheckResourceAttr("data.stackit_opensearch_instance.instance", "parameters.enable_monitoring", instanceResource["enable_monitoring"]),
resource.TestCheckResourceAttr("data.stackit_opensearch_instance.instance", "parameters.syslog.#", "1"),
resource.TestCheckResourceAttr("data.stackit_opensearch_instance.instance", "parameters.syslog.0", instanceResource["syslog-0"]),
// Credential data
resource.TestCheckResourceAttr("data.stackit_opensearch_credential.credential", "project_id", instanceResource["project_id"]),
@ -187,7 +208,13 @@ func TestAccOpenSearchResource(t *testing.T) {
},
// Update
{
Config: resourceConfigUpdate(),
Config: resourceConfig(
map[string]string{
"sgw_acl": instanceResource["sgw_acl-2"],
"max_disk_threshold": instanceResource["max_disk_threshold"],
"enable_monitoring": instanceResource["enable_monitoring"],
"syslog": fmt.Sprintf(`[%q]`, instanceResource["syslog-0"]),
}),
Check: resource.ComposeAggregateTestCheckFunc(
// Instance data
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "project_id", instanceResource["project_id"]),
@ -196,7 +223,11 @@ func TestAccOpenSearchResource(t *testing.T) {
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "plan_name", instanceResource["plan_name"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "version", instanceResource["version"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "name", instanceResource["name"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.sgw_acl", instanceResource["sgw_acl"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.sgw_acl", instanceResource["sqw_acl-2"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.max_disk_threshold", instanceResource["max_disk_threshold"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.enable_monitoring", instanceResource["enable_monitoring"]),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.syslog.#", "1"),
resource.TestCheckResourceAttr("stackit_opensearch_instance.instance", "parameters.syslog.0", instanceResource["syslog-0"]),
),
},
// Deletion is done by the framework implicitly