From 5279c8d1a776410163000839aad40930f513b6e1 Mon Sep 17 00:00:00 2001 From: Toby Brain Date: Wed, 3 Dec 2025 17:27:05 +1100 Subject: [PATCH 1/3] Ignore empty fields in API response --- internal/elasticsearch/index/alias/models.go | 17 ++- .../ml/anomaly_detection_job/models_tf.go | 101 +++--------------- internal/fleet/output/models_elasticsearch.go | 3 +- internal/fleet/output/models_kafka.go | 3 +- internal/fleet/output/models_logstash.go | 3 +- internal/fleet/output/models_ssl.go | 18 +++- internal/fleet/output/models_ssl_test.go | 22 ++++ internal/fleet/output/schema.go | 9 ++ .../typeutils/{typeutils.go => string.go} | 14 +++ 9 files changed, 88 insertions(+), 102 deletions(-) rename internal/utils/typeutils/{typeutils.go => string.go} (63%) diff --git a/internal/elasticsearch/index/alias/models.go b/internal/elasticsearch/index/alias/models.go index 45a57edfa..3559b041c 100644 --- a/internal/elasticsearch/index/alias/models.go +++ b/internal/elasticsearch/index/alias/models.go @@ -6,6 +6,7 @@ import ( "reflect" "github.com/elastic/terraform-provider-elasticstack/internal/models" + "github.com/elastic/terraform-provider-elasticstack/internal/utils/typeutils" "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" @@ -95,19 +96,13 @@ func (model *tfModel) populateFromAPI(ctx context.Context, aliasName string, ind // indexFromAlias converts a models.IndexAlias to an indexModel func indexFromAlias(indexName string, aliasData models.IndexAlias) (indexModel, diag.Diagnostics) { index := indexModel{ - Name: types.StringValue(indexName), - IsHidden: types.BoolValue(aliasData.IsHidden), + Name: types.StringValue(indexName), + IsHidden: types.BoolValue(aliasData.IsHidden), + IndexRouting: typeutils.NonEmptyStringValue(aliasData.IndexRouting), + Routing: typeutils.NonEmptyStringValue(aliasData.Routing), + SearchRouting: typeutils.NonEmptyStringValue(aliasData.SearchRouting), } - if aliasData.IndexRouting != "" { - index.IndexRouting = types.StringValue(aliasData.IndexRouting) - } - if aliasData.Routing != "" { - index.Routing = types.StringValue(aliasData.Routing) - } - if aliasData.SearchRouting != "" { - index.SearchRouting = types.StringValue(aliasData.SearchRouting) - } if aliasData.Filter != nil { filterBytes, err := json.Marshal(aliasData.Filter) if err != nil { diff --git a/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go b/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go index 0b4c67ec3..5be24e4cc 100644 --- a/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go +++ b/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go @@ -7,6 +7,7 @@ import ( "github.com/elastic/terraform-provider-elasticstack/internal/utils" "github.com/elastic/terraform-provider-elasticstack/internal/utils/customtypes" + "github.com/elastic/terraform-provider-elasticstack/internal/utils/typeutils" "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" fwdiags "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" @@ -300,10 +301,7 @@ func (tfModel *AnomalyDetectionJobTFModel) fromAPIModel(ctx context.Context, api // Convert optional fields tfModel.AllowLazyOpen = types.BoolPointerValue(apiModel.AllowLazyOpen) - - if apiModel.BackgroundPersistInterval != "" { - tfModel.BackgroundPersistInterval = types.StringValue(apiModel.BackgroundPersistInterval) - } + tfModel.BackgroundPersistInterval = typeutils.NonEmptyStringValue(apiModel.BackgroundPersistInterval) if apiModel.CustomSettings != nil { customSettingsJSON, err := json.Marshal(apiModel.CustomSettings) @@ -324,10 +322,7 @@ func (tfModel *AnomalyDetectionJobTFModel) fromAPIModel(ctx context.Context, api tfModel.RenormalizationWindowDays = types.Int64Value(*apiModel.RenormalizationWindowDays) } - if apiModel.ResultsIndexName != "" { - tfModel.ResultsIndexName = types.StringValue(apiModel.ResultsIndexName) - } - + tfModel.ResultsIndexName = typeutils.NonEmptyStringValue(apiModel.ResultsIndexName) tfModel.ResultsRetentionDays = types.Int64PointerValue(apiModel.ResultsRetentionDays) // Convert analysis_config @@ -363,29 +358,10 @@ func (tfModel *AnomalyDetectionJobTFModel) convertAnalysisConfigFromAPI(ctx cont } // Convert optional string fields - if apiConfig.CategorizationFieldName != "" { - analysisConfigTF.CategorizationFieldName = types.StringValue(apiConfig.CategorizationFieldName) - } else { - analysisConfigTF.CategorizationFieldName = types.StringNull() - } - - if apiConfig.Latency != "" { - analysisConfigTF.Latency = types.StringValue(apiConfig.Latency) - } else { - analysisConfigTF.Latency = types.StringNull() - } - - if apiConfig.ModelPruneWindow != "" { - analysisConfigTF.ModelPruneWindow = types.StringValue(apiConfig.ModelPruneWindow) - } else { - analysisConfigTF.ModelPruneWindow = types.StringNull() - } - - if apiConfig.SummaryCountFieldName != "" { - analysisConfigTF.SummaryCountFieldName = types.StringValue(apiConfig.SummaryCountFieldName) - } else { - analysisConfigTF.SummaryCountFieldName = types.StringNull() - } + analysisConfigTF.CategorizationFieldName = typeutils.NonEmptyStringValue(apiConfig.CategorizationFieldName) + analysisConfigTF.Latency = typeutils.NonEmptyStringValue(apiConfig.Latency) + analysisConfigTF.ModelPruneWindow = typeutils.NonEmptyStringValue(apiConfig.ModelPruneWindow) + analysisConfigTF.SummaryCountFieldName = typeutils.NonEmptyStringValue(apiConfig.SummaryCountFieldName) // Convert boolean fields analysisConfigTF.MultivariateByFields = types.BoolPointerValue(apiConfig.MultivariateByFields) @@ -417,41 +393,12 @@ func (tfModel *AnomalyDetectionJobTFModel) convertAnalysisConfigFromAPI(ctx cont } // Convert optional string fields - if detector.FieldName != "" { - detectorsTF[i].FieldName = types.StringValue(detector.FieldName) - } else { - detectorsTF[i].FieldName = types.StringNull() - } - - if detector.ByFieldName != "" { - detectorsTF[i].ByFieldName = types.StringValue(detector.ByFieldName) - } else { - detectorsTF[i].ByFieldName = types.StringNull() - } - - if detector.OverFieldName != "" { - detectorsTF[i].OverFieldName = types.StringValue(detector.OverFieldName) - } else { - detectorsTF[i].OverFieldName = types.StringNull() - } - - if detector.PartitionFieldName != "" { - detectorsTF[i].PartitionFieldName = types.StringValue(detector.PartitionFieldName) - } else { - detectorsTF[i].PartitionFieldName = types.StringNull() - } - - if detector.DetectorDescription != "" { - detectorsTF[i].DetectorDescription = types.StringValue(detector.DetectorDescription) - } else { - detectorsTF[i].DetectorDescription = types.StringNull() - } - - if detector.ExcludeFrequent != "" { - detectorsTF[i].ExcludeFrequent = types.StringValue(detector.ExcludeFrequent) - } else { - detectorsTF[i].ExcludeFrequent = types.StringNull() - } + detectorsTF[i].FieldName = typeutils.NonEmptyStringValue(detector.FieldName) + detectorsTF[i].ByFieldName = typeutils.NonEmptyStringValue(detector.ByFieldName) + detectorsTF[i].OverFieldName = typeutils.NonEmptyStringValue(detector.OverFieldName) + detectorsTF[i].PartitionFieldName = typeutils.NonEmptyStringValue(detector.PartitionFieldName) + detectorsTF[i].DetectorDescription = typeutils.NonEmptyStringValue(detector.DetectorDescription) + detectorsTF[i].ExcludeFrequent = typeutils.NonEmptyStringValue(detector.ExcludeFrequent) // Convert boolean field detectorsTF[i].UseNull = types.BoolPointerValue(detector.UseNull) @@ -530,18 +477,9 @@ func (tfModel *AnomalyDetectionJobTFModel) convertDataDescriptionFromAPI(ctx con return types.ObjectNull(getDataDescriptionAttrTypes()) } - dataDescriptionTF := DataDescriptionTFModel{} - - if apiDataDescription.TimeField != "" { - dataDescriptionTF.TimeField = types.StringValue(apiDataDescription.TimeField) - } else { - dataDescriptionTF.TimeField = types.StringNull() - } - - if apiDataDescription.TimeFormat != "" { - dataDescriptionTF.TimeFormat = types.StringValue(apiDataDescription.TimeFormat) - } else { - dataDescriptionTF.TimeFormat = types.StringNull() + dataDescriptionTF := DataDescriptionTFModel{ + TimeField: typeutils.NonEmptyStringValue(apiDataDescription.TimeField), + TimeFormat: typeutils.NonEmptyStringValue(apiDataDescription.TimeFormat), } dataDescriptionObjectValue, d := types.ObjectValueFrom(ctx, getDataDescriptionAttrTypes(), dataDescriptionTF) @@ -576,12 +514,7 @@ func (tfModel *AnomalyDetectionJobTFModel) convertModelPlotConfigFromAPI(ctx con modelPlotConfigTF := ModelPlotConfigTFModel{ Enabled: types.BoolValue(apiModelPlotConfig.Enabled), - } - - if apiModelPlotConfig.Terms != "" { - modelPlotConfigTF.Terms = types.StringValue(apiModelPlotConfig.Terms) - } else { - modelPlotConfigTF.Terms = types.StringNull() + Terms: typeutils.NonEmptyStringValue(apiModelPlotConfig.Terms), } modelPlotConfigTF.AnnotationsEnabled = types.BoolPointerValue(apiModelPlotConfig.AnnotationsEnabled) diff --git a/internal/fleet/output/models_elasticsearch.go b/internal/fleet/output/models_elasticsearch.go index 800fc91a1..31efe1ae0 100644 --- a/internal/fleet/output/models_elasticsearch.go +++ b/internal/fleet/output/models_elasticsearch.go @@ -5,6 +5,7 @@ import ( "github.com/elastic/terraform-provider-elasticstack/generated/kbapi" "github.com/elastic/terraform-provider-elasticstack/internal/utils" + "github.com/elastic/terraform-provider-elasticstack/internal/utils/typeutils" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/types" @@ -17,7 +18,7 @@ func (model *outputModel) fromAPIElasticsearchModel(ctx context.Context, data *k model.Type = types.StringValue(string(data.Type)) model.Hosts = utils.SliceToListType_String(ctx, data.Hosts, path.Root("hosts"), &diags) model.CaSha256 = types.StringPointerValue(data.CaSha256) - model.CaTrustedFingerprint = types.StringPointerValue(data.CaTrustedFingerprint) + model.CaTrustedFingerprint = typeutils.NonEmptyStringPointerValue(data.CaTrustedFingerprint) model.DefaultIntegrations = types.BoolPointerValue(data.IsDefault) model.DefaultMonitoring = types.BoolPointerValue(data.IsDefaultMonitoring) model.ConfigYaml = types.StringPointerValue(data.ConfigYaml) diff --git a/internal/fleet/output/models_kafka.go b/internal/fleet/output/models_kafka.go index 9de3ba188..31f554f29 100644 --- a/internal/fleet/output/models_kafka.go +++ b/internal/fleet/output/models_kafka.go @@ -5,6 +5,7 @@ import ( "github.com/elastic/terraform-provider-elasticstack/generated/kbapi" "github.com/elastic/terraform-provider-elasticstack/internal/utils" + "github.com/elastic/terraform-provider-elasticstack/internal/utils/typeutils" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/types" @@ -437,7 +438,7 @@ func (model *outputModel) fromAPIKafkaModel(ctx context.Context, data *kbapi.Out model.Type = types.StringValue(string(data.Type)) model.Hosts = utils.SliceToListType_String(ctx, data.Hosts, path.Root("hosts"), &diags) model.CaSha256 = types.StringPointerValue(data.CaSha256) - model.CaTrustedFingerprint = types.StringPointerValue(data.CaTrustedFingerprint) + model.CaTrustedFingerprint = typeutils.NonEmptyStringPointerValue(data.CaTrustedFingerprint) model.DefaultIntegrations = types.BoolPointerValue(data.IsDefault) model.DefaultMonitoring = types.BoolPointerValue(data.IsDefaultMonitoring) model.ConfigYaml = types.StringPointerValue(data.ConfigYaml) diff --git a/internal/fleet/output/models_logstash.go b/internal/fleet/output/models_logstash.go index 2a4b68990..be58f2e12 100644 --- a/internal/fleet/output/models_logstash.go +++ b/internal/fleet/output/models_logstash.go @@ -5,6 +5,7 @@ import ( "github.com/elastic/terraform-provider-elasticstack/generated/kbapi" "github.com/elastic/terraform-provider-elasticstack/internal/utils" + "github.com/elastic/terraform-provider-elasticstack/internal/utils/typeutils" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/types" @@ -17,7 +18,7 @@ func (model *outputModel) fromAPILogstashModel(ctx context.Context, data *kbapi. model.Type = types.StringValue(string(data.Type)) model.Hosts = utils.SliceToListType_String(ctx, data.Hosts, path.Root("hosts"), &diags) model.CaSha256 = types.StringPointerValue(data.CaSha256) - model.CaTrustedFingerprint = types.StringPointerValue(data.CaTrustedFingerprint) + model.CaTrustedFingerprint = typeutils.NonEmptyStringPointerValue(data.CaTrustedFingerprint) model.DefaultIntegrations = types.BoolPointerValue(data.IsDefault) model.DefaultMonitoring = types.BoolPointerValue(data.IsDefaultMonitoring) model.ConfigYaml = types.StringPointerValue(data.ConfigYaml) diff --git a/internal/fleet/output/models_ssl.go b/internal/fleet/output/models_ssl.go index e1f05d09a..a0f136230 100644 --- a/internal/fleet/output/models_ssl.go +++ b/internal/fleet/output/models_ssl.go @@ -5,6 +5,7 @@ import ( "github.com/elastic/terraform-provider-elasticstack/generated/kbapi" "github.com/elastic/terraform-provider-elasticstack/internal/utils" + "github.com/elastic/terraform-provider-elasticstack/internal/utils/typeutils" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/types" @@ -57,12 +58,21 @@ func sslToObjectValue(ctx context.Context, ssl *kbapi.OutputSsl) (types.Object, } var diags diag.Diagnostics - p := path.Root("ssl") sslModel := outputSslModel{ - CertificateAuthorities: utils.SliceToListType_String(ctx, utils.Deref(ssl.CertificateAuthorities), p.AtName("certificate_authorities"), &diags), - Certificate: types.StringPointerValue(ssl.Certificate), - Key: types.StringPointerValue(ssl.Key), + Certificate: typeutils.NonEmptyStringPointerValue(ssl.Certificate), + Key: typeutils.NonEmptyStringPointerValue(ssl.Key), } + + if cas := utils.Deref(ssl.CertificateAuthorities); len(cas) > 0 { + sslModel.CertificateAuthorities = utils.SliceToListType_String(ctx, cas, path.Root("ssl").AtName("certificate_authorities"), &diags) + } else { + sslModel.CertificateAuthorities = types.ListNull(types.StringType) + } + + if sslModel.CertificateAuthorities.IsNull() && sslModel.Certificate.IsNull() && sslModel.Key.IsNull() { + return types.ObjectNull(getSslAttrTypes()), nil + } + obj, diagTemp := types.ObjectValueFrom(ctx, getSslAttrTypes(), sslModel) diags.Append(diagTemp...) return obj, diags diff --git a/internal/fleet/output/models_ssl_test.go b/internal/fleet/output/models_ssl_test.go index 19f9b79eb..5632af8e2 100644 --- a/internal/fleet/output/models_ssl_test.go +++ b/internal/fleet/output/models_ssl_test.go @@ -122,6 +122,28 @@ func Test_sslToObjectValue(t *testing.T) { }, want: types.ObjectNull(getSslAttrTypes()), }, + { + name: "returns null object when ssl has all empty fields", + args: args{ + ssl: &kbapi.OutputSsl{ + Certificate: nil, + CertificateAuthorities: nil, + Key: nil, + }, + }, + want: types.ObjectNull(getSslAttrTypes()), + }, + { + name: "returns null object when ssl has empty string pointers and empty slice", + args: args{ + ssl: &kbapi.OutputSsl{ + Certificate: utils.Pointer(""), + CertificateAuthorities: &[]string{}, + Key: utils.Pointer(""), + }, + }, + want: types.ObjectNull(getSslAttrTypes()), + }, { name: "returns an object when populated", args: args{ diff --git a/internal/fleet/output/schema.go b/internal/fleet/output/schema.go index 7fc53cf35..6e031fbea 100644 --- a/internal/fleet/output/schema.go +++ b/internal/fleet/output/schema.go @@ -108,15 +108,24 @@ func getSchema() schema.Schema { Description: "Server SSL certificate authorities.", Optional: true, ElementType: types.StringType, + Validators: []validator.List{ + listvalidator.SizeAtLeast(1), + }, }, "certificate": schema.StringAttribute{ Description: "Client SSL certificate.", Required: true, + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + }, }, "key": schema.StringAttribute{ Description: "Client SSL certificate key.", Required: true, Sensitive: true, + Validators: []validator.String{ + stringvalidator.LengthAtLeast(1), + }, }, }, }, diff --git a/internal/utils/typeutils/typeutils.go b/internal/utils/typeutils/string.go similarity index 63% rename from internal/utils/typeutils/typeutils.go rename to internal/utils/typeutils/string.go index bcc9f626a..2739352c0 100644 --- a/internal/utils/typeutils/typeutils.go +++ b/internal/utils/typeutils/string.go @@ -14,3 +14,17 @@ func StringishPointerValue[T ~string](ptr *T) types.String { func StringishValue[T ~string](value T) types.String { return types.StringValue(string(value)) } + +func NonEmptyStringValue[T ~string](value T) types.String { + if value == "" { + return types.StringNull() + } + return types.StringValue(string(value)) +} + +func NonEmptyStringPointerValue[T ~string](ptr *T) types.String { + if ptr == nil { + return types.StringNull() + } + return NonEmptyStringValue(*ptr) +} From 231ac56f722ee02ccf0e3305f70862635b8b37d3 Mon Sep 17 00:00:00 2001 From: Toby Brain Date: Wed, 3 Dec 2025 17:32:08 +1100 Subject: [PATCH 2/3] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b5a41fac..547c6f2a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ alias = [ ### Changes +- Fix an issue where the `elasticstack_fleet_output` resource would error due to inconsistent state after an ouptut was edited in the Kibana UI ([#1506](https://github.com/elastic/terraform-provider-elasticstack/pull/1506)) - Allow `index` and `data_view_id` values to both be unknown during planning in `elasticstack_kibana_security_detection_rule` ([#1499](https://github.com/elastic/terraform-provider-elasticstack/pull/1499)) - Support `.bedrock` and `.gen-ai` connectors ([#1467](https://github.com/elastic/terraform-provider-elasticstack/pull/1467)) - Support the `solution` attribute in `elasticstack_kibana_space` from 8.16 ([#1486](https://github.com/elastic/terraform-provider-elasticstack/pull/1486)) From 1d0ecd600468a7161eccb4444435ae5d114badf4 Mon Sep 17 00:00:00 2001 From: Toby Brain Date: Wed, 3 Dec 2025 20:36:09 +1100 Subject: [PATCH 3/3] Stringish --- internal/elasticsearch/index/alias/models.go | 6 ++-- .../ml/anomaly_detection_job/models_tf.go | 30 +++++++++---------- internal/fleet/output/models_elasticsearch.go | 2 +- internal/fleet/output/models_kafka.go | 2 +- internal/fleet/output/models_logstash.go | 2 +- internal/fleet/output/models_ssl.go | 4 +-- internal/utils/typeutils/string.go | 6 ++-- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/internal/elasticsearch/index/alias/models.go b/internal/elasticsearch/index/alias/models.go index 3559b041c..d4cf6f42e 100644 --- a/internal/elasticsearch/index/alias/models.go +++ b/internal/elasticsearch/index/alias/models.go @@ -98,9 +98,9 @@ func indexFromAlias(indexName string, aliasData models.IndexAlias) (indexModel, index := indexModel{ Name: types.StringValue(indexName), IsHidden: types.BoolValue(aliasData.IsHidden), - IndexRouting: typeutils.NonEmptyStringValue(aliasData.IndexRouting), - Routing: typeutils.NonEmptyStringValue(aliasData.Routing), - SearchRouting: typeutils.NonEmptyStringValue(aliasData.SearchRouting), + IndexRouting: typeutils.NonEmptyStringishValue(aliasData.IndexRouting), + Routing: typeutils.NonEmptyStringishValue(aliasData.Routing), + SearchRouting: typeutils.NonEmptyStringishValue(aliasData.SearchRouting), } if aliasData.Filter != nil { diff --git a/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go b/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go index 5be24e4cc..c2ee0cfc9 100644 --- a/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go +++ b/internal/elasticsearch/ml/anomaly_detection_job/models_tf.go @@ -301,7 +301,7 @@ func (tfModel *AnomalyDetectionJobTFModel) fromAPIModel(ctx context.Context, api // Convert optional fields tfModel.AllowLazyOpen = types.BoolPointerValue(apiModel.AllowLazyOpen) - tfModel.BackgroundPersistInterval = typeutils.NonEmptyStringValue(apiModel.BackgroundPersistInterval) + tfModel.BackgroundPersistInterval = typeutils.NonEmptyStringishValue(apiModel.BackgroundPersistInterval) if apiModel.CustomSettings != nil { customSettingsJSON, err := json.Marshal(apiModel.CustomSettings) @@ -322,7 +322,7 @@ func (tfModel *AnomalyDetectionJobTFModel) fromAPIModel(ctx context.Context, api tfModel.RenormalizationWindowDays = types.Int64Value(*apiModel.RenormalizationWindowDays) } - tfModel.ResultsIndexName = typeutils.NonEmptyStringValue(apiModel.ResultsIndexName) + tfModel.ResultsIndexName = typeutils.NonEmptyStringishValue(apiModel.ResultsIndexName) tfModel.ResultsRetentionDays = types.Int64PointerValue(apiModel.ResultsRetentionDays) // Convert analysis_config @@ -358,10 +358,10 @@ func (tfModel *AnomalyDetectionJobTFModel) convertAnalysisConfigFromAPI(ctx cont } // Convert optional string fields - analysisConfigTF.CategorizationFieldName = typeutils.NonEmptyStringValue(apiConfig.CategorizationFieldName) - analysisConfigTF.Latency = typeutils.NonEmptyStringValue(apiConfig.Latency) - analysisConfigTF.ModelPruneWindow = typeutils.NonEmptyStringValue(apiConfig.ModelPruneWindow) - analysisConfigTF.SummaryCountFieldName = typeutils.NonEmptyStringValue(apiConfig.SummaryCountFieldName) + analysisConfigTF.CategorizationFieldName = typeutils.NonEmptyStringishValue(apiConfig.CategorizationFieldName) + analysisConfigTF.Latency = typeutils.NonEmptyStringishValue(apiConfig.Latency) + analysisConfigTF.ModelPruneWindow = typeutils.NonEmptyStringishValue(apiConfig.ModelPruneWindow) + analysisConfigTF.SummaryCountFieldName = typeutils.NonEmptyStringishValue(apiConfig.SummaryCountFieldName) // Convert boolean fields analysisConfigTF.MultivariateByFields = types.BoolPointerValue(apiConfig.MultivariateByFields) @@ -393,12 +393,12 @@ func (tfModel *AnomalyDetectionJobTFModel) convertAnalysisConfigFromAPI(ctx cont } // Convert optional string fields - detectorsTF[i].FieldName = typeutils.NonEmptyStringValue(detector.FieldName) - detectorsTF[i].ByFieldName = typeutils.NonEmptyStringValue(detector.ByFieldName) - detectorsTF[i].OverFieldName = typeutils.NonEmptyStringValue(detector.OverFieldName) - detectorsTF[i].PartitionFieldName = typeutils.NonEmptyStringValue(detector.PartitionFieldName) - detectorsTF[i].DetectorDescription = typeutils.NonEmptyStringValue(detector.DetectorDescription) - detectorsTF[i].ExcludeFrequent = typeutils.NonEmptyStringValue(detector.ExcludeFrequent) + detectorsTF[i].FieldName = typeutils.NonEmptyStringishValue(detector.FieldName) + detectorsTF[i].ByFieldName = typeutils.NonEmptyStringishValue(detector.ByFieldName) + detectorsTF[i].OverFieldName = typeutils.NonEmptyStringishValue(detector.OverFieldName) + detectorsTF[i].PartitionFieldName = typeutils.NonEmptyStringishValue(detector.PartitionFieldName) + detectorsTF[i].DetectorDescription = typeutils.NonEmptyStringishValue(detector.DetectorDescription) + detectorsTF[i].ExcludeFrequent = typeutils.NonEmptyStringishValue(detector.ExcludeFrequent) // Convert boolean field detectorsTF[i].UseNull = types.BoolPointerValue(detector.UseNull) @@ -478,8 +478,8 @@ func (tfModel *AnomalyDetectionJobTFModel) convertDataDescriptionFromAPI(ctx con } dataDescriptionTF := DataDescriptionTFModel{ - TimeField: typeutils.NonEmptyStringValue(apiDataDescription.TimeField), - TimeFormat: typeutils.NonEmptyStringValue(apiDataDescription.TimeFormat), + TimeField: typeutils.NonEmptyStringishValue(apiDataDescription.TimeField), + TimeFormat: typeutils.NonEmptyStringishValue(apiDataDescription.TimeFormat), } dataDescriptionObjectValue, d := types.ObjectValueFrom(ctx, getDataDescriptionAttrTypes(), dataDescriptionTF) @@ -514,7 +514,7 @@ func (tfModel *AnomalyDetectionJobTFModel) convertModelPlotConfigFromAPI(ctx con modelPlotConfigTF := ModelPlotConfigTFModel{ Enabled: types.BoolValue(apiModelPlotConfig.Enabled), - Terms: typeutils.NonEmptyStringValue(apiModelPlotConfig.Terms), + Terms: typeutils.NonEmptyStringishValue(apiModelPlotConfig.Terms), } modelPlotConfigTF.AnnotationsEnabled = types.BoolPointerValue(apiModelPlotConfig.AnnotationsEnabled) diff --git a/internal/fleet/output/models_elasticsearch.go b/internal/fleet/output/models_elasticsearch.go index 31efe1ae0..c677f653b 100644 --- a/internal/fleet/output/models_elasticsearch.go +++ b/internal/fleet/output/models_elasticsearch.go @@ -18,7 +18,7 @@ func (model *outputModel) fromAPIElasticsearchModel(ctx context.Context, data *k model.Type = types.StringValue(string(data.Type)) model.Hosts = utils.SliceToListType_String(ctx, data.Hosts, path.Root("hosts"), &diags) model.CaSha256 = types.StringPointerValue(data.CaSha256) - model.CaTrustedFingerprint = typeutils.NonEmptyStringPointerValue(data.CaTrustedFingerprint) + model.CaTrustedFingerprint = typeutils.NonEmptyStringishPointerValue(data.CaTrustedFingerprint) model.DefaultIntegrations = types.BoolPointerValue(data.IsDefault) model.DefaultMonitoring = types.BoolPointerValue(data.IsDefaultMonitoring) model.ConfigYaml = types.StringPointerValue(data.ConfigYaml) diff --git a/internal/fleet/output/models_kafka.go b/internal/fleet/output/models_kafka.go index 31f554f29..a16f2589b 100644 --- a/internal/fleet/output/models_kafka.go +++ b/internal/fleet/output/models_kafka.go @@ -438,7 +438,7 @@ func (model *outputModel) fromAPIKafkaModel(ctx context.Context, data *kbapi.Out model.Type = types.StringValue(string(data.Type)) model.Hosts = utils.SliceToListType_String(ctx, data.Hosts, path.Root("hosts"), &diags) model.CaSha256 = types.StringPointerValue(data.CaSha256) - model.CaTrustedFingerprint = typeutils.NonEmptyStringPointerValue(data.CaTrustedFingerprint) + model.CaTrustedFingerprint = typeutils.NonEmptyStringishPointerValue(data.CaTrustedFingerprint) model.DefaultIntegrations = types.BoolPointerValue(data.IsDefault) model.DefaultMonitoring = types.BoolPointerValue(data.IsDefaultMonitoring) model.ConfigYaml = types.StringPointerValue(data.ConfigYaml) diff --git a/internal/fleet/output/models_logstash.go b/internal/fleet/output/models_logstash.go index be58f2e12..6f79c56d3 100644 --- a/internal/fleet/output/models_logstash.go +++ b/internal/fleet/output/models_logstash.go @@ -18,7 +18,7 @@ func (model *outputModel) fromAPILogstashModel(ctx context.Context, data *kbapi. model.Type = types.StringValue(string(data.Type)) model.Hosts = utils.SliceToListType_String(ctx, data.Hosts, path.Root("hosts"), &diags) model.CaSha256 = types.StringPointerValue(data.CaSha256) - model.CaTrustedFingerprint = typeutils.NonEmptyStringPointerValue(data.CaTrustedFingerprint) + model.CaTrustedFingerprint = typeutils.NonEmptyStringishPointerValue(data.CaTrustedFingerprint) model.DefaultIntegrations = types.BoolPointerValue(data.IsDefault) model.DefaultMonitoring = types.BoolPointerValue(data.IsDefaultMonitoring) model.ConfigYaml = types.StringPointerValue(data.ConfigYaml) diff --git a/internal/fleet/output/models_ssl.go b/internal/fleet/output/models_ssl.go index a0f136230..27203bf2f 100644 --- a/internal/fleet/output/models_ssl.go +++ b/internal/fleet/output/models_ssl.go @@ -59,8 +59,8 @@ func sslToObjectValue(ctx context.Context, ssl *kbapi.OutputSsl) (types.Object, var diags diag.Diagnostics sslModel := outputSslModel{ - Certificate: typeutils.NonEmptyStringPointerValue(ssl.Certificate), - Key: typeutils.NonEmptyStringPointerValue(ssl.Key), + Certificate: typeutils.NonEmptyStringishPointerValue(ssl.Certificate), + Key: typeutils.NonEmptyStringishPointerValue(ssl.Key), } if cas := utils.Deref(ssl.CertificateAuthorities); len(cas) > 0 { diff --git a/internal/utils/typeutils/string.go b/internal/utils/typeutils/string.go index 2739352c0..c20a5497d 100644 --- a/internal/utils/typeutils/string.go +++ b/internal/utils/typeutils/string.go @@ -15,16 +15,16 @@ func StringishValue[T ~string](value T) types.String { return types.StringValue(string(value)) } -func NonEmptyStringValue[T ~string](value T) types.String { +func NonEmptyStringishValue[T ~string](value T) types.String { if value == "" { return types.StringNull() } return types.StringValue(string(value)) } -func NonEmptyStringPointerValue[T ~string](ptr *T) types.String { +func NonEmptyStringishPointerValue[T ~string](ptr *T) types.String { if ptr == nil { return types.StringNull() } - return NonEmptyStringValue(*ptr) + return NonEmptyStringishValue(*ptr) }