istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/echo/instances.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 echo
    16  
    17  import (
    18  	"errors"
    19  	"sort"
    20  
    21  	"github.com/hashicorp/go-multierror"
    22  
    23  	"istio.io/istio/pkg/test"
    24  	"istio.io/istio/pkg/test/framework/components/cluster"
    25  )
    26  
    27  var _ Target = Instances{}
    28  
    29  // Instances contains the instances created by the builder with methods for filtering
    30  type Instances []Instance
    31  
    32  func (i Instances) ServiceName() string {
    33  	return i.Config().Service
    34  }
    35  
    36  func (i Instances) NamespaceName() string {
    37  	return i.Config().NamespaceName()
    38  }
    39  
    40  func (i Instances) ServiceAccountName() string {
    41  	return i.Config().ServiceAccountName()
    42  }
    43  
    44  func (i Instances) ClusterLocalFQDN() string {
    45  	return i.Config().ClusterLocalFQDN()
    46  }
    47  
    48  func (i Instances) ClusterSetLocalFQDN() string {
    49  	return i.Config().ClusterSetLocalFQDN()
    50  }
    51  
    52  func (i Instances) NamespacedName() NamespacedName {
    53  	return i.Config().NamespacedName()
    54  }
    55  
    56  func (i Instances) PortForName(name string) Port {
    57  	return i.Config().Ports.MustForName(name)
    58  }
    59  
    60  func (i Instances) Config() Config {
    61  	return i.mustGetFirst().Config()
    62  }
    63  
    64  func (i Instances) Instances() Instances {
    65  	return i
    66  }
    67  
    68  func (i Instances) mustGetFirst() Instance {
    69  	if i.Len() == 0 {
    70  		panic("instances are empty")
    71  	}
    72  	return i[0]
    73  }
    74  
    75  // Callers is a convenience method to convert Instances into Callers.
    76  func (i Instances) Callers() Callers {
    77  	var out Callers
    78  	for _, instance := range i {
    79  		out = append(out, instance)
    80  	}
    81  	return out
    82  }
    83  
    84  // Clusters returns a list of cluster names that the instances are deployed in
    85  func (i Instances) Clusters() cluster.Clusters {
    86  	clusters := map[string]cluster.Cluster{}
    87  	for _, instance := range i {
    88  		clusters[instance.Config().Cluster.Name()] = instance.Config().Cluster
    89  	}
    90  	out := make(cluster.Clusters, 0, len(clusters))
    91  	for _, c := range clusters {
    92  		out = append(out, c)
    93  	}
    94  	return out
    95  }
    96  
    97  // ForCluster returns a list of instances that match the cluster name
    98  func (i Instances) ForCluster(name string) Instances {
    99  	out := make(Instances, 0, len(i))
   100  	for _, c := range i {
   101  		if c.Config().Cluster.Name() == name {
   102  			out = append(out, c)
   103  		}
   104  	}
   105  	return out
   106  }
   107  
   108  func (i Instances) Workloads() (Workloads, error) {
   109  	var out Workloads
   110  	for _, inst := range i {
   111  		ws, err := inst.Workloads()
   112  		if err != nil {
   113  			return nil, err
   114  		}
   115  		out = append(out, ws...)
   116  	}
   117  
   118  	if len(out) == 0 {
   119  		return nil, errors.New("got 0 workloads")
   120  	}
   121  
   122  	return out, nil
   123  }
   124  
   125  func (i Instances) WorkloadsOrFail(t test.Failer) Workloads {
   126  	t.Helper()
   127  	out, err := i.Workloads()
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	return out
   132  }
   133  
   134  func (i Instances) MustWorkloads() Workloads {
   135  	out, err := i.Workloads()
   136  	if err != nil {
   137  		panic(err)
   138  	}
   139  	return out
   140  }
   141  
   142  // IsDeployment returns true if there is only one deployment contained in the Instances
   143  func (i Instances) IsDeployment() bool {
   144  	return len(i.Services()) == 1
   145  }
   146  
   147  func (i Instances) ContainsTarget(t Target) bool {
   148  	return i.Contains(t.Instances()...)
   149  }
   150  
   151  func (i Instances) Contains(instances ...Instance) bool {
   152  	for _, thatI := range instances {
   153  		found := false
   154  		for _, thisI := range i {
   155  			if thisI == thatI {
   156  				found = true
   157  				break
   158  			}
   159  		}
   160  		if !found {
   161  			return false
   162  		}
   163  	}
   164  	return true
   165  }
   166  
   167  // Services groups the Instances by FQDN. Each returned element is an Instances
   168  // containing only instances of a single service.
   169  func (i Instances) Services() Services {
   170  	grouped := map[string]Instances{}
   171  	for _, instance := range i {
   172  		k := instance.Config().ClusterLocalFQDN()
   173  		grouped[k] = append(grouped[k], instance)
   174  	}
   175  	var out Services
   176  	for _, deployment := range grouped {
   177  		out = append(out, deployment)
   178  	}
   179  	sort.Stable(out)
   180  	return out
   181  }
   182  
   183  // Copy this Instances array.
   184  func (i Instances) Copy() Instances {
   185  	return append(Instances{}, i...)
   186  }
   187  
   188  // Append returns a new Instances array with the given values appended.
   189  func (i Instances) Append(instances Instances) Instances {
   190  	return append(i.Copy(), instances...)
   191  }
   192  
   193  // Restart each Instance
   194  func (i Instances) Restart() error {
   195  	g := multierror.Group{}
   196  	for _, app := range i {
   197  		app := app
   198  		g.Go(app.Restart)
   199  	}
   200  	return g.Wait().ErrorOrNil()
   201  }
   202  
   203  func (i Instances) Len() int {
   204  	return len(i)
   205  }
   206  
   207  func (i Instances) NamespacedNames() NamespacedNames {
   208  	out := make(NamespacedNames, 0, i.Len())
   209  	for _, ii := range i {
   210  		out = append(out, ii.NamespacedName())
   211  	}
   212  
   213  	sort.Stable(out)
   214  	return out
   215  }