Repository: kumahq/kuma
Pull request #3821 (2022-02-14 09:31:53)

chore(deps): bump github.com/sethvargo/go-retry from 0.2.2 to 0.2.3
Bumps [github.com/sethvargo/go-retry](https://github.com/sethvargo/go-retry) from 0.2.2 to 0.2.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/sethvargo/go-retry/releases">github.com/sethvargo/go-retry's releases</a>.</em></p>
<blockquote>
<h2>v0.2.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Small refactor cancel context by <a href="https://github.com/tinoquang"><code>@​tinoquang</code></a> in <a href="https://github-redirect.dependabot.com/sethvargo/go-retry/pull/11">sethvargo/go-retry#11</a></li>
<li>Handle overflow cases by <a href="https://github.com/sethvargo"><code>@​sethvargo</code></a> in <a href="https://github-redirect.dependabot.com/sethvargo/go-retry/pull/13">sethvargo/go-retry#13</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/tinoquang"><code>@​tinoquang</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/sethvargo/go-retry/pull/11">sethvargo/go-retry#11</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/sethvargo/go-retry/compare/v0.2.2...v0.2.3">https://github.com/sethvargo/go-retry/compare/v0.2.2...v0.2.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/sethvargo/go-retry/commit/009eed153ec9d7ba75ed381c7d93e4af600acae8"><code>009eed1</code></a> Handle overflow cases (<a href="https://github-redirect.dependabot.com/sethvargo/go-retry/issues/13">#13</a>)</li>
<li><a href="https://github.com/sethvargo/go-retry/commit/7a0bb9fc5c819043e9bc63bbbf88e9a6a411b655"><code>7a0bb9f</code></a> Don't leak timer</li>
<li><a href="https://github.com/sethvargo/go-retry/commit/f691e5cece1148685047296ec21c0198d3c0bd20"><code>f691e5c</code></a> refactor cancel context (<a href="https://github-redirect.dependabot.com/sethvargo/go-retry/issues/11">#11</a>)</li>
<li>See full diff in <a href="https://github.com/sethvargo/go-retry/compare/v0.2.2...v0.2.3">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/sethvargo/go-retry&package-manager=go_modules&previous-version=0.2.2&new-version=0.2.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

codecov-commenter: # [Codecov](https://codecov.io/gh/kumahq/kuma/pull/3821?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq) Report
> Merging [#3821](https://codecov.io/gh/kumahq/kuma/pull/3821?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq) (fdb1fef) into [master](https://codecov.io/gh/kumahq/kuma/commit/3a1dcfcf5026519fd710ac4844fbc9c5b3d42a19?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq) (3a1dcfc) will **decrease** coverage by `0.01%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/kumahq/kuma/pull/3821/graphs/tree.svg?width=650&height=150&src=pr&token=D7Yvqs6rwV&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq)](https://codecov.io/gh/kumahq/kuma/pull/3821?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq)

```diff
@@            Coverage Diff             @@
##           master    #3821      +/-   ##
==========================================
- Coverage   56.02%   56.00%   -0.02%     
==========================================
  Files         909      909              
  Lines       54199    54199              
==========================================
- Hits        30365    30355      -10     
- Misses      21404    21417      +13     
+ Partials     2430     2427       -3     
```


| [Impacted Files](https://codecov.io/gh/kumahq/kuma/pull/3821?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq) | Coverage Δ | |
|---|---|---|
| [pkg/insights/components.go](https://codecov.io/gh/kumahq/kuma/pull/3821/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq#diff-cGtnL2luc2lnaHRzL2NvbXBvbmVudHMuZ28=) | `70.00% <0.00%> (-30.00%)` | :arrow_down: |
| [pkg/events/eventbus.go](https://codecov.io/gh/kumahq/kuma/pull/3821/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq#diff-cGtnL2V2ZW50cy9ldmVudGJ1cy5nbw==) | `85.18% <0.00%> (-7.41%)` | :arrow_down: |
| [pkg/plugins/runtime/gateway/route/sorter.go](https://codecov.io/gh/kumahq/kuma/pull/3821/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq#diff-cGtnL3BsdWdpbnMvcnVudGltZS9nYXRld2F5L3JvdXRlL3NvcnRlci5nbw==) | `66.66% <0.00%> (-5.13%)` | :arrow_down: |
| [pkg/insights/resyncer.go](https://codecov.io/gh/kumahq/kuma/pull/3821/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq#diff-cGtnL2luc2lnaHRzL3Jlc3luY2VyLmdv) | `71.16% <0.00%> (-2.46%)` | :arrow_down: |
| [pkg/xds/generator/direct\_access\_proxy\_generator.go](https://codecov.io/gh/kumahq/kuma/pull/3821/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq#diff-cGtnL3hkcy9nZW5lcmF0b3IvZGlyZWN0X2FjY2Vzc19wcm94eV9nZW5lcmF0b3IuZ28=) | `88.76% <0.00%> (+1.12%)` | :arrow_up: |
| [pkg/core/resources/manager/cache.go](https://codecov.io/gh/kumahq/kuma/pull/3821/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq#diff-cGtnL2NvcmUvcmVzb3VyY2VzL21hbmFnZXIvY2FjaGUuZ28=) | `88.31% <0.00%> (+5.19%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/kumahq/kuma/pull/3821?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/kumahq/kuma/pull/3821?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq). Last update [3a1dcfc...fdb1fef](https://codecov.io/gh/kumahq/kuma/pull/3821?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kumahq).


Patch:
diff --git a/go.mod b/go.mod
index c4a363a9a..036193c4f 100644
--- a/go.mod
+++ b/go.mod
@@ -37,7 +37,7 @@ require (
 	github.com/prometheus/client_model v0.2.0
 	github.com/prometheus/common v0.32.1
 	github.com/prometheus/prometheus v0.0.0-00010101000000-000000000000
-	github.com/sethvargo/go-retry v0.2.2
+	github.com/sethvargo/go-retry v0.2.3
 	github.com/slok/go-http-metrics v0.10.0
 	github.com/soheilhy/cmux v0.1.5
 	github.com/spf13/cobra v1.3.0
@@ -47,7 +47,7 @@ require (
 	github.com/spiffe/spire v1.2.0
 	github.com/testcontainers/testcontainers-go v0.12.0
 	go.uber.org/multierr v1.7.0
-	go.uber.org/zap v1.20.0
+	go.uber.org/zap v1.21.0
 	golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 	golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a
diff --git a/go.sum b/go.sum
index b023ede6c..28d331b7f 100644
--- a/go.sum
+++ b/go.sum
@@ -1537,8 +1537,8 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/sethvargo/go-retry v0.2.2 h1:TGPxHlApEgiGZHaxrfFN2U+wHEuK3V6KASblJzt78Yc=
-github.com/sethvargo/go-retry v0.2.2/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw=
+github.com/sethvargo/go-retry v0.2.3 h1:oYlgvIvsju3jNbottWABtbnoLC+GDtLdBHxKWxQm/iU=
+github.com/sethvargo/go-retry v0.2.3/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw=
 github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
 github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
@@ -1782,8 +1782,8 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
 go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
 go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
-go.uber.org/zap v1.20.0 h1:N4oPlghZwYG55MlU6LXk/Zp00FVNE9X9wrYO8CEs4lc=
-go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
+go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
+go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 goji.io v2.0.2+incompatible/go.mod h1:sbqFwrtqZACxLBTQcdgVjFh54yGVCvwq8+w49MVMMIk=
 golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
diff --git a/pkg/api-server/inspect_endpoints.go b/pkg/api-server/inspect_endpoints.go
index e5d15cbc0..b9d4cd450 100644
--- a/pkg/api-server/inspect_endpoints.go
+++ b/pkg/api-server/inspect_endpoints.go
@@ -38,6 +38,8 @@ func (f fakeDataSourceLoader) Load(ctx context.Context, mesh string, source *sys
 	return []byte("secret"), nil
 }
 
+var CustomizeProxy func(meshContext xds_context.MeshContext, proxy *core_xds.Proxy) error
+
 func getMatchedPolicies(cfg *kuma_cp.Config, meshContext xds_context.MeshContext, dataplaneKey core_model.ResourceKey) (*core_xds.MatchedPolicies, *core_mesh.DataplaneResource, error) {
 	proxyBuilder := sync.DefaultDataplaneProxyBuilder(
 		&fakeDataSourceLoader{},
@@ -47,6 +49,11 @@ func getMatchedPolicies(cfg *kuma_cp.Config, meshContext xds_context.MeshContext
 	if proxy, err := proxyBuilder.Build(dataplaneKey, meshContext); err != nil {
 		return nil, nil, err
 	} else {
+		if CustomizeProxy != nil {
+			if err := CustomizeProxy(meshContext, proxy); err != nil {
+				return nil, nil, err
+			}
+		}
 		return &proxy.Policies, proxy.Dataplane, nil
 	}
 }
diff --git a/pkg/core/xds/matched_policies.go b/pkg/core/xds/matched_policies.go
index 6eda838bc..d79212dc4 100644
--- a/pkg/core/xds/matched_policies.go
+++ b/pkg/core/xds/matched_policies.go
@@ -11,9 +11,10 @@ import (
 
 type MatchedPolicies struct {
 	// Inbound(Listener) -> Policy
-	TrafficPermissions TrafficPermissionMap
-	FaultInjections    FaultInjectionMap
-	RateLimitsInbound  InboundRateLimitsMap
+	TrafficPermissions    TrafficPermissionMap
+	FaultInjections       FaultInjectionMap
+	RateLimitsInbound     InboundRateLimitsMap
+	CustomInboundPolicies []map[mesh_proto.InboundInterface]core_model.Resource
 
 	// Service(Cluster) -> Policy
 	TrafficLogs     TrafficLogMap
@@ -184,6 +185,11 @@ func getInboundMatchedPolicies(matchedPolicies *MatchedPolicies) map[mesh_proto.
 			result[inbound] = append(result[inbound], rl)
 		}
 	}
+	for _, customPolicy := range matchedPolicies.CustomInboundPolicies {
+		for inbound, customList := range customPolicy {
+			result[inbound] = append(result[inbound], customList)
+		}
+	}
 
 	return result
 }
diff --git a/pkg/kds/context/context.go b/pkg/kds/context/context.go
index 5a2f8fa48..3a9451169 100644
--- a/pkg/kds/context/context.go
+++ b/pkg/kds/context/context.go
@@ -2,10 +2,15 @@ package context
 
 import (
 	"context"
+	"reflect"
 	"strings"
 
+	"github.com/pkg/errors"
+	"google.golang.org/protobuf/proto"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	"google.golang.org/protobuf/types/known/wrapperspb"
 
+	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
 	system_proto "github.com/kumahq/kuma/api/system/v1alpha1"
 	"github.com/kumahq/kuma/pkg/core"
 	config_manager "github.com/kumahq/kuma/pkg/core/config/manager"
@@ -47,10 +52,59 @@ func DefaultContext(manager manager.ResourceManager, zone string) *Context {
 		GlobalProvidedFilter: GlobalProvidedFilter(manager, configs),
 		ZoneProvidedFilter:   ZoneProvidedFilter(zone),
 		Configs:              configs,
-		GlobalResourceMapper: MapZoneTokenSigningKeyGlobalToPublicKey(ctx, manager),
+		GlobalResourceMapper: CompositeResourceMapper(
+			MapZoneTokenSigningKeyGlobalToPublicKey(ctx, manager),
+			MapInsightResourcesZeroGeneration,
+		),
 	}
 }
 
+// CompositeResourceMapper combines the given ResourceMappers into
+// a single ResourceMapper which calls each in order. If an error
+// occurs, the first one is returned and no further mappers are executed.
+func CompositeResourceMapper(mappers ...reconcile.ResourceMapper) reconcile.ResourceMapper {
+	return func(r model.Resource) (model.Resource, error) {
+		var err error
+		for _, mapper := range mappers {
+			r, err = mapper(r)
+			if err != nil {
+				return r, err
+			}
+		}
+		return r, nil
+	}
+}
+
+type specWithDiscoverySubscriptions interface {
+	GetSubscriptions() []*mesh_proto.DiscoverySubscription
+	ProtoReflect() protoreflect.Message
+}
+
+// MapInsightResourcesZeroGeneration zeros "generation" field in resources for which
+// the field has only local relevance. This prevents reconciliation from unnecessarily
+// deeming the object to have changed.
+func MapInsightResourcesZeroGeneration(r model.Resource) (model.Resource, error) {
+	if spec, ok := r.GetSpec().(specWithDiscoverySubscriptions); ok {
+		spec = proto.Clone(spec).(specWithDiscoverySubscriptions)
+		for _, sub := range spec.GetSubscriptions() {
+			sub.Generation = 0
+		}
+
+		meta := r.GetMeta()
+		resType := reflect.TypeOf(r).Elem()
+
+		newR := reflect.New(resType).Interface().(model.Resource)
+		newR.SetMeta(meta)
+		if err := newR.SetSpec(spec.(model.ResourceSpec)); err != nil {
+			panic(errors.Wrap(err, "error setting spec on resource"))
+		}
+
+		return newR, nil
+	}
+
+	return r, nil
+}
+
 func MapZoneTokenSigningKeyGlobalToPublicKey(
 	_ context.Context,
 	_ manager.ResourceManager,


Test patch:
diff --git a/pkg/kds/context/context_test.go b/pkg/kds/context/context_test.go
index ec2fbf774..a6b88e0e3 100644
--- a/pkg/kds/context/context_test.go
+++ b/pkg/kds/context/context_test.go
@@ -4,6 +4,7 @@ import (
 	stdcontext "context"
 	"fmt"
 
+	"github.com/golang/protobuf/proto"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/ginkgo/extensions/table"
 	. "github.com/onsi/gomega"
@@ -27,6 +28,195 @@ import (
 )
 
 var _ = Describe("Context", func() {
+	Describe("GlobalResourceMapper", func() {
+		var rm manager.ResourceManager
+		var mapper reconcile.ResourceMapper
+
+		type testCase struct {
+			resource model.Resource
+			expect   model.Resource
+		}
+
+		BeforeEach(func() {
+			rm = manager.NewResourceManager(memory.NewStore())
+			defaultContext := context.DefaultContext(rm, "zone")
+			mapper = defaultContext.GlobalResourceMapper
+		})
+
+		DescribeTable("should zero generation field",
+			func(given testCase) {
+				// when
+				out, _ := mapper(given.resource)
+
+				// then
+				Expect(out.GetMeta()).To(Equal(given.expect.GetMeta()))
+				Expect(out.Descriptor()).To(Equal(given.expect.Descriptor()))
+				Expect(proto.Equal(out.GetSpec(), given.expect.GetSpec())).To(BeTrue())
+			},
+			Entry("should zero generation on DataplaneInsight", testCase{
+				resource: &core_mesh.DataplaneInsightResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "dpi-1",
+					},
+					Spec: &mesh_proto.DataplaneInsight{
+						MTLS: &mesh_proto.DataplaneInsight_MTLS{
+							IssuedBackend:     "test",
+							SupportedBackends: []string{"one", "two"},
+						},
+						Subscriptions: []*mesh_proto.DiscoverySubscription{
+							{
+								Id:         "sub1",
+								Generation: 10,
+							},
+							{
+								Id:         "sub2",
+								Generation: 15,
+							},
+						},
+					},
+				},
+				expect: &core_mesh.DataplaneInsightResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "dpi-1",
+					},
+					Spec: &mesh_proto.DataplaneInsight{
+						MTLS: &mesh_proto.DataplaneInsight_MTLS{
+							IssuedBackend:     "test",
+							SupportedBackends: []string{"one", "two"},
+						},
+						Subscriptions: []*mesh_proto.DiscoverySubscription{
+							{
+								Id:         "sub1",
+								Generation: 0,
+							},
+							{
+								Id:         "sub2",
+								Generation: 0,
+							},
+						},
+					},
+				},
+			}),
+			Entry("should zero generation on ZoneIngressInsight", testCase{
+				resource: &core_mesh.ZoneIngressInsightResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "zii-1",
+					},
+					Spec: &mesh_proto.ZoneIngressInsight{
+						Subscriptions: []*mesh_proto.DiscoverySubscription{
+							{
+								ControlPlaneInstanceId: "ID1",
+								Generation:             10,
+							},
+							{
+								ControlPlaneInstanceId: "ID2",
+								Generation:             15,
+							},
+						},
+					},
+				},
+				expect: &core_mesh.ZoneIngressInsightResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "zii-1",
+					},
+					Spec: &mesh_proto.ZoneIngressInsight{
+						Subscriptions: []*mesh_proto.DiscoverySubscription{
+							{
+								ControlPlaneInstanceId: "ID1",
+								Generation:             0,
+							},
+							{
+								ControlPlaneInstanceId: "ID2",
+								Generation:             0,
+							},
+						},
+					},
+				},
+			}),
+			Entry("should zero generation on ZoneEgressInsight", testCase{
+				resource: &core_mesh.ZoneEgressInsightResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "zei-1",
+					},
+					Spec: &mesh_proto.ZoneEgressInsight{
+						Subscriptions: []*mesh_proto.DiscoverySubscription{
+							{
+								Generation: 10,
+							},
+							{
+								Generation: 15,
+							},
+						},
+					},
+				},
+				expect: &core_mesh.ZoneEgressInsightResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "zei-1",
+					},
+					Spec: &mesh_proto.ZoneEgressInsight{
+						Subscriptions: []*mesh_proto.DiscoverySubscription{
+							{
+								Generation: 0,
+							},
+							{
+								Generation: 0,
+							},
+						},
+					},
+				},
+			}),
+			Entry("should not change non-insight", testCase{
+				resource: &core_mesh.CircuitBreakerResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "cb-1",
+					},
+					Spec: &mesh_proto.CircuitBreaker{
+						Sources: []*mesh_proto.Selector{
+							{
+								Match: map[string]string{
+									"match1": "source",
+								},
+							},
+						},
+						Destinations: []*mesh_proto.Selector{
+							{
+								Match: map[string]string{
+									"match2": "dest",
+								},
+							},
+						},
+						Conf: &mesh_proto.CircuitBreaker_Conf{
+							SplitExternalAndLocalErrors: true,
+						},
+					},
+				},
+				expect: &core_mesh.CircuitBreakerResource{
+					Meta: &test_model.ResourceMeta{
+						Name: "cb-1",
+					},
+					Spec: &mesh_proto.CircuitBreaker{
+						Sources: []*mesh_proto.Selector{
+							{
+								Match: map[string]string{
+									"match1": "source",
+								},
+							},
+						},
+						Destinations: []*mesh_proto.Selector{
+							{
+								Match: map[string]string{
+									"match2": "dest",
+								},
+							},
+						},
+						Conf: &mesh_proto.CircuitBreaker_Conf{
+							SplitExternalAndLocalErrors: true,
+						},
+					},
+				},
+			}),
+		)
+	})
 	Describe("GlobalProvidedFilter", func() {
 		var rm manager.ResourceManager
 		var predicate reconcile.ResourceFilter