istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/translate/translate_common.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package translate
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"google.golang.org/protobuf/types/known/wrapperspb"
    21  
    22  	"istio.io/api/operator/v1alpha1"
    23  	"istio.io/istio/operator/pkg/name"
    24  	"istio.io/istio/operator/pkg/tpath"
    25  	"istio.io/istio/operator/pkg/util"
    26  )
    27  
    28  // IsComponentEnabledInSpec reports whether the given component is enabled in the given spec.
    29  // IsComponentEnabledInSpec assumes that controlPlaneSpec has been validated.
    30  // TODO: remove extra validations when comfort level is high enough.
    31  func IsComponentEnabledInSpec(componentName name.ComponentName, controlPlaneSpec *v1alpha1.IstioOperatorSpec) (bool, error) {
    32  	componentNodeI, found, err := tpath.GetFromStructPath(controlPlaneSpec, "Components."+string(componentName)+".Enabled")
    33  	if err != nil {
    34  		return false, fmt.Errorf("error in IsComponentEnabledInSpec GetFromStructPath componentEnabled for component=%s: %s",
    35  			componentName, err)
    36  	}
    37  	if !found || componentNodeI == nil {
    38  		return false, nil
    39  	}
    40  	componentNode, ok := componentNodeI.(*wrapperspb.BoolValue)
    41  	if !ok {
    42  		return false, fmt.Errorf("component %s enabled has bad type %T, expect *v1alpha1.BoolValueForPB", componentName, componentNodeI)
    43  	}
    44  	if componentNode == nil {
    45  		return false, nil
    46  	}
    47  	return componentNode.Value, nil
    48  }
    49  
    50  // IsComponentEnabledFromValue get whether component is enabled in helm value.yaml tree.
    51  // valuePath points to component path in the values tree.
    52  func IsComponentEnabledFromValue(cn name.ComponentName, valueSpec map[string]any) (enabled bool, pathExist bool, err error) {
    53  	t := NewTranslator()
    54  	cnMap, ok := t.ComponentMaps[cn]
    55  	if !ok {
    56  		return false, false, nil
    57  	}
    58  	valuePath := cnMap.ToHelmValuesTreeRoot
    59  	enabledPath := valuePath + ".enabled"
    60  	enableNodeI, found, err := tpath.Find(valueSpec, util.ToYAMLPath(enabledPath))
    61  	if err != nil {
    62  		return false, false, fmt.Errorf("error finding component enablement path: %s in helm value.yaml tree", enabledPath)
    63  	}
    64  	if !found {
    65  		// Some components do not specify enablement should be treated as enabled if the root node in the component subtree exists.
    66  		_, found, err := tpath.Find(valueSpec, util.ToYAMLPath(valuePath))
    67  		if err != nil {
    68  			return false, false, err
    69  		}
    70  		if found {
    71  			return true, false, nil
    72  		}
    73  		return false, false, nil
    74  	}
    75  	enableNode, ok := enableNodeI.(bool)
    76  	if !ok {
    77  		return false, true, fmt.Errorf("node at valuePath %s has bad type %T, expect bool", enabledPath, enableNodeI)
    78  	}
    79  	return enableNode, true, nil
    80  }
    81  
    82  // OverlayValuesEnablement overlays any enablement in values path from the user file overlay or set flag overlay.
    83  // The overlay is translated from values to the corresponding addonComponents enablement paths.
    84  func OverlayValuesEnablement(baseYAML, fileOverlayYAML, setOverlayYAML string) (string, error) {
    85  	overlayYAML, err := util.OverlayYAML(fileOverlayYAML, setOverlayYAML)
    86  	if err != nil {
    87  		return "", fmt.Errorf("could not overlay user config over base: %s", err)
    88  	}
    89  
    90  	return YAMLTree(overlayYAML, baseYAML, name.ValuesEnablementPathMap)
    91  }
    92  
    93  // GetEnabledComponents get all the enabled components from the given istio operator spec
    94  func GetEnabledComponents(iopSpec *v1alpha1.IstioOperatorSpec) ([]string, error) {
    95  	var enabledComponents []string
    96  	if iopSpec.Components != nil {
    97  		for _, c := range name.AllCoreComponentNames {
    98  			enabled, err := IsComponentEnabledInSpec(c, iopSpec)
    99  			if err != nil {
   100  				return nil, fmt.Errorf("failed to check if component: %s is enabled or not: %v", string(c), err)
   101  			}
   102  			if enabled {
   103  				enabledComponents = append(enabledComponents, string(c))
   104  			}
   105  		}
   106  		for _, c := range iopSpec.Components.IngressGateways {
   107  			if c != nil && c.Enabled.GetValue() {
   108  				enabledComponents = append(enabledComponents, string(name.IngressComponentName))
   109  				break
   110  			}
   111  		}
   112  		for _, c := range iopSpec.Components.EgressGateways {
   113  			if c != nil && c.Enabled.GetValue() {
   114  				enabledComponents = append(enabledComponents, string(name.EgressComponentName))
   115  				break
   116  			}
   117  		}
   118  	}
   119  
   120  	return enabledComponents, nil
   121  }