ec/ecresource/deploymentresource/elasticsearch/v2/node_roles_plan_modifier.go (87 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/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/elastic/terraform-provider-ec/ec/internal/planmodifiers" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" ) func UseNodeRolesDefault() nodeRolesDefault { return nodeRolesDefault{} } type nodeRolesDefault struct{} func (m nodeRolesDefault) PlanModifySet(ctx context.Context, req planmodifier.SetRequest, resp *planmodifier.SetResponse) { useState, useNodeRoles, diags := useStateAndNodeRolesInPlanModifiers(ctx, req.ConfigValue, req.Plan, req.State, resp.PlanValue) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } if !useState { return } // If useNodeRoles is false, we can use the current state and // it should be null in this case - we don't migrate back from node_roles to node_types if !useNodeRoles && !req.StateValue.IsNull() { // it should not happen return } // If useNodeRoles is true, then either // * state already uses node_roles or // * state uses node_types but we need to migrate to node_roles. // We cannot use state in the second case (migration to node_roles) // It happens when node_roles state is null. if useNodeRoles && req.StateValue.IsNull() { return } resp.PlanValue = req.StateValue } // Description returns a human-readable description of the plan modifier. func (r nodeRolesDefault) Description(ctx context.Context) string { return "Use current state if it's still valid." } // MarkdownDescription returns a markdown description of the plan modifier. func (r nodeRolesDefault) MarkdownDescription(ctx context.Context) string { return "Use current state if it's still valid." } func SetUnknownOnTopologySizeChange() planmodifier.Set { return setUnknownOnTopologyChanges{} } type setUnknownOnTopologyChanges struct{} var ( tierNames = []string{"hot", "coordinating", "master", "warm", "cold", "frozen"} sizingAttributes = []string{"size", "zone_count"} ) func (m setUnknownOnTopologyChanges) PlanModifySet(ctx context.Context, req planmodifier.SetRequest, resp *planmodifier.SetResponse) { if req.PlanValue.IsUnknown() || req.PlanValue.IsNull() { return } for _, tierName := range tierNames { var tierValue attr.Value resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("elasticsearch").AtName(tierName), &tierValue)...) if resp.Diagnostics.HasError() { return } for _, attrName := range sizingAttributes { attrPath := path.Root("elasticsearch").AtName(tierName).AtName(attrName) var planValue attr.Value resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, attrPath, &planValue)...) if resp.Diagnostics.HasError() { return } var stateValue attr.Value resp.Diagnostics.Append(req.State.GetAttribute(ctx, attrPath, &stateValue)...) if resp.Diagnostics.HasError() { return } // If the plan value is unknown then planmodifiers haven't run for this topology element // Eventually the plan value will be set to the state value and it will be unchanged. // The tier should be directly checked for unknown, since the planValue will be null in that case (instead of unknown). // See: https://github.com/hashicorp/terraform-plugin-framework/issues/186 if (planValue.IsUnknown() || tierValue.IsUnknown()) && !(stateValue.IsUnknown() || stateValue.IsNull()) { continue } hasChanged, diags := planmodifiers.AttributeChanged(ctx, attrPath, req.Plan, req.State) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } if hasChanged { resp.PlanValue = types.SetUnknown(types.StringType) return } } } } // Description returns a human-readable description of the plan modifier. func (r setUnknownOnTopologyChanges) Description(ctx context.Context) string { return "Sets the plan value to unknown if the size of any topology element has changed." } // MarkdownDescription returns a markdown description of the plan modifier. func (r setUnknownOnTopologyChanges) MarkdownDescription(ctx context.Context) string { return "Sets the plan value to unknown if the size of any topology element has changed." }