istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/cluster/clusters.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 cluster
    16  
    17  import (
    18  	"fmt"
    19  	"sort"
    20  
    21  	"istio.io/istio/pkg/util/sets"
    22  )
    23  
    24  // Clusters is an ordered list of Cluster instances.
    25  type Clusters []Cluster
    26  
    27  func (c Clusters) Len() int {
    28  	return len(c)
    29  }
    30  
    31  // IsMulticluster is a utility method that indicates whether there are multiple Clusters available.
    32  func (c Clusters) IsMulticluster() bool {
    33  	return c.Len() > 1
    34  }
    35  
    36  // Default returns the first cluster in the list.
    37  func (c Clusters) Default() Cluster {
    38  	return c[0]
    39  }
    40  
    41  // GetOrDefault returns the given cluster if non-nil. Otherwise returns the first
    42  // Cluster in the list.
    43  func (c Clusters) GetOrDefault(cluster Cluster) Cluster {
    44  	if cluster != nil {
    45  		return cluster
    46  	}
    47  	return c.Default()
    48  }
    49  
    50  // GetByName returns the Cluster with the given name or nil if it is not in the list.
    51  func (c Clusters) GetByName(name string) Cluster {
    52  	for _, cc := range c {
    53  		if cc.Name() == name {
    54  			return cc
    55  		}
    56  	}
    57  	return nil
    58  }
    59  
    60  // Contains returns true if a cluster with the given name is found in the list.
    61  func (c Clusters) Contains(cc Cluster) bool {
    62  	return c.GetByName(cc.Name()) != nil
    63  }
    64  
    65  // Names returns the deduped list of names of the clusters.
    66  func (c Clusters) Names() []string {
    67  	dedup := sets.String{}
    68  	for _, cc := range c {
    69  		dedup.Insert(cc.Name())
    70  	}
    71  	return dedup.UnsortedList()
    72  }
    73  
    74  type ClustersByNetwork map[string]Clusters
    75  
    76  func (c ClustersByNetwork) Networks() []string {
    77  	out := make([]string, 0, len(c))
    78  	for n := range c {
    79  		out = append(out, n)
    80  	}
    81  	sort.Strings(out)
    82  	return out
    83  }
    84  
    85  // ByNetwork returns a map of network name to a subset of clusters
    86  func (c Clusters) ByNetwork() ClustersByNetwork {
    87  	out := make(ClustersByNetwork)
    88  	for _, cc := range c {
    89  		out[cc.NetworkName()] = append(out[cc.NetworkName()], cc)
    90  	}
    91  	return out
    92  }
    93  
    94  // Networks returns the list of network names for the clusters.
    95  func (c Clusters) Networks() []string {
    96  	return c.ByNetwork().Networks()
    97  }
    98  
    99  // ForNetworks returns the list of clusters in the given networks.
   100  func (c Clusters) ForNetworks(networks ...string) Clusters {
   101  	out := make(Clusters, 0, len(c))
   102  	for _, cc := range c {
   103  		for _, network := range networks {
   104  			if cc.NetworkName() == network {
   105  				out = append(out, cc)
   106  				break
   107  			}
   108  		}
   109  	}
   110  	return out
   111  }
   112  
   113  // Primaries returns the subset that are primary clusters.
   114  func (c Clusters) Primaries(excluded ...Cluster) Clusters {
   115  	return c.filterClusters(func(cc Cluster) bool {
   116  		return cc.IsPrimary()
   117  	}, exclude(excluded...))
   118  }
   119  
   120  // Exclude returns all clusters not given as input.
   121  func (c Clusters) Exclude(excluded ...Cluster) Clusters {
   122  	return c.filterClusters(func(cc Cluster) bool {
   123  		return true
   124  	}, exclude(excluded...))
   125  }
   126  
   127  // Configs returns the subset that are config clusters.
   128  func (c Clusters) Configs(excluded ...Cluster) Clusters {
   129  	return c.filterClusters(func(cc Cluster) bool {
   130  		return cc.IsConfig()
   131  	}, exclude(excluded...))
   132  }
   133  
   134  // Remotes returns the subset that are remote clusters.
   135  func (c Clusters) Remotes(excluded ...Cluster) Clusters {
   136  	return c.filterClusters(func(cc Cluster) bool {
   137  		return cc.IsRemote()
   138  	}, exclude(excluded...))
   139  }
   140  
   141  // MeshClusters returns the subset that are not external control plane clusters.
   142  func (c Clusters) MeshClusters(excluded ...Cluster) Clusters {
   143  	return c.filterClusters(func(cc Cluster) bool {
   144  		return !cc.IsExternalControlPlane()
   145  	}, exclude(excluded...))
   146  }
   147  
   148  // IsExternalControlPlane indicates whether the clusters are set up in an enternal
   149  // control plane configuration. An external control plane is a primary cluster that
   150  // gets its Istio configuration from a different cluster.
   151  func (c Clusters) IsExternalControlPlane() bool {
   152  	for _, cc := range c {
   153  		if cc.IsExternalControlPlane() {
   154  			return true
   155  		}
   156  	}
   157  	return false
   158  }
   159  
   160  // Kube returns OfKind(cluster.Kubernetes)
   161  func (c Clusters) Kube() Clusters {
   162  	return c.OfKind(Kubernetes)
   163  }
   164  
   165  // OfKind filters clusters by their Kind.
   166  func (c Clusters) OfKind(kind Kind) Clusters {
   167  	return c.filterClusters(func(cc Cluster) bool {
   168  		return cc.Kind() == kind
   169  	}, none)
   170  }
   171  
   172  func none(Cluster) bool {
   173  	return false
   174  }
   175  
   176  func exclude(exclude ...Cluster) func(Cluster) bool {
   177  	return func(cc Cluster) bool {
   178  		for _, e := range exclude {
   179  			if cc.Name() == e.Name() {
   180  				return true
   181  			}
   182  		}
   183  		return false
   184  	}
   185  }
   186  
   187  func (c Clusters) filterClusters(included func(Cluster) bool,
   188  	excluded func(Cluster) bool,
   189  ) Clusters {
   190  	var out Clusters
   191  	for _, cc := range c {
   192  		if !excluded(cc) && included(cc) {
   193  			out = append(out, cc)
   194  		}
   195  	}
   196  	return out
   197  }
   198  
   199  func (c Clusters) String() string {
   200  	return fmt.Sprintf("%v", c.Names())
   201  }