diff --git a/go.mod b/go.mod index ed58bc584..0bc80780a 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/go-version v1.7.0 github.com/hashicorp/terraform-plugin-framework v1.13.0 - github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 github.com/hashicorp/terraform-plugin-go v0.25.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-mux v0.16.0 diff --git a/go.sum b/go.sum index 0ca2ada7a..8b6a16a35 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7 github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw= github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= -github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 h1:RXMmu7JgpFjnI1a5QjMCBb11usrW2OtAG+iOTIj5c9Y= -github.com/hashicorp/terraform-plugin-framework-validators v0.15.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= +github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 h1:O9QqGoYDzQT7lwTXUsZEtgabeWW96zUBh47Smn2lkFA= +github.com/hashicorp/terraform-plugin-framework-validators v0.16.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= github.com/hashicorp/terraform-plugin-go v0.25.0 h1:oi13cx7xXA6QciMcpcFi/rwA974rdTxjqEhXJjbAyks= github.com/hashicorp/terraform-plugin-go v0.25.0/go.mod h1:+SYagMYadJP86Kvn+TGeV+ofr/R3g4/If0O5sO96MVw= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= diff --git a/ovh/data_dbaas_logs_cluster_retention.go b/ovh/data_dbaas_logs_cluster_retention.go index 6024bf593..bbc571753 100644 --- a/ovh/data_dbaas_logs_cluster_retention.go +++ b/ovh/data_dbaas_logs_cluster_retention.go @@ -7,6 +7,8 @@ import ( "strings" "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-log/tflog" + ovhtypes "github.com/ovh/terraform-provider-ovh/ovh/types" ) var _ datasource.DataSourceWithConfigure = (*dbaasLogsClusterRetentionDataSource)(nil) @@ -75,7 +77,7 @@ func (d *dbaasLogsClusterRetentionDataSource) Read(ctx context.Context, req data return } - // No retention ID given, try to fetch a retention with given duration + // No retention ID given, try to fetch a retention with given type and duration var ( retentionIDs []string availableDurations []string @@ -87,6 +89,12 @@ func (d *dbaasLogsClusterRetentionDataSource) Read(ctx context.Context, req data return } + // If no retention_type given, default on LOGS_INDEXING value + if data.RetentionType.IsNull() { + tflog.Info(ctx, "no retention type defined, defaulting to LOGS_INDEXING") + data.RetentionType = ovhtypes.NewTfStringValue("LOGS_INDEXING") + } + for _, id := range retentionIDs { var ( retentionData DbaasLogsClusterRetentionModel @@ -98,6 +106,16 @@ func (d *dbaasLogsClusterRetentionDataSource) Read(ctx context.Context, req data return } + if !data.RetentionType.Equal(retentionData.RetentionType) { + tflog.Info(ctx, fmt.Sprintf("skipping retention %s with wrong type %s", retentionData.RetentionId, retentionData.RetentionType)) + continue + } + + if !retentionData.IsSupported.ValueBool() { + tflog.Info(ctx, fmt.Sprintf("skipping retention %s as it is not supported", retentionData.RetentionId)) + continue + } + availableDurations = append(availableDurations, retentionData.Duration.ValueString()) if data.Duration.Equal(retentionData.Duration) { data.MergeWith(&retentionData) @@ -108,7 +126,11 @@ func (d *dbaasLogsClusterRetentionDataSource) Read(ctx context.Context, req data } } - // No retention found with given duration, error + // No retention found with given duration and type, error + errorDetails := "" + if len(availableDurations) > 0 { + errorDetails = ", available values are: " + strings.Join(availableDurations, ",") + } resp.Diagnostics.AddError("retention not found", - fmt.Sprintf("no retention was found with duration %s, available values are: %s", data.Duration.ValueString(), strings.Join(availableDurations, ","))) + fmt.Sprintf("no retention was found with duration %s and type %s%s", data.Duration.ValueString(), data.RetentionType.ValueString(), errorDetails)) } diff --git a/ovh/data_dbaas_logs_cluster_retention_gen.go b/ovh/data_dbaas_logs_cluster_retention_gen.go index ec0255bb2..ada0fb734 100644 --- a/ovh/data_dbaas_logs_cluster_retention_gen.go +++ b/ovh/data_dbaas_logs_cluster_retention_gen.go @@ -5,7 +5,10 @@ package ovh import ( "context" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" ovhtypes "github.com/ovh/terraform-provider-ovh/ovh/types" ) @@ -18,9 +21,12 @@ func DbaasLogsClusterRetentionDataSourceSchema(ctx context.Context) schema.Schem MarkdownDescription: "Cluster ID", }, "duration": schema.StringAttribute{ - CustomType: ovhtypes.TfStringType{}, - Computed: true, - Optional: true, + CustomType: ovhtypes.TfStringType{}, + Computed: true, + Optional: true, + Validators: []validator.String{ + stringvalidator.ConflictsWith(path.MatchRoot("retention_id")), + }, Description: "Indexed duration expressed in ISO-8601 format", MarkdownDescription: "Indexed duration expressed in ISO-8601 format", }, @@ -31,11 +37,30 @@ func DbaasLogsClusterRetentionDataSourceSchema(ctx context.Context) schema.Schem MarkdownDescription: "Indicates if a new stream can use it", }, "retention_id": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Computed: true, + Optional: true, + Validators: []validator.String{ + stringvalidator.ConflictsWith(path.MatchRoot("duration")), + stringvalidator.ConflictsWith(path.MatchRoot("retention_type")), + }, + Description: "Retention ID", + MarkdownDescription: "Retention ID", + }, + "retention_type": schema.StringAttribute{ CustomType: ovhtypes.TfStringType{}, Computed: true, Optional: true, - Description: "Retention ID", - MarkdownDescription: "Retention ID", + Description: "Retention type", + MarkdownDescription: "Retention type", + Validators: []validator.String{ + stringvalidator.OneOf( + "LOGS_COLD_STORAGE", + "LOGS_INDEXING", + "METRICS_TENANT", + ), + stringvalidator.ConflictsWith(path.MatchRoot("retention_id")), + }, }, "service_name": schema.StringAttribute{ CustomType: ovhtypes.TfStringType{}, @@ -51,11 +76,12 @@ func DbaasLogsClusterRetentionDataSourceSchema(ctx context.Context) schema.Schem } type DbaasLogsClusterRetentionModel struct { - ClusterId ovhtypes.TfStringValue `tfsdk:"cluster_id" json:"clusterId"` - Duration ovhtypes.TfStringValue `tfsdk:"duration" json:"duration"` - IsSupported ovhtypes.TfBoolValue `tfsdk:"is_supported" json:"isSupported"` - RetentionId ovhtypes.TfStringValue `tfsdk:"retention_id" json:"retentionId"` - ServiceName ovhtypes.TfStringValue `tfsdk:"service_name" json:"serviceName"` + ClusterId ovhtypes.TfStringValue `tfsdk:"cluster_id" json:"clusterId"` + Duration ovhtypes.TfStringValue `tfsdk:"duration" json:"duration"` + IsSupported ovhtypes.TfBoolValue `tfsdk:"is_supported" json:"isSupported"` + RetentionId ovhtypes.TfStringValue `tfsdk:"retention_id" json:"retentionId"` + RetentionType ovhtypes.TfStringValue `tfsdk:"retention_type" json:"retentionType"` + ServiceName ovhtypes.TfStringValue `tfsdk:"service_name" json:"serviceName"` } func (v *DbaasLogsClusterRetentionModel) MergeWith(other *DbaasLogsClusterRetentionModel) { @@ -75,6 +101,10 @@ func (v *DbaasLogsClusterRetentionModel) MergeWith(other *DbaasLogsClusterRetent v.RetentionId = other.RetentionId } + if (v.RetentionType.IsUnknown() || v.RetentionType.IsNull()) && !other.RetentionType.IsUnknown() { + v.RetentionType = other.RetentionType + } + if (v.ServiceName.IsUnknown() || v.ServiceName.IsNull()) && !other.ServiceName.IsUnknown() { v.ServiceName = other.ServiceName } diff --git a/ovh/data_dbaas_logs_cluster_retention_test.go b/ovh/data_dbaas_logs_cluster_retention_test.go index 4acf8257c..93e231572 100644 --- a/ovh/data_dbaas_logs_cluster_retention_test.go +++ b/ovh/data_dbaas_logs_cluster_retention_test.go @@ -47,6 +47,11 @@ func TestAccDataSourceDbaasLogsClusterRetention_basic(t *testing.T) { "is_supported", "true", ), + resource.TestCheckResourceAttr( + "data.ovh_dbaas_logs_cluster_retention.ret", + "retention_type", + "LOGS_INDEXING", + ), ), }, }, @@ -90,6 +95,60 @@ func TestAccDataSourceDbaasLogsClusterRetention_by_duration(t *testing.T) { "is_supported", "true", ), + resource.TestCheckResourceAttr( + "data.ovh_dbaas_logs_cluster_retention.ret", + "retention_type", + "LOGS_INDEXING", + ), + ), + }, + }, + }) +} + +func TestAccDataSourceDbaasLogsClusterRetention_by_duration_and_type(t *testing.T) { + serviceName := os.Getenv("OVH_DBAAS_LOGS_SERVICE_TEST") + clusterId := os.Getenv("OVH_DBAAS_LOGS_CLUSTER_ID") + retentionId := os.Getenv("OVH_DBAAS_LOGS_CLUSTER_RETENTION_ID") + + config := fmt.Sprintf(` + data "ovh_dbaas_logs_cluster_retention" "ret" { + service_name = "%s" + cluster_id = "%s" + duration = "P1Y" + retention_type = "LOGS_INDEXING" + }`, + serviceName, + clusterId, + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckDbaasLogsClusterRetention(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.ovh_dbaas_logs_cluster_retention.ret", + "service_name", + serviceName, + ), + resource.TestCheckResourceAttr( + "data.ovh_dbaas_logs_cluster_retention.ret", + "retention_id", + retentionId, + ), + resource.TestCheckResourceAttr( + "data.ovh_dbaas_logs_cluster_retention.ret", + "is_supported", + "true", + ), + resource.TestCheckResourceAttr( + "data.ovh_dbaas_logs_cluster_retention.ret", + "retention_type", + "LOGS_INDEXING", + ), ), }, }, @@ -116,7 +175,34 @@ func TestAccDataSourceDbaasLogsClusterRetention_by_duration_not_found(t *testing Steps: []resource.TestStep{ { Config: config, - ExpectError: regexp.MustCompile("no retention was found with duration P1000Y"), + ExpectError: regexp.MustCompile("no retention was found with duration P1000Y and type LOGS_INDEXING"), + }, + }, + }) +} + +func TestAccDataSourceDbaasLogsClusterRetention_by_duration_and_type_not_found(t *testing.T) { + serviceName := os.Getenv("OVH_DBAAS_LOGS_SERVICE_TEST") + clusterId := os.Getenv("OVH_DBAAS_LOGS_CLUSTER_ID") + + config := fmt.Sprintf(` + data "ovh_dbaas_logs_cluster_retention" "ret" { + service_name = "%s" + cluster_id = "%s" + duration = "P1Y" + retention_type = "METRICS_TENANT" + }`, + serviceName, + clusterId, + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckDbaasLogsClusterRetention(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: config, + ExpectError: regexp.MustCompile("no retention was found with duration P1Y and type METRICS_TENANT"), }, }, }) @@ -146,3 +232,32 @@ func TestAccDataSourceDbaasLogsClusterRetention_missing_params(t *testing.T) { }, }) } + +func TestAccDataSourceDbaasLogsClusterRetention_invalid_params(t *testing.T) { + serviceName := os.Getenv("OVH_DBAAS_LOGS_SERVICE_TEST") + clusterId := os.Getenv("OVH_DBAAS_LOGS_CLUSTER_ID") + retentionId := os.Getenv("OVH_DBAAS_LOGS_CLUSTER_RETENTION_ID") + + config := fmt.Sprintf(` + data "ovh_dbaas_logs_cluster_retention" "ret" { + service_name = "%s" + cluster_id = "%s" + retention_id = "%s" + retention_type = "LOGS_INDEXING" + }`, + serviceName, + clusterId, + retentionId, + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckDbaasLogsCluster(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: config, + ExpectError: regexp.MustCompile(`Attribute \"retention_type\" cannot be specified when \"retention_id\"`), + }, + }, + }) +} diff --git a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/also_requires.go b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/also_requires.go index 7abc8ae92..f2de2828a 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/also_requires.go +++ b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/also_requires.go @@ -29,6 +29,7 @@ var ( _ validator.Object = AlsoRequiresValidator{} _ validator.Set = AlsoRequiresValidator{} _ validator.String = AlsoRequiresValidator{} + _ validator.Dynamic = AlsoRequiresValidator{} ) // AlsoRequiresValidator is the underlying struct implementing AlsoRequires. @@ -57,7 +58,8 @@ func (av AlsoRequiresValidator) MarkdownDescription(_ context.Context) string { func (av AlsoRequiresValidator) Validate(ctx context.Context, req AlsoRequiresValidatorRequest, res *AlsoRequiresValidatorResponse) { // If attribute configuration is null, there is nothing else to validate - if req.ConfigValue.IsNull() { + // If attribute configuration is unknown, delay the validation until it is known. + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { return } @@ -257,3 +259,17 @@ func (av AlsoRequiresValidator) ValidateString(ctx context.Context, req validato resp.Diagnostics.Append(validateResp.Diagnostics...) } + +func (av AlsoRequiresValidator) ValidateDynamic(ctx context.Context, req validator.DynamicRequest, resp *validator.DynamicResponse) { + validateReq := AlsoRequiresValidatorRequest{ + Config: req.Config, + ConfigValue: req.ConfigValue, + Path: req.Path, + PathExpression: req.PathExpression, + } + validateResp := &AlsoRequiresValidatorResponse{} + + av.Validate(ctx, validateReq, validateResp) + + resp.Diagnostics.Append(validateResp.Diagnostics...) +} diff --git a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/at_least_one_of.go b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/at_least_one_of.go index a31e45074..c68ea841d 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/at_least_one_of.go +++ b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/at_least_one_of.go @@ -29,6 +29,7 @@ var ( _ validator.Object = AtLeastOneOfValidator{} _ validator.Set = AtLeastOneOfValidator{} _ validator.String = AtLeastOneOfValidator{} + _ validator.Dynamic = AtLeastOneOfValidator{} ) // AtLeastOneOfValidator is the underlying struct implementing AtLeastOneOf. @@ -57,6 +58,7 @@ func (av AtLeastOneOfValidator) MarkdownDescription(_ context.Context) string { func (av AtLeastOneOfValidator) Validate(ctx context.Context, req AtLeastOneOfValidatorRequest, res *AtLeastOneOfValidatorResponse) { // If attribute configuration is not null, validator already succeeded. + // If attribute configuration is unknown, delay the validation until it is known. if !req.ConfigValue.IsNull() { return } @@ -257,3 +259,17 @@ func (av AtLeastOneOfValidator) ValidateString(ctx context.Context, req validato resp.Diagnostics.Append(validateResp.Diagnostics...) } + +func (av AtLeastOneOfValidator) ValidateDynamic(ctx context.Context, req validator.DynamicRequest, resp *validator.DynamicResponse) { + validateReq := AtLeastOneOfValidatorRequest{ + Config: req.Config, + ConfigValue: req.ConfigValue, + Path: req.Path, + PathExpression: req.PathExpression, + } + validateResp := &AtLeastOneOfValidatorResponse{} + + av.Validate(ctx, validateReq, validateResp) + + resp.Diagnostics.Append(validateResp.Diagnostics...) +} diff --git a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/conflicts_with.go b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/conflicts_with.go index 185d58e99..9cbc096c2 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/conflicts_with.go +++ b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/conflicts_with.go @@ -29,6 +29,7 @@ var ( _ validator.Object = ConflictsWithValidator{} _ validator.Set = ConflictsWithValidator{} _ validator.String = ConflictsWithValidator{} + _ validator.Dynamic = ConflictsWithValidator{} ) // ConflictsWithValidator is the underlying struct implementing ConflictsWith. @@ -57,7 +58,8 @@ func (av ConflictsWithValidator) MarkdownDescription(_ context.Context) string { func (av ConflictsWithValidator) Validate(ctx context.Context, req ConflictsWithValidatorRequest, res *ConflictsWithValidatorResponse) { // If attribute configuration is null, it cannot conflict with others - if req.ConfigValue.IsNull() { + // If attribute configuration is unknown, delay the validation until it is known. + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { return } @@ -257,3 +259,17 @@ func (av ConflictsWithValidator) ValidateString(ctx context.Context, req validat resp.Diagnostics.Append(validateResp.Diagnostics...) } + +func (av ConflictsWithValidator) ValidateDynamic(ctx context.Context, req validator.DynamicRequest, resp *validator.DynamicResponse) { + validateReq := ConflictsWithValidatorRequest{ + Config: req.Config, + ConfigValue: req.ConfigValue, + Path: req.Path, + PathExpression: req.PathExpression, + } + validateResp := &ConflictsWithValidatorResponse{} + + av.Validate(ctx, validateReq, validateResp) + + resp.Diagnostics.Append(validateResp.Diagnostics...) +} diff --git a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/exactly_one_of.go b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/exactly_one_of.go index 40af43839..b4714a71d 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/exactly_one_of.go +++ b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator/exactly_one_of.go @@ -29,6 +29,7 @@ var ( _ validator.Object = ExactlyOneOfValidator{} _ validator.Set = ExactlyOneOfValidator{} _ validator.String = ExactlyOneOfValidator{} + _ validator.Dynamic = ExactlyOneOfValidator{} ) // ExactlyOneOfValidator is the underlying struct implementing ExactlyOneOf. @@ -277,3 +278,17 @@ func (av ExactlyOneOfValidator) ValidateString(ctx context.Context, req validato resp.Diagnostics.Append(validateResp.Diagnostics...) } + +func (av ExactlyOneOfValidator) ValidateDynamic(ctx context.Context, req validator.DynamicRequest, resp *validator.DynamicResponse) { + validateReq := ExactlyOneOfValidatorRequest{ + Config: req.Config, + ConfigValue: req.ConfigValue, + Path: req.Path, + PathExpression: req.PathExpression, + } + validateResp := &ExactlyOneOfValidatorResponse{} + + av.Validate(ctx, validateReq, validateResp) + + resp.Diagnostics.Append(validateResp.Diagnostics...) +} diff --git a/vendor/github.com/hashicorp/terraform-plugin-framework-validators/listvalidator/no_null_values.go b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/listvalidator/no_null_values.go new file mode 100644 index 000000000..a66e8b0be --- /dev/null +++ b/vendor/github.com/hashicorp/terraform-plugin-framework-validators/listvalidator/no_null_values.go @@ -0,0 +1,78 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package listvalidator + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/function" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" +) + +var _ validator.List = noNullValuesValidator{} +var _ function.ListParameterValidator = noNullValuesValidator{} + +type noNullValuesValidator struct{} + +func (v noNullValuesValidator) Description(_ context.Context) string { + return "All values in the list must be configured" +} + +func (v noNullValuesValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} + +func (v noNullValuesValidator) ValidateList(_ context.Context, req validator.ListRequest, resp *validator.ListResponse) { + if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() { + return + } + + elements := req.ConfigValue.Elements() + + for _, e := range elements { + // Only evaluate known values for null + if e.IsUnknown() { + continue + } + + if e.IsNull() { + resp.Diagnostics.AddAttributeError( + req.Path, + "Null List Value", + "This attribute contains a null value.", + ) + } + } +} + +func (v noNullValuesValidator) ValidateParameterList(ctx context.Context, req function.ListParameterValidatorRequest, resp *function.ListParameterValidatorResponse) { + if req.Value.IsNull() || req.Value.IsUnknown() { + return + } + + elements := req.Value.Elements() + + for _, e := range elements { + // Only evaluate known values for null + if e.IsUnknown() { + continue + } + + if e.IsNull() { + resp.Error = function.ConcatFuncErrors( + resp.Error, + function.NewArgumentFuncError( + req.ArgumentPosition, + "Null List Value: This attribute contains a null value.", + ), + ) + } + } +} + +// NoNullValues returns a validator which ensures that any configured list +// only contains non-null values. +func NoNullValues() noNullValuesValidator { + return noNullValuesValidator{} +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 17f68505e..a67bbda32 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -171,7 +171,7 @@ github.com/hashicorp/terraform-plugin-framework/schema/validator github.com/hashicorp/terraform-plugin-framework/tfsdk github.com/hashicorp/terraform-plugin-framework/types github.com/hashicorp/terraform-plugin-framework/types/basetypes -# github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 +# github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 ## explicit; go 1.22.0 github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatorfuncerr diff --git a/website/docs/d/dbaas_logs_cluster_retention.html.markdown b/website/docs/d/dbaas_logs_cluster_retention.html.markdown index 04d43e8a0..a22cec1ea 100644 --- a/website/docs/d/dbaas_logs_cluster_retention.html.markdown +++ b/website/docs/d/dbaas_logs_cluster_retention.html.markdown @@ -27,15 +27,28 @@ data "ovh_dbaas_logs_cluster_retention" "retention" { } ``` +Additionnaly, you can filter retentions on their type: + +```hcl +data "ovh_dbaas_logs_cluster_retention" "retention" { + service_name = "ldp-xx-xxxxx" + cluster_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + duration = "P14D" + retention_type = "LOGS_INDEXING" +} +``` + ## Argument Reference * `service_name` - (Required) The service name. It's the ID of your Logs Data Platform instance. * `cluster_id` - (Required) Cluster ID -* `retention_id` - ID of the retention object -* `duration` - Indexed duration expressed in ISO-8601 format +* `retention_id` - ID of the retention object. Cannot be used if `duration` or `retention_type` is defined. +* `retention_type` - Type of the retention (LOGS_INDEXING | LOGS_COLD_STORAGE | METRICS_TENANT). Cannot be used if `retention_id` is defined. Defaults to `LOGS_INDEXING` if not defined. +* `duration` - Indexed duration expressed in ISO-8601 format. Cannot be used if `retention_id` is defined. ## Attributes Reference * `retention_id` - ID of the retention that can be used when creating a stream * `duration` - Indexed duration expressed in ISO-8601 format +* `retention_type` - Type of the retention (LOGS_INDEXING | LOGS_COLD_STORAGE | METRICS_TENANT) * `is_supported` - Indicates if a new stream can use it \ No newline at end of file