ec/ecresource/deploymentresource/enterprisesearch/v2/enterprise_search_payload.go (122 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 v2
import (
"context"
"github.com/elastic/cloud-sdk-go/pkg/models"
"github.com/elastic/cloud-sdk-go/pkg/util/ec"
v1 "github.com/elastic/terraform-provider-ec/ec/ecresource/deploymentresource/enterprisesearch/v1"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
)
type EnterpriseSearchTF struct {
ElasticsearchClusterRefId types.String `tfsdk:"elasticsearch_cluster_ref_id"`
RefId types.String `tfsdk:"ref_id"`
ResourceId types.String `tfsdk:"resource_id"`
Region types.String `tfsdk:"region"`
HttpEndpoint types.String `tfsdk:"http_endpoint"`
HttpsEndpoint types.String `tfsdk:"https_endpoint"`
InstanceConfigurationId types.String `tfsdk:"instance_configuration_id"`
LatestInstanceConfigurationId types.String `tfsdk:"latest_instance_configuration_id"`
InstanceConfigurationVersion types.Int64 `tfsdk:"instance_configuration_version"`
LatestInstanceConfigurationVersion types.Int64 `tfsdk:"latest_instance_configuration_version"`
Size types.String `tfsdk:"size"`
SizeResource types.String `tfsdk:"size_resource"`
ZoneCount types.Int64 `tfsdk:"zone_count"`
NodeTypeAppserver types.Bool `tfsdk:"node_type_appserver"`
NodeTypeConnector types.Bool `tfsdk:"node_type_connector"`
NodeTypeWorker types.Bool `tfsdk:"node_type_worker"`
Config types.Object `tfsdk:"config"`
}
func (es *EnterpriseSearchTF) payload(ctx context.Context, payload models.EnterpriseSearchPayload) (*models.EnterpriseSearchPayload, diag.Diagnostics) {
var diags diag.Diagnostics
if !es.ElasticsearchClusterRefId.IsNull() {
payload.ElasticsearchClusterRefID = ec.String(es.ElasticsearchClusterRefId.ValueString())
}
if !es.RefId.IsNull() {
payload.RefID = ec.String(es.RefId.ValueString())
}
if es.Region.ValueString() != "" {
payload.Region = ec.String(es.Region.ValueString())
}
if !es.Config.IsNull() && !es.Config.IsUnknown() {
var config *v1.EnterpriseSearchConfigTF
ds := tfsdk.ValueAs(ctx, es.Config, &config)
diags.Append(ds...)
if !ds.HasError() && config != nil {
diags.Append(enterpriseSearchConfigPayload(ctx, *config, payload.Plan.EnterpriseSearch)...)
}
}
topologyTF := v1.EnterpriseSearchTopologyTF{
InstanceConfigurationId: es.InstanceConfigurationId,
InstanceConfigurationVersion: es.InstanceConfigurationVersion,
Size: es.Size,
SizeResource: es.SizeResource,
ZoneCount: es.ZoneCount,
NodeTypeAppserver: es.NodeTypeAppserver,
NodeTypeConnector: es.NodeTypeConnector,
NodeTypeWorker: es.NodeTypeWorker,
}
// Always use the first topology element - discard any other topology elements
topology, ds := enterpriseSearchTopologyPayload(ctx, topologyTF, defaultTopology(payload.Plan.ClusterTopology)[0])
diags = append(diags, ds...)
if topology != nil {
payload.Plan.ClusterTopology = []*models.EnterpriseSearchTopologyElement{topology}
}
return &payload, diags
}
func EnterpriseSearchesPayload(ctx context.Context, esObj types.Object, updateResources *models.DeploymentUpdateResources) (*models.EnterpriseSearchPayload, diag.Diagnostics) {
es, diags := objectToEnterpriseSearch(ctx, esObj)
if diags.HasError() {
return nil, diags
}
if es == nil {
return nil, nil
}
templatePayload := payloadFromUpdate(updateResources)
if templatePayload == nil {
diags.AddError(
"enterprise_search payload error",
"enterprise_search specified but deployment template is not configured for it. Use a different template if you wish to add enterprise_search",
)
return nil, diags
}
payload, diags := es.payload(ctx, *templatePayload)
if diags.HasError() {
return nil, diags
}
return payload, nil
}
func objectToEnterpriseSearch(ctx context.Context, plan types.Object) (*EnterpriseSearchTF, diag.Diagnostics) {
var enterpriseSearch *EnterpriseSearchTF
if plan.IsNull() || plan.IsUnknown() {
return nil, nil
}
if diags := tfsdk.ValueAs(ctx, plan, &enterpriseSearch); diags.HasError() {
return nil, diags
}
return enterpriseSearch, nil
}
func CheckAvailableMigration(ctx context.Context, plan types.Object, state types.Object) (bool, diag.Diagnostics) {
esPlan, diags := objectToEnterpriseSearch(ctx, plan)
if diags.HasError() {
return false, diags
}
esState, diags := objectToEnterpriseSearch(ctx, state)
if diags.HasError() {
return false, diags
}
if esPlan == nil || esState == nil {
return false, nil
}
// We won't migrate this topology element if 'instance_configuration_id' or 'instance_configuration_version' are
// defined on the TF configuration. Otherwise, we may be setting an incorrect value for 'size', in case the
// template IC has different size increments
if !esPlan.InstanceConfigurationId.IsUnknown() || !esPlan.InstanceConfigurationVersion.IsUnknown() {
return false, nil
}
instanceConfigIdsDiff := esState.InstanceConfigurationId != esState.LatestInstanceConfigurationId
instanceConfigVersionsDiff := esState.InstanceConfigurationVersion != esState.LatestInstanceConfigurationVersion
// We consider that a migration is available when:
// * the current instance config ID doesn't match the one in the template
// * the instance config IDs match but the instance config versions differ
return instanceConfigIdsDiff || instanceConfigVersionsDiff, nil
}
// payloadFromUpdate returns the EnterpriseSearchPayload from a deployment
// template or an empty version of the payload.
func payloadFromUpdate(updateResources *models.DeploymentUpdateResources) *models.EnterpriseSearchPayload {
if updateResources == nil || len(updateResources.EnterpriseSearch) == 0 {
return nil
}
return updateResources.EnterpriseSearch[0]
}