ec/ecdatasource/deploymentsdatasource/expanders.go (181 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package deploymentsdatasource import ( "context" "fmt" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/elastic/cloud-sdk-go/pkg/models" "github.com/elastic/cloud-sdk-go/pkg/util" "github.com/elastic/cloud-sdk-go/pkg/util/ec" ) // expandFilters expands all filters into a search request model func expandFilters(ctx context.Context, state modelV0) (*models.SearchRequest, diag.Diagnostics) { var diags diag.Diagnostics var queries []*models.QueryContainer namePrefix := state.NamePrefix.ValueString() if namePrefix != "" { queries = append(queries, &models.QueryContainer{ Prefix: map[string]models.PrefixQuery{ // The "keyword" addition denotes that the query will be using a keyword // field rather than a text field in order to ensure the query is not analyzed "name.keyword": {Value: &namePrefix}, }, }) } name := state.Name.ValueString() if name != "" { queries = append(queries, &models.QueryContainer{ Term: map[string]models.TermQuery{ "name.keyword": {Value: &name}, }, }) } depTemplateID := state.DeploymentTemplateID.ValueString() if depTemplateID != "" { esPath := "resources.elasticsearch" tplTermPath := esPath + ".info.plan_info.current.plan.deployment_template.id" queries = append(queries, newNestedTermQuery(esPath, tplTermPath, depTemplateID)) } healthy := state.Healthy.ValueString() if healthy != "" { if healthy != "true" && healthy != "false" { diags.AddError("invalid value for healthy", fmt.Sprintf("expected either [true] or [false] but got [%s]", healthy)) return nil, diags } queries = append(queries, &models.QueryContainer{ Term: map[string]models.TermQuery{ "healthy": {Value: &healthy}, }, }) } var tags = make(map[string]string) diags.Append(state.Tags.ElementsAs(ctx, &tags, false)...) if diags.HasError() { return nil, diags } var tagQueries []*models.QueryContainer for key, value := range tags { tagQueries = append(tagQueries, newNestedTagQuery(key, value), ) } if len(tagQueries) > 0 { queries = append(queries, &models.QueryContainer{ Bool: &models.BoolQuery{ MinimumShouldMatch: int32(len(tags)), Should: tagQueries, }, }) } type resourceFilter struct { resourceKind string settings *types.List } resourceFilters := []resourceFilter{ {resourceKind: util.Elasticsearch, settings: &state.Elasticsearch}, {resourceKind: util.Kibana, settings: &state.Kibana}, {resourceKind: util.Apm, settings: &state.Apm}, {resourceKind: util.EnterpriseSearch, settings: &state.EnterpriseSearch}, {resourceKind: util.IntegrationsServer, settings: &state.IntegrationsServer}, } for _, filter := range resourceFilters { req, diags := expandResourceFilters(ctx, filter.settings, filter.resourceKind) if diags.HasError() { return nil, diags } queries = append(queries, req...) } searchReq := models.SearchRequest{ Size: int32(state.Size.ValueInt64()), Sort: []interface{}{"id"}, } if len(queries) > 0 { searchReq.Query = &models.QueryContainer{ Bool: &models.BoolQuery{ Filter: []*models.QueryContainer{ { Bool: &models.BoolQuery{ Must: queries, }, }, }, }, } } return &searchReq, nil } // expandResourceFilters expands filters from a specific resource kind into query models func expandResourceFilters(ctx context.Context, resources *types.List, resourceKind string) ([]*models.QueryContainer, diag.Diagnostics) { var diags diag.Diagnostics if len(resources.Elements()) == 0 { return nil, nil } var filters []resourceFiltersModelV0 var queries []*models.QueryContainer diags.Append(resources.ElementsAs(ctx, &filters, false)...) if diags.HasError() { return nil, diags } for _, filter := range filters { resourceKindPath := "resources." + resourceKind if filter.Status.ValueString() != "" { statusTermPath := resourceKindPath + ".info.status" queries = append(queries, newNestedTermQuery(resourceKindPath, statusTermPath, filter.Status.ValueString())) } if filter.Version.ValueString() != "" { versionTermPath := resourceKindPath + ".info.plan_info.current.plan." + resourceKind + ".version" queries = append(queries, newNestedTermQuery(resourceKindPath, versionTermPath, filter.Version.ValueString())) } if filter.Healthy.ValueString() != "" { healthyTermPath := resourceKindPath + ".info.healthy" if filter.Healthy.ValueString() != "true" && filter.Healthy.ValueString() != "false" { diags.AddError("invalid value for healthy", fmt.Sprintf("expected either [true] or [false] but got [%s]", filter.Healthy.ValueString())) return nil, diags } queries = append(queries, newNestedTermQuery(resourceKindPath, healthyTermPath, filter.Healthy.ValueString())) } } return queries, nil } func newNestedTermQuery(path, term string, value string) *models.QueryContainer { return &models.QueryContainer{ Nested: &models.NestedQuery{ Path: &path, Query: &models.QueryContainer{ Term: map[string]models.TermQuery{ term: { Value: &value, }, }, }, }, } } // newNestedTagQuery returns a nested query for a metadata tag func newNestedTagQuery(key string, value string) *models.QueryContainer { return &models.QueryContainer{ Nested: &models.NestedQuery{ Path: ec.String("metadata.tags"), Query: &models.QueryContainer{ Bool: &models.BoolQuery{ Filter: []*models.QueryContainer{ { Term: map[string]models.TermQuery{ "metadata.tags.key": { Value: &key, }, }, }, { Term: map[string]models.TermQuery{ "metadata.tags.value": { Value: &value, }, }, }, }, }, }, }, } }