istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/status/distribution/reporter_test.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 distribution
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	. "github.com/onsi/gomega"
    22  	"k8s.io/utils/clock"
    23  
    24  	"istio.io/istio/pilot/pkg/status"
    25  	"istio.io/istio/pilot/pkg/xds"
    26  	"istio.io/istio/pkg/config"
    27  	"istio.io/istio/pkg/config/schema/collections"
    28  	"istio.io/istio/pkg/ledger"
    29  	"istio.io/istio/pkg/util/sets"
    30  )
    31  
    32  func TestStatusMaps(t *testing.T) {
    33  	r := initReporterWithoutStarting()
    34  	typ := ""
    35  	r.processEvent("conA", typ, "a")
    36  	r.processEvent("conB", typ, "a")
    37  	r.processEvent("conC", typ, "c")
    38  	r.processEvent("conD", typ, "d")
    39  	RegisterTestingT(t)
    40  	x := struct{}{}
    41  	Expect(r.status).To(Equal(map[string]string{"conA~": "a", "conB~": "a", "conC~": "c", "conD~": "d"}))
    42  	Expect(r.reverseStatus).To(Equal(map[string]sets.String{"a": {"conA~": x, "conB~": x}, "c": {"conC~": x}, "d": {"conD~": x}}))
    43  	r.processEvent("conA", typ, "d")
    44  	Expect(r.status).To(Equal(map[string]string{"conA~": "d", "conB~": "a", "conC~": "c", "conD~": "d"}))
    45  	Expect(r.reverseStatus).To(Equal(map[string]sets.String{"a": {"conB~": x}, "c": {"conC~": x}, "d": {"conD~": x, "conA~": x}}))
    46  	r.RegisterDisconnect("conA", sets.New[xds.EventType](typ))
    47  	Expect(r.status).To(Equal(map[string]string{"conB~": "a", "conC~": "c", "conD~": "d"}))
    48  	Expect(r.reverseStatus).To(Equal(map[string]sets.String{"a": {"conB~": x}, "c": {"conC~": x}, "d": {"conD~": x}}))
    49  }
    50  
    51  func initReporterWithoutStarting() (out Reporter) {
    52  	out.PodName = "tespod"
    53  	out.inProgressResources = map[string]*inProgressEntry{}
    54  	out.client = nil              // TODO
    55  	out.clock = clock.RealClock{} // TODO
    56  	out.UpdateInterval = 300 * time.Millisecond
    57  	out.cm = nil // TODO
    58  	out.reverseStatus = make(map[string]sets.String)
    59  	out.status = make(map[string]string)
    60  	return
    61  }
    62  
    63  func TestBuildReport(t *testing.T) {
    64  	RegisterTestingT(t)
    65  	r := initReporterWithoutStarting()
    66  	r.ledger = ledger.Make(time.Minute)
    67  	resources := []*config.Config{
    68  		{
    69  			Meta: config.Meta{
    70  				Namespace:       "default",
    71  				Name:            "foo",
    72  				ResourceVersion: "1",
    73  			},
    74  		},
    75  		{
    76  			Meta: config.Meta{
    77  				Namespace:       "default",
    78  				Name:            "bar",
    79  				ResourceVersion: "1",
    80  			},
    81  		},
    82  		{
    83  			Meta: config.Meta{
    84  				Namespace:       "alternate",
    85  				Name:            "boo",
    86  				ResourceVersion: "1",
    87  			},
    88  		},
    89  	}
    90  	// cast our model.Configs to Resource because these types aren't compatible
    91  	var myResources []status.Resource
    92  	col := collections.VirtualService
    93  	for _, res := range resources {
    94  		// Set Group Version and GroupVersionKind to real world values from VS
    95  		res.GroupVersionKind = col.GroupVersionKind()
    96  		myResources = append(myResources, status.ResourceFromModelConfig(*res))
    97  		// Add each resource to our ledger for tracking history
    98  		// mark each of our resources as in flight so they are included in the report.
    99  		r.AddInProgressResource(*res)
   100  	}
   101  	firstNoncePrefix := r.ledger.RootHash()
   102  	connections := []string{
   103  		"conA", "conB", "conC",
   104  	}
   105  	// mark each fake connection as having acked version 1 of all resources
   106  	for _, con := range connections {
   107  		r.processEvent(con, "", firstNoncePrefix)
   108  	}
   109  	// modify one resource to version 2
   110  	resources[1].Generation = int64(2)
   111  	myResources[1].Generation = "2"
   112  	// notify the ledger of the new version
   113  	r.AddInProgressResource(*resources[1])
   114  	// mark only one connection as having acked version 2
   115  	r.processEvent(connections[1], "", r.ledger.RootHash())
   116  	// mark one connection as having disconnected.
   117  	r.RegisterDisconnect(connections[2], sets.New[xds.EventType](""))
   118  	// build a report, which should have only two dataplanes, with 50% acking v2 of config
   119  	rpt, prunes := r.buildReport()
   120  	r.removeCompletedResource(prunes)
   121  	Expect(rpt.DataPlaneCount).To(Equal(2))
   122  	Expect(rpt.InProgressResources).To(Equal(map[string]int{
   123  		myResources[0].String(): 2,
   124  		myResources[1].String(): 1,
   125  		myResources[2].String(): 2,
   126  	}))
   127  	Expect(r.inProgressResources).NotTo(ContainElement(resources[0]))
   128  }