@@ -238,6 +238,9 @@ func ResourceContainerCluster() *schema.Resource {
238238 containerClusterEnableK8sBetaApisCustomizeDiff,
239239 containerClusterNodeVersionCustomizeDiff,
240240 tpgresource.SetDiffForLabelsWithCustomizedName (" resource_labels" ),
241+ {{ if ne $ .TargetVersionName ` ga` }}
242+ clusterAcceleratorNetworkProfileCustomizeDiff,
243+ {{- end }}
241244 ),
242245
243246 Timeouts: &schema.ResourceTimeout {
@@ -8495,3 +8498,154 @@ func containerClusterNodeVersionCustomizeDiffFunc(diff tpgresource.TerraformReso
84958498
84968499 return nil
84978500}
8501+
8502+ {{ if ne $ .TargetVersionName ` ga` }}
8503+ func clusterAcceleratorNetworkProfileCustomizeDiff(_ context.Context , diff *schema.ResourceDiff , meta any) error {
8504+ // 1. SKIP ON CREATE
8505+ if diff.Id () == " " {
8506+ return nil
8507+ }
8508+
8509+ // 2. PREPARE TO UPDATE THE FULL LIST
8510+ oldNodePools := diff.Get (" node_pool" ). ([]interface{})
8511+ newNodePools := make([]interface{}, len (oldNodePools))
8512+ listChanged := false
8513+
8514+ // We need Raw Config to check what the user actually wrote
8515+ rawConfig := diff.GetRawConfig ()
8516+ rawNodePools := rawConfig.GetAttr (" node_pool" )
8517+
8518+ // 3. ITERATE OVER ALL POOLS IN STATE
8519+ for i, np := range oldNodePools {
8520+ // Deep copy the node pool map
8521+ npMap := np. (map[string]interface{})
8522+ newNpMap := make(map[string]interface{})
8523+ for k, v := range npMap {
8524+ newNpMap[k] = v
8525+ }
8526+
8527+ // Check if this specific node pool is actually defined in the Raw Config (Inline).
8528+ // If it is not in Raw Config, it is a Standalone resource (or API generated).
8529+ // We must not touch Standalone resources from the Cluster resource.
8530+ isInline := false
8531+ currentName := npMap[" name" ]. (string)
8532+
8533+ // Iterate over Raw Config to find a match by name
8534+ if !rawNodePools.IsNull () && rawNodePools.Type ().IsCollectionType () {
8535+ it := rawNodePools.ElementIterator ()
8536+ for it.Next () {
8537+ _, val := it.Element ()
8538+ rawNameVal := val.GetAttr (" name" )
8539+ if !rawNameVal.IsNull () && rawNameVal.AsString () == currentName {
8540+ isInline = true
8541+ break
8542+ }
8543+ }
8544+ }
8545+
8546+ // If this is NOT an inline pool, copy it as-is and skip logic.
8547+ if !isInline {
8548+ newNodePools[i] = newNpMap
8549+ continue
8550+ }
8551+
8552+ // A. DETECT USER CONFIG (Raw Config Check for this specific pool)
8553+ userHasAdditionalConfigs := false
8554+
8555+ // Re-find the specific raw block for logic checking
8556+ if !rawNodePools.IsNull () {
8557+ it := rawNodePools.ElementIterator ()
8558+ for it.Next () {
8559+ _, val := it.Element ()
8560+ rawNameVal := val.GetAttr (" name" )
8561+ if !rawNameVal.IsNull () && rawNameVal.AsString () == currentName {
8562+ // We found the matching raw block , now check its network config
8563+ rawNc := val.GetAttr (" network_config" )
8564+ if !rawNc.IsNull () && rawNc.Type ().IsCollectionType () {
8565+ ncIt := rawNc.ElementIterator ()
8566+ for ncIt.Next () {
8567+ _, ncVal := ncIt.Element ()
8568+ userConfig := ncVal.GetAttr (" additional_node_network_configs" )
8569+ if !userConfig.IsNull () && userConfig.LengthInt () > 0 {
8570+ userHasAdditionalConfigs = true
8571+ }
8572+ }
8573+ }
8574+ break
8575+ }
8576+ }
8577+ }
8578+
8579+ // B. CHECK TRANSITION LOGIC
8580+ shouldClear := false
8581+ basePath := fmt.Sprintf (" node_pool.%d " , i)
8582+ networkConfigPath := basePath + " .network_config.0"
8583+
8584+ oldProfile, newProfile := diff.GetChange (networkConfigPath + " .accelerator_network_profile" )
8585+
8586+ newProfileStr := " "
8587+ if newProfile != nil { newProfileStr = newProfile. (string) }
8588+ oldProfileStr := " "
8589+ if oldProfile != nil { oldProfileStr = oldProfile. (string) }
8590+
8591+ anpIsActive := newProfileStr != " "
8592+ anpIsChanging := oldProfileStr != newProfileStr
8593+
8594+ if !userHasAdditionalConfigs {
8595+ if anpIsActive && anpIsChanging {
8596+ shouldClear = true
8597+ }
8598+ if !anpIsActive {
8599+ shouldClear = true
8600+ }
8601+ }
8602+
8603+ // Check if additional configs currently exist to avoid no-op
8604+ currentCount := 0
8605+ if c, ok := diff.Get (networkConfigPath + " .additional_node_network_configs.#" ). (int); ok {
8606+ currentCount = c
8607+ }
8608+ if shouldClear && currentCount == 0 {
8609+ shouldClear = false
8610+ }
8611+
8612+ // C. APPLY FIX TO THE MAP
8613+ if shouldClear {
8614+ log.Printf (" [DEBUG] Cluster ANP CustomizeDiff: Clearing additional configs for INLINE pool %s " , currentName)
8615+
8616+ var newConfigMap map[string]interface{}
8617+
8618+ if ncList, ok := newNpMap[" network_config" ]. ([]interface{}); ok && len (ncList) > 0 {
8619+ if existingMap, ok := ncList[0]. (map[string]interface{}); ok {
8620+ newConfigMap = make(map[string]interface{})
8621+ for k, v := range existingMap {
8622+ newConfigMap[k] = v
8623+ }
8624+ }
8625+ }
8626+
8627+ if newConfigMap == nil {
8628+ newConfigMap = make(map[string]interface{})
8629+ }
8630+
8631+ newConfigMap[" additional_node_network_configs" ] = []interface{}{}
8632+
8633+ if !anpIsActive {
8634+ newConfigMap[" accelerator_network_profile" ] = " "
8635+ }
8636+
8637+ newNpMap[" network_config" ] = []interface{}{newConfigMap}
8638+ listChanged = true
8639+ }
8640+
8641+ newNodePools[i] = newNpMap
8642+ }
8643+
8644+ // 4. WRITE THE FULL LIST BACK
8645+ if listChanged {
8646+ return diff.SetNew (" node_pool" , newNodePools)
8647+ }
8648+
8649+ return nil
8650+ }
8651+ {{- end }}
0 commit comments