Repository: kumahq/kuma
Pull request #1345 (2020-12-21 16:11:59)

chore(*) updates suggested by dependabot (bp #1331)
This is an automated backport of pull request #1331 done by Mergify
---


<details>
<summary>Mergify commands and options</summary>

<br />

More conditions and actions can be found in the [documentation](https://docs.mergify.io/).

You can also trigger Mergify actions by commenting on this pull request:

- `@Mergifyio refresh` will re-evaluate the rules
- `@Mergifyio rebase` will rebase this PR on its base branch
- `@Mergifyio update` will merge the base branch into this PR
- `@Mergifyio backport <destination>` will backport this PR on `<destination>` branch

Additionally, on Mergify [dashboard](https://dashboard.mergify.io/) you can:

- look at your merge queues
- generate the Mergify configuration with the config editor.

Finally, you can contact us on https://mergify.io/
</details>



Patch:
diff --git a/api/go.mod b/api/go.mod
index 6b00c5b7a..c2fbc3c61 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -8,11 +8,11 @@ require (
 	github.com/ghodss/yaml v1.0.0
 	github.com/golang/protobuf v1.4.3
 	github.com/onsi/ginkgo v1.14.2
-	github.com/onsi/gomega v1.10.3
+	github.com/onsi/gomega v1.10.4
 	github.com/pkg/errors v0.9.1
-	google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f
-	google.golang.org/grpc v1.30.0
-	google.golang.org/protobuf v1.23.0
+	google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013
+	google.golang.org/grpc v1.33.2
+	google.golang.org/protobuf v1.25.0
 // When running `make generate` in this folder, one can get into errors of missing proto dependecies
 // To solve the issue, uncomment the section below and run `go mod download`
 //github.com/cncf/udpa latest
diff --git a/api/go.sum b/api/go.sum
index e7289a1af..a01f1dd02 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -24,20 +24,22 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
 github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
 github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@@ -47,8 +49,8 @@ github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
 github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
-github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
+github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U=
+github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -68,8 +70,8 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -100,21 +102,24 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f h1:2wh8dWY8959cBGQvk1RD+/eQBgRYYDaZ+hT0/zsARoA=
-google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
 google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
diff --git a/api/mesh/v1alpha1/dataplane_helpers.go b/api/mesh/v1alpha1/dataplane_helpers.go
index 6ad399f60..6dc979567 100644
--- a/api/mesh/v1alpha1/dataplane_helpers.go
+++ b/api/mesh/v1alpha1/dataplane_helpers.go
@@ -27,8 +27,24 @@ const (
 
 	// External service tag
 	ExternalServiceTag = "kuma.io/external-service-name"
+
+	RegularDpType DpType = "regular"
+	IngressDpType DpType = "ingress"
+	GatewayDpType DpType = "gateway"
 )
 
+type DpType string
+
+func (d *Dataplane) DpType() DpType {
+	if d.IsIngress() {
+		return IngressDpType
+	}
+	if d.GetNetworking().GetGateway() != nil {
+		return GatewayDpType
+	}
+	return RegularDpType
+}
+
 type InboundInterface struct {
 	DataplaneIP   string
 	DataplanePort uint32
diff --git a/go.mod b/go.mod
index 6da3c1c89..1b555e1ae 100644
--- a/go.mod
+++ b/go.mod
@@ -30,44 +30,41 @@ require (
 	github.com/lib/pq v1.8.0
 	github.com/miekg/dns v1.1.29
 	github.com/onsi/ginkgo v1.14.2
-	github.com/onsi/gomega v1.10.3
+	github.com/onsi/gomega v1.10.4
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pkg/errors v0.9.1
-	github.com/prometheus/client_golang v1.7.1
+	github.com/prometheus/client_golang v1.9.0
 	github.com/prometheus/client_model v0.2.0
-	github.com/prometheus/common v0.10.0
+	github.com/prometheus/common v0.15.0
 	github.com/prometheus/prometheus v0.0.0-00010101000000-000000000000
 	github.com/sethvargo/go-retry v0.1.0
 	github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
 	github.com/slok/go-http-metrics v0.9.0
 	github.com/spf13/cobra v1.0.0
 	github.com/spiffe/go-spiffe v0.0.0-20190820222348-6adcf1eecbcc
-	github.com/spiffe/spire v0.10.0
+	github.com/spiffe/spire v0.12.0
+	github.com/spiffe/spire/proto/spire v0.12.0 // indirect
 	go.uber.org/multierr v1.3.0
 	go.uber.org/zap v1.13.0
 	golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
 	golang.org/x/tools v0.0.0-20201210164618-f31efc5a5c28 // indirect
 	google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3
-	google.golang.org/grpc v1.33.1
+	google.golang.org/grpc v1.33.2
 	google.golang.org/protobuf v1.25.0
-	gopkg.in/yaml.v2 v2.3.0
+	gopkg.in/yaml.v2 v2.4.0
 	helm.sh/helm/v3 v3.3.4
 	k8s.io/api v0.18.9
 	k8s.io/apimachinery v0.18.9
 	k8s.io/client-go v10.0.0+incompatible
-	// migrating to v0.6.2 fails integration tests with:
-	// failed to convert core list model of type SampleTrafficRoute into k8s counterpart
-	sigs.k8s.io/controller-runtime v0.6.1
+	sigs.k8s.io/controller-runtime v0.6.4
 	sigs.k8s.io/testing_frameworks v0.1.2
 )
 
 replace (
-	github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.3.2+incompatible
 	github.com/kumahq/kuma/api => ./api
 	github.com/kumahq/kuma/pkg/plugins/resources/k8s/native => ./pkg/plugins/resources/k8s/native
 	github.com/kumahq/kuma/pkg/transparentproxy/istio => ./pkg/transparentproxy/istio
 
 	github.com/prometheus/prometheus => ./vendored/github.com/prometheus/prometheus
-	github.com/spiffe/spire/proto/spire => github.com/spiffe/spire/proto/spire v0.10.0
 	k8s.io/client-go => k8s.io/client-go v0.18.9
 )
diff --git a/go.sum b/go.sum
index d2636bce3..8372623c2 100644
--- a/go.sum
+++ b/go.sum
@@ -40,52 +40,57 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
 cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
 cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
 contrib.go.opencensus.io/exporter/prometheus v0.2.0/go.mod h1:TYmVAyE8Tn1lyPcltF5IYYfWp2KHu7lQGIZnj8iZMys=
 contrib.go.opencensus.io/exporter/stackdriver v0.12.9/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
 contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 fortio.org/fortio v1.4.1/go.mod h1:a5CRkkB3+UTJsVV+T5N9WqV3xXMFDyW4TfJWMSFL+J8=
 github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
-github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v38.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
-github.com/Azure/go-autorest v13.3.2+incompatible h1:VxzPyuhtnlBOzc4IWCZHqpyH2d+QMLQEuy3wREyY4oc=
-github.com/Azure/go-autorest v13.3.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
-github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
+github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
+github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
 github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
-github.com/Azure/go-autorest/autorest v0.9.4 h1:1cM+NmKw91+8h5vfjgzK4ZGLuN72k87XVZBWyGwNjUM=
 github.com/Azure/go-autorest/autorest v0.9.4/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
-github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E=
+github.com/Azure/go-autorest/autorest v0.11.0 h1:tnO41Uo+/0sxTMFY/U7aKg2abek3JOnnXcuSuba74jI=
+github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
 github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
 github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
 github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
-github.com/Azure/go-autorest/autorest/adal v0.8.3 h1:O1AGG9Xig71FxdX9HO5pGNyZ7TbSyHaVg+5eJO/jSGw=
 github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
-github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM=
+github.com/Azure/go-autorest/autorest/adal v0.9.0 h1:SigMbuFNuKgc1xcGhaeapbh+8fgsu+GxgDRFyg7f5lM=
+github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
 github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
-github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U=
+github.com/Azure/go-autorest/autorest/azure/auth v0.5.0/go.mod h1:QRTvSZQpxqm8mSErhnbI+tANIBAKP7B+UIE2z4ypUO0=
 github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
+github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s=
 github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
-github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM=
 github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
+github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
+github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
 github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
 github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
-github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
 github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
+github.com/Azure/go-autorest/autorest/mocks v0.4.0 h1:z20OWOSG5aCye0HEkDp6TPmP17ZcfeMxPi6HnSALa8c=
+github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
 github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
 github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
+github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
 github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
 github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
-github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
+github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
 github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
-github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
-github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
+github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
+github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
 github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
+github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
+github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@@ -142,6 +147,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
 github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
 github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
@@ -198,7 +204,6 @@ github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
 github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
 github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
-github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
@@ -338,6 +343,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/go-control-plane v0.9.7-0.20200730005029-803dd64f0468/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
+github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
 github.com/envoyproxy/go-control-plane v0.9.8 h1:bbmjRkjmP0ZggMoahdNMmJFFnK7v5H+/j5niP5QH6bg=
 github.com/envoyproxy/go-control-plane v0.9.8/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
@@ -352,6 +358,7 @@ github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQo
 github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
 github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
+github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
 github.com/fluent/fluent-logger-golang v1.3.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU=
@@ -578,11 +585,9 @@ github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
-github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20171214222146-0e7658f8ee99/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
@@ -601,8 +606,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
 github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
 github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
 github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
-github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
-github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-hclog v0.14.0 h1:1X+ga+2ki9aUJJaliI2isvjNLI8rNCGHFkZ1FaVpvCA=
+github.com/hashicorp/go-hclog v0.14.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
 github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
 github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
@@ -611,8 +616,9 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:
 github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
 github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
 github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
-github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=
 github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
+github.com/hashicorp/go-plugin v1.3.0 h1:4d/wJojzvHV1I4i/rrjVaeuyxWrLzDE1mDCyDy8fXS8=
+github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
 github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
 github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
 github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
@@ -640,7 +646,9 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/hashicorp/serf v0.8.5/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k=
 github.com/hashicorp/vault/api v1.0.3/go.mod h1:aXl6A3Tfh50BoCNJd3oM3IK+bj2m/vVQGu8blfCvEsY=
+github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
 github.com/hashicorp/vault/sdk v0.1.12/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
+github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
@@ -688,6 +696,8 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ
 github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
+github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
 github.com/jinzhu/gorm v1.9.9/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
@@ -699,6 +709,7 @@ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhB
 github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -771,6 +782,8 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
 github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
 github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@@ -779,6 +792,7 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@@ -829,6 +843,7 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
 github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
 github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
@@ -873,8 +888,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
 github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
 github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
-github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
+github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U=
+github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
 github.com/open-policy-agent/opa v0.8.2/go.mod h1:rlfeSeHuZmMEpmrcGla42AjkOUjP4rGIpS96H12un3o=
 github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@@ -944,8 +959,9 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
 github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
 github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
 github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
-github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
+github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
 github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -962,8 +978,9 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
-github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
+github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
 github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -973,8 +990,9 @@ github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
 github.com/prometheus/procfs v0.0.6/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
+github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/prom2json v1.1.0/go.mod h1:v7OY1795b9fEUZgq4UU2+15YjRv0LfpxKejIQCy3L7o=
 github.com/prometheus/prom2json v1.2.2/go.mod h1:yIcXOj/TLPdtZ12qRyhswPnu+02sfDoqatDjj0WGSvo=
 github.com/prometheus/statsd_exporter v0.15.0/go.mod h1:Dv8HnkoLQkeEjkIE4/2ndAA7WL1zHKK7WMqFQqu72rw=
@@ -1061,13 +1079,15 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
 github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
 github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
-github.com/spiffe/go-spiffe v0.0.0-20190717182101-d8657cb50cae/go.mod h1:HyNeJnVYkDyQgB2qcSPxVYkAA2F3lQu51bDxNpFcKxY=
 github.com/spiffe/go-spiffe v0.0.0-20190820222348-6adcf1eecbcc h1:YeGvOZLHZxE8nrxPGDNH1LGv8zzkAIDfIRgy256rotk=
 github.com/spiffe/go-spiffe v0.0.0-20190820222348-6adcf1eecbcc/go.mod h1:HyNeJnVYkDyQgB2qcSPxVYkAA2F3lQu51bDxNpFcKxY=
-github.com/spiffe/spire v0.10.0 h1:UuBHgHI/4Uqcn0SpVMXWPgWtgKLJkBXOWP9Vs/82sZ4=
-github.com/spiffe/spire v0.10.0/go.mod h1:6dqxKqiDPREetq8Z62bcb+zFybVr/cj2ncTt0iLwREw=
-github.com/spiffe/spire/proto/spire v0.10.0 h1:NJ6HK9/XlnvqTox3fJUTAt6180105ZknpDS6sJC+QUM=
-github.com/spiffe/spire/proto/spire v0.10.0/go.mod h1:QmfLOnjxfc4o9KAe1f8bwYX3WcMLWSiKljTEHdGNFYU=
+github.com/spiffe/go-spiffe/v2 v2.0.0-beta.4 h1:tF4to8mhz24XGez/Vn9YPdmKrhg50M+zLGt1cbGuZbI=
+github.com/spiffe/go-spiffe/v2 v2.0.0-beta.4/go.mod h1:TEfgrEcyFhuSuvqohJt6IxENUNeHfndWCCV1EX7UaVk=
+github.com/spiffe/spire v0.12.0 h1:6NRPDVaTx5aErrrgSCQSYdG8o91M5mEshPRKW7xjG/4=
+github.com/spiffe/spire v0.12.0/go.mod h1:DRlFbPnrxPP1BO/+G6tFAiBStuArejV8sWDg5E+6nlY=
+github.com/spiffe/spire/proto/spire v0.10.1/go.mod h1:QmfLOnjxfc4o9KAe1f8bwYX3WcMLWSiKljTEHdGNFYU=
+github.com/spiffe/spire/proto/spire v0.12.0 h1:5juqJwMoKsbBbnTlSlKGAwJXZ3OhE261kwbTv28PowI=
+github.com/spiffe/spire/proto/spire v0.12.0/go.mod h1:oq/86U6YwjQMTUfRyBWc3+BBDcUusYlVXW6QAXziUME=
 github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
 github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
 github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
@@ -1139,8 +1159,8 @@ github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBU
 github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
 github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
 github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
-github.com/zeebo/errs v1.2.0 h1:Tk8UszIOLEjtx6DWnvfmMJe6N8q7vu03Bj95HMWDUkc=
-github.com/zeebo/errs v1.2.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
+github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
+github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
 github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
 github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
 gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
@@ -1183,7 +1203,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
-golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -1238,6 +1257,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1287,10 +1307,10 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d h1:dOiJ2n2cMwGLce/74I/QHMbnpk5GfY7InR8rczoMqRM=
 golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -1378,11 +1398,13 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1y1GAbb02pRlWvI54OM=
 golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
+golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1420,7 +1442,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190618163018-fdf1049a943a/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
@@ -1483,7 +1504,6 @@ gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmK
 google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
 google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
 google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
 google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -1513,6 +1533,7 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
 google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
 google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
+google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1553,10 +1574,10 @@ google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3 h1:sg8vLDNIxFPHTchfhH1E3AI32BL3f23oie38xUWnJM8=
 google.golang.org/genproto v0.0.0-20201030142918-24207fddd1c3/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1576,8 +1597,10 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
 google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1616,6 +1639,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk=
@@ -1629,8 +1653,9 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -1658,28 +1683,26 @@ istio.io/istio v0.0.0-20201207124053-74a8d16a8006 h1:wwXOcatk5k71pE5Z8v4zBKM9WcK
 istio.io/istio v0.0.0-20201207124053-74a8d16a8006/go.mod h1:RQZXDAvprt0RwlctOxWBx65sRa6jKGmJ1VOj53MunTI=
 istio.io/pkg v0.0.0-20201012181155-29f8c67d2848 h1:jlx00Y7sjbjMBPgDKDh6cYjV7H84JFYl5OtgaY8x0Ic=
 istio.io/pkg v0.0.0-20201012181155-29f8c67d2848/go.mod h1:EwvmercDF5DLCg5qUQlkM40xHwCxGoY1H/2LhI1p2YU=
-k8s.io/api v0.0.0-20190222213804-5cb15d344471/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
 k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
 k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
 k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
 k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=
-k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
+k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
 k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
 k8s.io/api v0.18.9 h1:7VDtivqwbvLOf8hmXSd/PDSSbpCBq49MELg84EYBYiQ=
 k8s.io/api v0.18.9/go.mod h1:9u/h6sUh6FxfErv7QqetX1EB3yBMIYOBXzdcf0Gf0rc=
 k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo=
 k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
 k8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE=
-k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
+k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M=
 k8s.io/apiextensions-apiserver v0.18.8 h1:pkqYPKTHa0/3lYwH7201RpF9eFm0lmZDFBNzhN+k/sA=
 k8s.io/apiextensions-apiserver v0.18.8/go.mod h1:7f4ySEkkvifIr4+BRrRWriKKIJjPyg9mb/p63dJKnlM=
-k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
 k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
 k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
 k8s.io/apimachinery v0.18.1/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
 k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
 k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
-k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
+k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
 k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
 k8s.io/apimachinery v0.18.9 h1:3ZABKQx3F3xPWlsGhCfUl8W+JXRRblV6Wo2A3zn0pvY=
 k8s.io/apimachinery v0.18.9/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
@@ -1687,7 +1710,7 @@ k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg=
 k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw=
 k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
 k8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw=
-k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
+k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg=
 k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
 k8s.io/cli-runtime v0.18.0/go.mod h1:1eXfmBsIJosjn9LjEBUd2WVPoPAY9XGTqTFcPMIBsUQ=
 k8s.io/cli-runtime v0.18.3/go.mod h1:pqbbi4nqRIQhUWAVzen8uE8DD/zcZLwf+8sQYO4lwLk=
@@ -1699,13 +1722,13 @@ k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqD
 k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
 k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
 k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
-k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
+k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
 k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
 k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
 k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c=
 k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
 k8s.io/component-base v0.18.3/go.mod h1:bp5GzGR0aGkYEfTj+eTY0AN/vXTgkJdQXjNTTVUaa3k=
-k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk=
+k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14=
 k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
 k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@@ -1754,8 +1777,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
 sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo=
-sigs.k8s.io/controller-runtime v0.6.1 h1:LcK2+nk0kmaOnKGN+vBcWHqY5WDJNJNB/c5pW+sU8fc=
-sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
+sigs.k8s.io/controller-runtime v0.6.4 h1:4013CKsBs5bEqo+LevzDett+LLxag/FjQWG94nVZ/9g=
+sigs.k8s.io/controller-runtime v0.6.4/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY=
 sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
 sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
 sigs.k8s.io/service-apis v0.0.0-20200708220836-10c7cb28ed93/go.mod h1:s/e4e7RMwEcieVQ33+YMaKbSeaQyatebjinhC/kIJ3U=
diff --git a/pkg/core/xds/metadata.go b/pkg/core/xds/metadata.go
index 7687af52d..8cd2d3941 100644
--- a/pkg/core/xds/metadata.go
+++ b/pkg/core/xds/metadata.go
@@ -3,12 +3,12 @@ package xds
 import (
 	"strconv"
 
+	_struct "github.com/golang/protobuf/ptypes/struct"
+
 	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
 	"github.com/kumahq/kuma/pkg/core/resources/model/rest"
 
 	"github.com/kumahq/kuma/pkg/core"
-
-	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
 )
 
 var metadataLog = core.Log.WithName("xds-server").WithName("metadata-tracker")
@@ -62,22 +62,22 @@ func (m *DataplaneMetadata) GetAdminPort() uint32 {
 	return m.AdminPort
 }
 
-func DataplaneMetadataFromNode(node *envoy_core.Node) *DataplaneMetadata {
+func DataplaneMetadataFromXdsMetadata(xdsMetadata *_struct.Struct) *DataplaneMetadata {
 	metadata := DataplaneMetadata{}
-	if node.Metadata == nil {
+	if xdsMetadata == nil {
 		return &metadata
 	}
-	if field := node.Metadata.Fields[fieldDataplaneTokenPath]; field != nil {
+	if field := xdsMetadata.Fields[fieldDataplaneTokenPath]; field != nil {
 		metadata.DataplaneTokenPath = field.GetStringValue()
 	}
-	if value := node.Metadata.Fields[fieldDataplaneAdminPort]; value != nil {
+	if value := xdsMetadata.Fields[fieldDataplaneAdminPort]; value != nil {
 		if port, err := strconv.Atoi(value.GetStringValue()); err == nil {
 			metadata.AdminPort = uint32(port)
 		} else {
 			metadataLog.Error(err, "invalid value in dataplane metadata", "field", fieldDataplaneAdminPort, "value", value)
 		}
 	}
-	if value := node.Metadata.Fields[fieldDataplaneDataplaneResource]; value != nil {
+	if value := xdsMetadata.Fields[fieldDataplaneDataplaneResource]; value != nil {
 		res, err := rest.UnmarshallToCore([]byte(value.GetStringValue()))
 		if err != nil {
 			metadataLog.Error(err, "invalid value in dataplane metadata", "field", fieldDataplaneDataplaneResource, "value", value)
diff --git a/pkg/core/xds/types.go b/pkg/core/xds/types.go
index b8e30adaf..7735c4185 100644
--- a/pkg/core/xds/types.go
+++ b/pkg/core/xds/types.go
@@ -91,24 +91,30 @@ type CLACache interface {
 	GetCLA(ctx context.Context, meshName, meshHash, service string) (*envoy_api_v2.ClusterLoadAssignment, error)
 }
 type Proxy struct {
-	Id                 ProxyId
-	Dataplane          *mesh_core.DataplaneResource
+	Id        ProxyId
+	Dataplane *mesh_core.DataplaneResource
+	Metadata  *DataplaneMetadata
+	Routing   Routing
+	Policies  MatchedPolicies
+}
+
+type Routing struct {
+	TrafficRoutes   RouteMap
+	OutboundTargets EndpointMap
+
+	// todo(lobkovilya): split Proxy struct into DataplaneProxy and IngressProxy
+	// TrafficRouteList is used only for generating configs for Ingress.
+	TrafficRouteList *mesh_core.TrafficRouteResourceList
+}
+
+type MatchedPolicies struct {
 	TrafficPermissions TrafficPermissionMap
 	Logs               LogMap
-	TrafficRoutes      RouteMap
-	OutboundSelectors  DestinationMap
-	OutboundTargets    EndpointMap
 	HealthChecks       HealthCheckMap
 	CircuitBreakers    CircuitBreakerMap
 	TrafficTrace       *mesh_core.TrafficTraceResource
 	TracingBackend     *mesh_proto.TracingBackend
-	Metadata           *DataplaneMetadata
 	FaultInjections    FaultInjectionMap
-	CLACache           CLACache
-
-	// todo(lobkovilya): split Proxy struct into DataplaneProxy and IngressProxy
-	// TrafficRouteList is used only for generating configs for Ingress.
-	TrafficRouteList *mesh_core.TrafficRouteResourceList
 }
 
 func (s TagSelectorSet) Add(new mesh_proto.TagSelector) TagSelectorSet {
@@ -167,6 +173,9 @@ func ParseProxyId(node *envoy_core.Node) (*ProxyId, error) {
 }
 
 func ParseProxyIdFromString(id string) (*ProxyId, error) {
+	if id == "" {
+		return nil, errors.Errorf("Envoy ID must not be nil")
+	}
 	parts := strings.SplitN(id, ".", 2)
 	mesh := parts[0]
 	if mesh == "" {
diff --git a/pkg/dp-server/components.go b/pkg/dp-server/components.go
index ce4e0faae..e646a6be8 100644
--- a/pkg/dp-server/components.go
+++ b/pkg/dp-server/components.go
@@ -4,7 +4,7 @@ import (
 	"github.com/kumahq/kuma/pkg/core/runtime"
 	sds_server "github.com/kumahq/kuma/pkg/sds/server"
 	"github.com/kumahq/kuma/pkg/xds/bootstrap"
-	xds_server "github.com/kumahq/kuma/pkg/xds/server"
+	xds_server_v2 "github.com/kumahq/kuma/pkg/xds/server/v2"
 )
 
 func SetupServer(rt runtime.Runtime) error {
@@ -12,7 +12,7 @@ func SetupServer(rt runtime.Runtime) error {
 	if err := sds_server.RegisterSDS(rt, dpServer.grpcServer); err != nil {
 		return err
 	}
-	if err := xds_server.RegisterXDS(rt, dpServer.grpcServer); err != nil {
+	if err := xds_server_v2.RegisterXDS(rt, dpServer.grpcServer); err != nil {
 		return err
 	}
 	if err := bootstrap.RegisterBootstrap(rt, dpServer.httpMux); err != nil {
diff --git a/pkg/kds/server/components.go b/pkg/kds/server/components.go
index cfd8faf45..93190d817 100644
--- a/pkg/kds/server/components.go
+++ b/pkg/kds/server/components.go
@@ -18,6 +18,7 @@ import (
 	core_metrics "github.com/kumahq/kuma/pkg/metrics"
 	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
 	util_xds "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 )
 
 func New(log logr.Logger, rt core_runtime.Runtime, providedTypes []model.ResourceType, serverID string, refresh time.Duration, filter reconcile.ResourceFilter, insight bool) (Server, error) {
@@ -33,11 +34,11 @@ func New(log logr.Logger, rt core_runtime.Runtime, providedTypes []model.Resourc
 	if err != nil {
 		return nil, err
 	}
-	callbacks := util_xds.CallbacksChain{
+	callbacks := util_xds_v2.CallbacksChain{
 		&typeAdjustCallbacks{},
-		util_xds.NewControlPlaneIdCallbacks(serverID),
-		util_xds.LoggingCallbacks{Log: log},
-		statsCallbacks,
+		util_xds_v2.NewControlPlaneIdCallbacks(serverID),
+		util_xds_v2.LoggingCallbacks{Log: log},
+		util_xds_v2.AdaptCallbacks(statsCallbacks),
 		syncTracker,
 	}
 	if insight {
@@ -75,7 +76,7 @@ func newSyncTracker(log logr.Logger, reconciler reconcile.Reconciler, refresh ti
 	if err := metrics.Register(kdsGenerationsErrors); err != nil {
 		return nil, err
 	}
-	return util_xds.NewWatchdogCallbacks(func(ctx context.Context, node *envoy_core.Node, streamID int64) (util_watchdog.Watchdog, error) {
+	return util_xds_v2.NewWatchdogCallbacks(func(ctx context.Context, node *envoy_core.Node, streamID int64) (util_watchdog.Watchdog, error) {
 		log := log.WithValues("streamID", streamID, "node", node)
 		return &util_watchdog.SimpleWatchdog{
 			NewTicker: func() *time.Ticker {
diff --git a/pkg/kds/server/status_tracker.go b/pkg/kds/server/status_tracker.go
index 6d0e5db48..a2e727d10 100644
--- a/pkg/kds/server/status_tracker.go
+++ b/pkg/kds/server/status_tracker.go
@@ -7,7 +7,7 @@ import (
 	"github.com/kumahq/kuma/pkg/core"
 	"github.com/kumahq/kuma/pkg/core/resources/model"
 	"github.com/kumahq/kuma/pkg/kds/util"
-	util_xds "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 
 	"github.com/go-logr/logr"
 
@@ -45,7 +45,7 @@ func NewStatusTracker(runtimeInfo core_runtime.RuntimeInfo,
 var _ StatusTracker = &statusTracker{}
 
 type statusTracker struct {
-	util_xds.NoopCallbacks
+	util_xds_v2.NoopCallbacks
 	runtimeInfo      core_runtime.RuntimeInfo
 	createStatusSink ZoneInsightSinkFactoryFunc
 	mu               sync.RWMutex // protects access to the fields below
diff --git a/pkg/kds/server/type_adjust_callbacks.go b/pkg/kds/server/type_adjust_callbacks.go
index a88a60055..7e371729b 100644
--- a/pkg/kds/server/type_adjust_callbacks.go
+++ b/pkg/kds/server/type_adjust_callbacks.go
@@ -4,7 +4,7 @@ import (
 	envoy_api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
 
 	"github.com/kumahq/kuma/pkg/kds"
-	util_xds "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 )
 
 // We are using go-control-plane's server and cache for KDS exchange.
@@ -16,7 +16,7 @@ import (
 // Ignores the TypeURL from marshalling operation and overrides it with TypeURL of the request.
 // If we pass wrong TypeURL in envoy_api.DiscoveryResponse#Resources we won't be able to unmarshall it, therefore we need to adjust the type.
 type typeAdjustCallbacks struct {
-	util_xds.NoopCallbacks
+	util_xds_v2.NoopCallbacks
 }
 
 func (c *typeAdjustCallbacks) OnStreamResponse(streamID int64, req *envoy_api.DiscoveryRequest, resp *envoy_api.DiscoveryResponse) {
diff --git a/pkg/mads/server/components.go b/pkg/mads/server/components.go
index c85f9eae1..1247a4536 100644
--- a/pkg/mads/server/components.go
+++ b/pkg/mads/server/components.go
@@ -12,6 +12,7 @@ import (
 	mads_reconcile "github.com/kumahq/kuma/pkg/mads/reconcile"
 	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
 	util_xds "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 
 	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
 	envoy_cache "github.com/envoyproxy/go-control-plane/pkg/cache/v2"
@@ -32,7 +33,7 @@ func NewReconciler(hasher envoy_cache.NodeHash, cache util_xds.SnapshotCache,
 }
 
 func NewSyncTracker(reconciler mads_reconcile.Reconciler, refresh time.Duration) envoy_xds.Callbacks {
-	return util_xds.NewWatchdogCallbacks(func(ctx context.Context, node *envoy_core.Node, streamID int64) (util_watchdog.Watchdog, error) {
+	return util_xds_v2.NewWatchdogCallbacks(func(ctx context.Context, node *envoy_core.Node, streamID int64) (util_watchdog.Watchdog, error) {
 		log := madsServerLog.WithValues("streamID", streamID, "node", node)
 		return &util_watchdog.SimpleWatchdog{
 			NewTicker: func() *time.Ticker {
diff --git a/pkg/mads/server/server.go b/pkg/mads/server/server.go
index d6d236ad6..62ff7e750 100644
--- a/pkg/mads/server/server.go
+++ b/pkg/mads/server/server.go
@@ -2,9 +2,9 @@ package server
 
 import (
 	"github.com/kumahq/kuma/pkg/core"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 
 	core_runtime "github.com/kumahq/kuma/pkg/core/runtime"
-	util_xds "github.com/kumahq/kuma/pkg/util/xds"
 )
 
 var (
@@ -17,8 +17,8 @@ func SetupServer(rt core_runtime.Runtime) error {
 	versioner := NewVersioner()
 	reconciler := NewReconciler(hasher, cache, generator, versioner)
 	syncTracker := NewSyncTracker(reconciler, rt.Config().MonitoringAssignmentServer.AssignmentRefreshInterval)
-	callbacks := util_xds.CallbacksChain{
-		util_xds.LoggingCallbacks{Log: madsServerLog},
+	callbacks := util_xds_v2.CallbacksChain{
+		util_xds_v2.LoggingCallbacks{Log: madsServerLog},
 		syncTracker,
 	}
 	srv := NewServer(cache, callbacks)
diff --git a/pkg/plugins/resources/k8s/native/go.mod b/pkg/plugins/resources/k8s/native/go.mod
index 273ceff49..70f65e386 100644
--- a/pkg/plugins/resources/k8s/native/go.mod
+++ b/pkg/plugins/resources/k8s/native/go.mod
@@ -7,12 +7,12 @@ require (
 	github.com/golang/protobuf v1.4.3
 	github.com/kumahq/kuma/api v0.0.0-00010101000000-000000000000
 	github.com/onsi/ginkgo v1.14.2
-	github.com/onsi/gomega v1.10.3
+	github.com/onsi/gomega v1.10.4
 	github.com/pkg/errors v0.9.1
-	golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0
+	golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb
 	k8s.io/apimachinery v0.18.9
 	k8s.io/client-go v0.18.9
-	sigs.k8s.io/controller-runtime v0.6.1
+	sigs.k8s.io/controller-runtime v0.6.4
 )
 
 replace github.com/kumahq/kuma/api => ../../../../../api
diff --git a/pkg/plugins/resources/k8s/native/go.sum b/pkg/plugins/resources/k8s/native/go.sum
index c8a907ab5..cea31d897 100644
--- a/pkg/plugins/resources/k8s/native/go.sum
+++ b/pkg/plugins/resources/k8s/native/go.sum
@@ -25,9 +25,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
 github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
-github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
-github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
@@ -147,12 +146,12 @@ github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
 github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
 github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
@@ -161,16 +160,18 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
 github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
 github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
@@ -249,8 +250,8 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
-github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
+github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U=
+github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -354,8 +355,8 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
-golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
@@ -426,23 +427,26 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f h1:2wh8dWY8959cBGQvk1RD+/eQBgRYYDaZ+hT0/zsARoA=
-google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
 google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -468,20 +472,20 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
+k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
 k8s.io/api v0.18.9 h1:7VDtivqwbvLOf8hmXSd/PDSSbpCBq49MELg84EYBYiQ=
 k8s.io/api v0.18.9/go.mod h1:9u/h6sUh6FxfErv7QqetX1EB3yBMIYOBXzdcf0Gf0rc=
-k8s.io/apiextensions-apiserver v0.18.4 h1:Y3HGERmS8t9u12YNUFoOISqefaoGRuTc43AYCLzWmWE=
-k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
-k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
+k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo=
+k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M=
+k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
 k8s.io/apimachinery v0.18.9 h1:3ZABKQx3F3xPWlsGhCfUl8W+JXRRblV6Wo2A3zn0pvY=
 k8s.io/apimachinery v0.18.9/go.mod h1:PF5taHbXgTEJLU+xMypMmYTXTWPJ5LaW8bfsisxnEXk=
-k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
-k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
+k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg=
+k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
 k8s.io/client-go v0.18.9 h1:sPHX49yOtUqv1fl49TwV3f8cC0N3etSnwgFGsIsXnZc=
 k8s.io/client-go v0.18.9/go.mod h1:UjkEetDmr40P9NX0Ok3Idt08FCf2I4mIHgjFsot77uY=
-k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
-k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk=
+k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
+k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
@@ -496,8 +500,8 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl
 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE=
 k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
-sigs.k8s.io/controller-runtime v0.6.1 h1:LcK2+nk0kmaOnKGN+vBcWHqY5WDJNJNB/c5pW+sU8fc=
-sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
+sigs.k8s.io/controller-runtime v0.6.4 h1:4013CKsBs5bEqo+LevzDett+LLxag/FjQWG94nVZ/9g=
+sigs.k8s.io/controller-runtime v0.6.4/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
diff --git a/pkg/sds/server/server.go b/pkg/sds/server/server.go
index 88b29e4ba..6036bfe81 100644
--- a/pkg/sds/server/server.go
+++ b/pkg/sds/server/server.go
@@ -19,9 +19,10 @@ import (
 	core_metrics "github.com/kumahq/kuma/pkg/metrics"
 	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
 	util_xds "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 	xds_auth "github.com/kumahq/kuma/pkg/xds/auth"
-	xds_server "github.com/kumahq/kuma/pkg/xds/server"
-	xds_sync "github.com/kumahq/kuma/pkg/xds/sync"
+	auth_components "github.com/kumahq/kuma/pkg/xds/auth/components"
+	xds_callbacks "github.com/kumahq/kuma/pkg/xds/server/callbacks"
 )
 
 var (
@@ -35,7 +36,7 @@ func RegisterSDS(rt core_runtime.Runtime, server *grpc.Server) error {
 
 	caProvider := DefaultMeshCaProvider(rt)
 	identityProvider := DefaultIdentityCertProvider(rt)
-	authenticator, err := xds_server.DefaultAuthenticator(rt)
+	authenticator, err := auth_components.DefaultAuthenticator(rt)
 	if err != nil {
 		return err
 	}
@@ -67,11 +68,11 @@ func RegisterSDS(rt core_runtime.Runtime, server *grpc.Server) error {
 	if err != nil {
 		return err
 	}
-	callbacks := util_xds.CallbacksChain{
-		statsCallbacks,
-		util_xds.LoggingCallbacks{Log: sdsServerLog},
-		authCallbacks,
-		syncTracker,
+	callbacks := util_xds_v2.CallbacksChain{
+		util_xds_v2.AdaptCallbacks(statsCallbacks),
+		util_xds_v2.LoggingCallbacks{Log: sdsServerLog},
+		util_xds_v2.AdaptCallbacks(authCallbacks),
+		util_xds_v2.AdaptCallbacks(syncTracker),
 	}
 
 	srv := envoy_server.NewServer(context.Background(), cache, callbacks)
@@ -81,7 +82,7 @@ func RegisterSDS(rt core_runtime.Runtime, server *grpc.Server) error {
 	return nil
 }
 
-func syncTracker(reconciler *DataplaneReconciler, refresh time.Duration, metrics core_metrics.Metrics) (envoy_server.Callbacks, error) {
+func syncTracker(reconciler *DataplaneReconciler, refresh time.Duration, metrics core_metrics.Metrics) (util_xds.Callbacks, error) {
 	sdsGenerations := prometheus.NewSummary(prometheus.SummaryOpts{
 		Name:       "sds_generation",
 		Help:       "Summary of SDS Snapshot generation",
@@ -97,7 +98,7 @@ func syncTracker(reconciler *DataplaneReconciler, refresh time.Duration, metrics
 	if err := metrics.Register(sdsGenerationsErrors); err != nil {
 		return nil, err
 	}
-	return xds_sync.NewDataplaneSyncTracker(func(dataplaneId core_model.ResourceKey, streamId int64) util_watchdog.Watchdog {
+	return xds_callbacks.NewDataplaneSyncTracker(func(dataplaneId core_model.ResourceKey, streamId int64) util_watchdog.Watchdog {
 		return &util_watchdog.SimpleWatchdog{
 			NewTicker: func() *time.Ticker {
 				return time.NewTicker(refresh)
diff --git a/pkg/util/xds/callbacks.go b/pkg/util/xds/callbacks.go
new file mode 100644
index 000000000..a6fe8f103
--- /dev/null
+++ b/pkg/util/xds/callbacks.go
@@ -0,0 +1,38 @@
+package xds
+
+import (
+	"context"
+
+	"github.com/golang/protobuf/proto"
+	_struct "github.com/golang/protobuf/ptypes/struct"
+)
+
+// DiscoveryRequest defines interface over real Envoy's DiscoveryRequest.
+type DiscoveryRequest interface {
+	NodeId() string
+	Metadata() *_struct.Struct
+	GetTypeUrl() string
+	GetResponseNonce() string
+	HasErrors() bool
+	Proto() proto.Message
+}
+
+// DiscoveryResponse defines interface over real Envoy's DiscoveryResponse.
+type DiscoveryResponse interface {
+	GetTypeUrl() string
+}
+
+// Callbacks defines Callbacks for XDS requests. The difference over real go-control-plane Callbacks is that it takes an DiscoveryRequest / DiscoveryResponse interface.
+// It helps us to implement Callbacks once for many different versions of Envoy API.
+type Callbacks interface {
+	// OnStreamOpen is called once an xDS stream is open with a stream ID and the type URL (or "" for ADS).
+	// Returning an error will end processing and close the stream. OnStreamClosed will still be called.
+	OnStreamOpen(context.Context, int64, string) error
+	// OnStreamClosed is called immediately prior to closing an xDS stream with a stream ID.
+	OnStreamClosed(int64)
+	// OnStreamRequest is called once a request is received on a stream.
+	// Returning an error will end processing and close the stream. OnStreamClosed will still be called.
+	OnStreamRequest(int64, DiscoveryRequest) error
+	// OnStreamResponse is called immediately prior to sending a response on a stream.
+	OnStreamResponse(int64, DiscoveryRequest, DiscoveryResponse)
+}
diff --git a/pkg/util/xds/noop_callbacks.go b/pkg/util/xds/noop_callbacks.go
index 3500ceedb..e1694952e 100644
--- a/pkg/util/xds/noop_callbacks.go
+++ b/pkg/util/xds/noop_callbacks.go
@@ -1,34 +1,22 @@
 package xds
 
-import (
-	"context"
-
-	envoy_api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
-)
+import "context"
 
 type NoopCallbacks struct {
 }
 
-func (c *NoopCallbacks) OnFetchRequest(context.Context, *envoy_api.DiscoveryRequest) error {
-	return nil
-}
-
-func (c *NoopCallbacks) OnFetchResponse(*envoy_api.DiscoveryRequest, *envoy_api.DiscoveryResponse) {
-}
-
-func (c *NoopCallbacks) OnStreamOpen(context.Context, int64, string) error {
+func (n *NoopCallbacks) OnStreamOpen(context.Context, int64, string) error {
 	return nil
 }
 
-func (c *NoopCallbacks) OnStreamClosed(int64) {
+func (n *NoopCallbacks) OnStreamClosed(int64) {
 }
 
-func (c *NoopCallbacks) OnStreamRequest(int64, *envoy_api.DiscoveryRequest) error {
+func (n *NoopCallbacks) OnStreamRequest(int64, DiscoveryRequest) error {
 	return nil
 }
 
-func (c *NoopCallbacks) OnStreamResponse(int64, *envoy_api.DiscoveryRequest, *envoy_api.DiscoveryResponse) {
+func (n *NoopCallbacks) OnStreamResponse(int64, DiscoveryRequest, DiscoveryResponse) {
 }
 
-var _ envoy_xds.Callbacks = &NoopCallbacks{}
+var _ Callbacks = &NoopCallbacks{}
diff --git a/pkg/util/xds/stats_callbacks.go b/pkg/util/xds/stats_callbacks.go
index 88627bd2d..70f566103 100644
--- a/pkg/util/xds/stats_callbacks.go
+++ b/pkg/util/xds/stats_callbacks.go
@@ -4,8 +4,6 @@ import (
 	"context"
 	"sync"
 
-	envoy_api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
 	"github.com/prometheus/client_golang/prometheus"
 )
 
@@ -17,7 +15,9 @@ type StatsCallbacks struct {
 	sync.RWMutex
 }
 
-func NewStatsCallbacks(metrics prometheus.Registerer, dsType string) (envoy_xds.Callbacks, error) {
+var _ Callbacks = &StatsCallbacks{}
+
+func NewStatsCallbacks(metrics prometheus.Registerer, dsType string) (Callbacks, error) {
 	stats := &StatsCallbacks{}
 
 	stats.ResponsesSentMetric = prometheus.NewCounterVec(prometheus.CounterOpts{
@@ -64,19 +64,17 @@ func (s *StatsCallbacks) OnStreamClosed(stream int64) {
 	s.StreamsActive--
 }
 
-func (s *StatsCallbacks) OnStreamRequest(stream int64, request *envoy_api.DiscoveryRequest) error {
-	if request.ResponseNonce != "" {
-		if request.ErrorDetail != nil {
-			s.RequestsReceivedMetric.WithLabelValues(request.TypeUrl, "NACK").Inc()
+func (s *StatsCallbacks) OnStreamRequest(stream int64, request DiscoveryRequest) error {
+	if request.GetResponseNonce() != "" {
+		if request.HasErrors() {
+			s.RequestsReceivedMetric.WithLabelValues(request.GetTypeUrl(), "NACK").Inc()
 		} else {
-			s.RequestsReceivedMetric.WithLabelValues(request.TypeUrl, "ACK").Inc()
+			s.RequestsReceivedMetric.WithLabelValues(request.GetTypeUrl(), "ACK").Inc()
 		}
 	}
 	return nil
 }
 
-func (s *StatsCallbacks) OnStreamResponse(stream int64, request *envoy_api.DiscoveryRequest, response *envoy_api.DiscoveryResponse) {
-	s.ResponsesSentMetric.WithLabelValues(response.TypeUrl).Inc()
+func (s *StatsCallbacks) OnStreamResponse(_ int64, _ DiscoveryRequest, response DiscoveryResponse) {
+	s.ResponsesSentMetric.WithLabelValues(response.GetTypeUrl()).Inc()
 }
-
-var _ envoy_xds.Callbacks = &StatsCallbacks{}
diff --git a/pkg/util/xds/v2/callbacks.go b/pkg/util/xds/v2/callbacks.go
new file mode 100644
index 000000000..81d4e970c
--- /dev/null
+++ b/pkg/util/xds/v2/callbacks.go
@@ -0,0 +1,75 @@
+package v2
+
+import (
+	"context"
+
+	envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
+	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
+	"github.com/golang/protobuf/proto"
+	_struct "github.com/golang/protobuf/ptypes/struct"
+
+	"github.com/kumahq/kuma/pkg/util/xds"
+)
+
+type adapterCallbacks struct {
+	callbacks xds.Callbacks
+}
+
+// AdaptCallbacks translate Kuma callbacks to real go-control-plane Callbacks
+func AdaptCallbacks(callbacks xds.Callbacks) envoy_xds.Callbacks {
+	return &adapterCallbacks{
+		callbacks: callbacks,
+	}
+}
+
+var _ envoy_xds.Callbacks = &adapterCallbacks{}
+
+func (a *adapterCallbacks) OnFetchRequest(ctx context.Context, request *envoy_api_v2.DiscoveryRequest) error {
+	panic("not implemented")
+}
+
+func (a *adapterCallbacks) OnFetchResponse(request *envoy_api_v2.DiscoveryRequest, response *envoy_api_v2.DiscoveryResponse) {
+	panic("not implemented")
+}
+
+func (a *adapterCallbacks) OnStreamOpen(ctx context.Context, streamID int64, typeURL string) error {
+	return a.callbacks.OnStreamOpen(ctx, streamID, typeURL)
+}
+
+func (a *adapterCallbacks) OnStreamClosed(streamID int64) {
+	a.callbacks.OnStreamClosed(streamID)
+}
+
+func (a *adapterCallbacks) OnStreamRequest(streamID int64, request *envoy_api_v2.DiscoveryRequest) error {
+	return a.callbacks.OnStreamRequest(streamID, &discoveryRequest{request})
+}
+
+func (a *adapterCallbacks) OnStreamResponse(streamID int64, request *envoy_api_v2.DiscoveryRequest, response *envoy_api_v2.DiscoveryResponse) {
+	a.callbacks.OnStreamResponse(streamID, &discoveryRequest{request}, &discoveryResponse{response})
+}
+
+type discoveryRequest struct {
+	*envoy_api_v2.DiscoveryRequest
+}
+
+func (d *discoveryRequest) Metadata() *_struct.Struct {
+	return d.GetNode().GetMetadata()
+}
+
+func (d *discoveryRequest) NodeId() string {
+	return d.GetNode().GetId()
+}
+
+func (d *discoveryRequest) HasErrors() bool {
+	return d.ErrorDetail != nil
+}
+
+func (d *discoveryRequest) Proto() proto.Message {
+	return d
+}
+
+var _ xds.DiscoveryRequest = &discoveryRequest{}
+
+type discoveryResponse struct {
+	*envoy_api_v2.DiscoveryResponse
+}
diff --git a/pkg/util/xds/callbacks_chain.go b/pkg/util/xds/v2/callbacks_chain.go
similarity index 99%
rename from pkg/util/xds/callbacks_chain.go
rename to pkg/util/xds/v2/callbacks_chain.go
index 26f73f3a4..a4d4930ec 100644
--- a/pkg/util/xds/callbacks_chain.go
+++ b/pkg/util/xds/v2/callbacks_chain.go
@@ -1,4 +1,4 @@
-package xds
+package v2
 
 import (
 	"context"
diff --git a/pkg/util/xds/control_plane_id_callbacks.go b/pkg/util/xds/v2/control_plane_id_callbacks.go
similarity index 98%
rename from pkg/util/xds/control_plane_id_callbacks.go
rename to pkg/util/xds/v2/control_plane_id_callbacks.go
index 46dcfbce2..8a0a959fe 100644
--- a/pkg/util/xds/control_plane_id_callbacks.go
+++ b/pkg/util/xds/v2/control_plane_id_callbacks.go
@@ -1,4 +1,4 @@
-package xds
+package v2
 
 import (
 	envoy_api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
diff --git a/pkg/util/xds/logging_callbacks.go b/pkg/util/xds/v2/logging_callbacks.go
similarity index 99%
rename from pkg/util/xds/logging_callbacks.go
rename to pkg/util/xds/v2/logging_callbacks.go
index 395c648a2..98e93fa4c 100644
--- a/pkg/util/xds/logging_callbacks.go
+++ b/pkg/util/xds/v2/logging_callbacks.go
@@ -1,4 +1,4 @@
-package xds
+package v2
 
 import (
 	"context"
diff --git a/pkg/util/xds/v2/noop_callbacks.go b/pkg/util/xds/v2/noop_callbacks.go
new file mode 100644
index 000000000..3870d4d52
--- /dev/null
+++ b/pkg/util/xds/v2/noop_callbacks.go
@@ -0,0 +1,34 @@
+package v2
+
+import (
+	"context"
+
+	envoy_api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
+	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
+)
+
+type NoopCallbacks struct {
+}
+
+func (c *NoopCallbacks) OnFetchRequest(context.Context, *envoy_api.DiscoveryRequest) error {
+	return nil
+}
+
+func (c *NoopCallbacks) OnFetchResponse(*envoy_api.DiscoveryRequest, *envoy_api.DiscoveryResponse) {
+}
+
+func (c *NoopCallbacks) OnStreamOpen(context.Context, int64, string) error {
+	return nil
+}
+
+func (c *NoopCallbacks) OnStreamClosed(int64) {
+}
+
+func (c *NoopCallbacks) OnStreamRequest(int64, *envoy_api.DiscoveryRequest) error {
+	return nil
+}
+
+func (c *NoopCallbacks) OnStreamResponse(int64, *envoy_api.DiscoveryRequest, *envoy_api.DiscoveryResponse) {
+}
+
+var _ envoy_xds.Callbacks = &NoopCallbacks{}
diff --git a/pkg/util/xds/watchdog_callbacks.go b/pkg/util/xds/v2/watchdog_callbacks.go
similarity index 99%
rename from pkg/util/xds/watchdog_callbacks.go
rename to pkg/util/xds/v2/watchdog_callbacks.go
index e581d48ef..68fe267c9 100644
--- a/pkg/util/xds/watchdog_callbacks.go
+++ b/pkg/util/xds/v2/watchdog_callbacks.go
@@ -1,4 +1,4 @@
-package xds
+package v2
 
 import (
 	"context"
diff --git a/pkg/xds/auth/callbacks.go b/pkg/xds/auth/callbacks.go
index d87cee3a8..bfb4f56aa 100644
--- a/pkg/xds/auth/callbacks.go
+++ b/pkg/xds/auth/callbacks.go
@@ -4,8 +4,6 @@ import (
 	"context"
 	"sync"
 
-	envoy_api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	envoy_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
 	"github.com/pkg/errors"
 	"google.golang.org/grpc/metadata"
 
@@ -13,11 +11,12 @@ import (
 	core_manager "github.com/kumahq/kuma/pkg/core/resources/manager"
 	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
 	core_xds "github.com/kumahq/kuma/pkg/core/xds"
+	util_xds "github.com/kumahq/kuma/pkg/util/xds"
 )
 
 const authorization = "authorization"
 
-func NewCallbacks(resManager core_manager.ResourceManager, authenticator Authenticator) envoy_server.Callbacks {
+func NewCallbacks(resManager core_manager.ResourceManager, authenticator Authenticator) util_xds.Callbacks {
 	return &authCallbacks{
 		resManager:    resManager,
 		authenticator: authenticator,
@@ -28,6 +27,7 @@ func NewCallbacks(resManager core_manager.ResourceManager, authenticator Authent
 
 // authCallback checks if the DiscoveryRequest is authorized, ie. if it has a valid Dataplane Token/Service Account Token.
 type authCallbacks struct {
+	util_xds.NoopCallbacks
 	resManager    core_manager.ResourceManager
 	authenticator Authenticator
 
@@ -39,7 +39,7 @@ type authCallbacks struct {
 	authenticated map[core_xds.StreamID]string
 }
 
-var _ envoy_server.Callbacks = &authCallbacks{}
+var _ util_xds.Callbacks = &authCallbacks{}
 
 func (a *authCallbacks) OnStreamOpen(ctx context.Context, streamID core_xds.StreamID, _ string) error {
 	a.Lock()
@@ -56,10 +56,10 @@ func (a *authCallbacks) OnStreamClosed(streamID core_xds.StreamID) {
 	a.Unlock()
 }
 
-func (a *authCallbacks) OnStreamRequest(streamID core_xds.StreamID, req *envoy_api.DiscoveryRequest) error {
+func (a *authCallbacks) OnStreamRequest(streamID core_xds.StreamID, req util_xds.DiscoveryRequest) error {
 	if id, alreadyAuthenticated := a.authNodeId(streamID); alreadyAuthenticated {
-		if req.Node != nil && req.Node.Id != id {
-			return errors.Errorf("stream was authenticated for ID %s. Received request is for node with ID %s. Node ID cannot be changed after stream is initialized", id, req.Node.Id)
+		if req.NodeId() != "" && req.NodeId() != id {
+			return errors.Errorf("stream was authenticated for ID %s. Received request is for node with ID %s. Node ID cannot be changed after stream is initialized", id, req.NodeId())
 		}
 		return nil
 	}
@@ -73,7 +73,7 @@ func (a *authCallbacks) OnStreamRequest(streamID core_xds.StreamID, req *envoy_a
 		return err
 	}
 	a.Lock()
-	a.authenticated[streamID] = req.Node.Id
+	a.authenticated[streamID] = req.NodeId()
 	a.Unlock()
 	return nil
 }
@@ -100,13 +100,13 @@ func (a *authCallbacks) credential(streamID core_xds.StreamID) (Credential, erro
 	return credential, err
 }
 
-func (a *authCallbacks) authenticate(credential Credential, req *envoy_api.DiscoveryRequest) error {
+func (a *authCallbacks) authenticate(credential Credential, req util_xds.DiscoveryRequest) error {
 	dataplane := core_mesh.NewDataplaneResource()
-	md := core_xds.DataplaneMetadataFromNode(req.Node)
+	md := core_xds.DataplaneMetadataFromXdsMetadata(req.Metadata())
 	if md.DataplaneResource != nil {
 		dataplane = md.DataplaneResource
 	} else {
-		proxyId, err := core_xds.ParseProxyId(req.Node)
+		proxyId, err := core_xds.ParseProxyIdFromString(req.NodeId())
 		if err != nil {
 			return errors.Wrap(err, "SDS request must have a valid Proxy Id")
 		}
@@ -125,22 +125,6 @@ func (a *authCallbacks) authenticate(credential Credential, req *envoy_api.Disco
 	return nil
 }
 
-func (a *authCallbacks) OnStreamResponse(core_xds.StreamID, *envoy_api.DiscoveryRequest, *envoy_api.DiscoveryResponse) {
-}
-
-func (a *authCallbacks) OnFetchRequest(ctx context.Context, request *envoy_api.DiscoveryRequest) error {
-	credential, err := extractCredential(ctx)
-	if err != nil {
-		return errors.Wrap(err, "could not extract credential from DiscoveryRequest")
-	}
-	return a.authenticate(credential, request)
-}
-
-func (a *authCallbacks) OnFetchResponse(*envoy_api.DiscoveryRequest, *envoy_api.DiscoveryResponse) {
-}
-
-var _ envoy_server.Callbacks = &authCallbacks{}
-
 func extractCredential(ctx context.Context) (Credential, error) {
 	metadata, ok := metadata.FromIncomingContext(ctx)
 	if !ok {
diff --git a/pkg/xds/auth/components/components.go b/pkg/xds/auth/components/components.go
new file mode 100644
index 000000000..b14d69a62
--- /dev/null
+++ b/pkg/xds/auth/components/components.go
@@ -0,0 +1,46 @@
+package components
+
+import (
+	"github.com/pkg/errors"
+	kube_auth "k8s.io/api/authentication/v1"
+
+	dp_server "github.com/kumahq/kuma/pkg/config/dp-server"
+	core_runtime "github.com/kumahq/kuma/pkg/core/runtime"
+	k8s_extensions "github.com/kumahq/kuma/pkg/plugins/extensions/k8s"
+	"github.com/kumahq/kuma/pkg/tokens/builtin"
+	"github.com/kumahq/kuma/pkg/xds/auth"
+	k8s_auth "github.com/kumahq/kuma/pkg/xds/auth/k8s"
+	universal_auth "github.com/kumahq/kuma/pkg/xds/auth/universal"
+)
+
+func NewKubeAuthenticator(rt core_runtime.Runtime) (auth.Authenticator, error) {
+	mgr, ok := k8s_extensions.FromManagerContext(rt.Extensions())
+	if !ok {
+		return nil, errors.Errorf("k8s controller runtime Manager hasn't been configured")
+	}
+	if err := kube_auth.AddToScheme(mgr.GetScheme()); err != nil {
+		return nil, errors.Wrapf(err, "could not add %q to scheme", kube_auth.SchemeGroupVersion)
+	}
+	return k8s_auth.New(mgr.GetClient()), nil
+}
+
+func NewUniversalAuthenticator(rt core_runtime.Runtime) (auth.Authenticator, error) {
+	issuer, err := builtin.NewDataplaneTokenIssuer(rt.ReadOnlyResourceManager())
+	if err != nil {
+		return nil, err
+	}
+	return universal_auth.NewAuthenticator(issuer), nil
+}
+
+func DefaultAuthenticator(rt core_runtime.Runtime) (auth.Authenticator, error) {
+	switch rt.Config().DpServer.Auth.Type {
+	case dp_server.DpServerAuthServiceAccountToken:
+		return NewKubeAuthenticator(rt)
+	case dp_server.DpServerAuthDpToken:
+		return NewUniversalAuthenticator(rt)
+	case dp_server.DpServerAuthNone:
+		return universal_auth.NewNoopAuthenticator(), nil
+	default:
+		return nil, errors.Errorf("unable to choose authenticator of %q", rt.Config().DpServer.Auth.Type)
+	}
+}
diff --git a/pkg/xds/context/context.go b/pkg/xds/context/context.go
index 5ed40a540..83f3baabd 100644
--- a/pkg/xds/context/context.go
+++ b/pkg/xds/context/context.go
@@ -5,6 +5,7 @@ import (
 
 	kuma_cp "github.com/kumahq/kuma/pkg/config/app/kuma-cp"
 	mesh_core "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
+	"github.com/kumahq/kuma/pkg/core/xds"
 )
 
 type Context struct {
@@ -20,6 +21,7 @@ type ConnectionInfo struct {
 
 type ControlPlaneContext struct {
 	SdsTlsCert []byte
+	CLACache   xds.CLACache
 }
 
 func (c Context) SDSLocation() string {
@@ -33,7 +35,7 @@ type MeshContext struct {
 	Hash       string
 }
 
-func BuildControlPlaneContext(config kuma_cp.Config) (*ControlPlaneContext, error) {
+func BuildControlPlaneContext(config kuma_cp.Config, claCache xds.CLACache) (*ControlPlaneContext, error) {
 	var cert []byte
 	if config.DpServer.TlsCertFile != "" {
 		c, err := ioutil.ReadFile(config.DpServer.TlsCertFile)
@@ -45,5 +47,6 @@ func BuildControlPlaneContext(config kuma_cp.Config) (*ControlPlaneContext, erro
 
 	return &ControlPlaneContext{
 		SdsTlsCert: cert,
+		CLACache:   claCache,
 	}, nil
 }
diff --git a/pkg/xds/generator/direct_access_proxy_generator.go b/pkg/xds/generator/direct_access_proxy_generator.go
index 209f75d10..6bc734f25 100644
--- a/pkg/xds/generator/direct_access_proxy_generator.go
+++ b/pkg/xds/generator/direct_access_proxy_generator.go
@@ -50,7 +50,7 @@ func (_ DirectAccessProxyGenerator) Generate(ctx xds_context.Context, proxy *cor
 			Configure(envoy_listeners.OutboundListener(name, endpoint.Address, endpoint.Port)).
 			Configure(envoy_listeners.FilterChain(envoy_listeners.NewFilterChainBuilder(envoy_common.APIV2).
 				Configure(envoy_listeners.TcpProxy(name, envoy_common.ClusterSubset{ClusterName: "direct_access"})).
-				Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, name, proxy.Logs[mesh_core.PassThroughService], proxy)))).
+				Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, name, proxy.Policies.Logs[mesh_core.PassThroughService], proxy)))).
 			Configure(envoy_listeners.TransparentProxying(proxy.Dataplane.Spec.Networking.GetTransparentProxying())).
 			Build()
 		if err != nil {
diff --git a/pkg/xds/generator/inbound_proxy_generator.go b/pkg/xds/generator/inbound_proxy_generator.go
index 64c7f1660..592e93eb9 100644
--- a/pkg/xds/generator/inbound_proxy_generator.go
+++ b/pkg/xds/generator/inbound_proxy_generator.go
@@ -58,15 +58,15 @@ func (g InboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.Pr
 			case mesh_core.ProtocolHTTP, mesh_core.ProtocolHTTP2:
 				filterChainBuilder.
 					Configure(envoy_listeners.HttpConnectionManager(localClusterName)).
-					Configure(envoy_listeners.FaultInjection(proxy.FaultInjections[endpoint])).
-					Configure(envoy_listeners.Tracing(proxy.TracingBackend)).
+					Configure(envoy_listeners.FaultInjection(proxy.Policies.FaultInjections[endpoint])).
+					Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
 					Configure(envoy_listeners.HttpInboundRoute(service, envoy_common.ClusterSubset{ClusterName: localClusterName}))
 			case mesh_core.ProtocolGRPC:
 				filterChainBuilder.
 					Configure(envoy_listeners.HttpConnectionManager(localClusterName)).
 					Configure(envoy_listeners.GrpcStats()).
-					Configure(envoy_listeners.FaultInjection(proxy.FaultInjections[endpoint])).
-					Configure(envoy_listeners.Tracing(proxy.TracingBackend)).
+					Configure(envoy_listeners.FaultInjection(proxy.Policies.FaultInjections[endpoint])).
+					Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
 					Configure(envoy_listeners.HttpInboundRoute(service, envoy_common.ClusterSubset{ClusterName: localClusterName}))
 			case mesh_core.ProtocolKafka:
 				filterChainBuilder.
@@ -80,7 +80,7 @@ func (g InboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.Pr
 			}
 			return filterChainBuilder.
 				Configure(envoy_listeners.ServerSideMTLS(ctx, proxy.Metadata)).
-				Configure(envoy_listeners.NetworkRBAC(inboundListenerName, ctx.Mesh.Resource.MTLSEnabled(), proxy.TrafficPermissions[endpoint]))
+				Configure(envoy_listeners.NetworkRBAC(inboundListenerName, ctx.Mesh.Resource.MTLSEnabled(), proxy.Policies.TrafficPermissions[endpoint]))
 		}()
 		inboundListener, err := envoy_listeners.NewListenerBuilder(envoy_common.APIV2).
 			Configure(envoy_listeners.InboundListener(inboundListenerName, endpoint.DataplaneIP, endpoint.DataplanePort)).
diff --git a/pkg/xds/generator/ingress_generator.go b/pkg/xds/generator/ingress_generator.go
index 2bcd05768..13ff70752 100644
--- a/pkg/xds/generator/ingress_generator.go
+++ b/pkg/xds/generator/ingress_generator.go
@@ -29,7 +29,7 @@ type IngressGenerator struct {
 func (i IngressGenerator) Generate(ctx xds_context.Context, proxy *model.Proxy) (*model.ResourceSet, error) {
 	resources := model.NewResourceSet()
 
-	destinationsPerService := i.destinations(proxy.TrafficRouteList)
+	destinationsPerService := i.destinations(proxy.Routing.TrafficRouteList)
 
 	listener, err := i.generateLDS(proxy.Dataplane, destinationsPerService)
 	if err != nil {
@@ -115,7 +115,7 @@ func (_ IngressGenerator) destinations(trs *core_mesh.TrafficRouteResourceList)
 
 func (_ IngressGenerator) services(proxy *model.Proxy) []string {
 	var services []string
-	for service := range proxy.OutboundTargets {
+	for service := range proxy.Routing.OutboundTargets {
 		services = append(services, service)
 	}
 	sort.Strings(services)
@@ -153,7 +153,7 @@ func (_ IngressGenerator) lbSubsets(service string, destinationsPerService map[s
 
 func (_ IngressGenerator) generateEDS(proxy *model.Proxy, services []string) (resources []*model.Resource) {
 	for _, service := range services {
-		endpoints := proxy.OutboundTargets[service]
+		endpoints := proxy.Routing.OutboundTargets[service]
 		resources = append(resources, &model.Resource{
 			Name:     service,
 			Origin:   OriginIngress,
diff --git a/pkg/xds/generator/outbound_proxy_generator.go b/pkg/xds/generator/outbound_proxy_generator.go
index 2fab91460..8e2324679 100644
--- a/pkg/xds/generator/outbound_proxy_generator.go
+++ b/pkg/xds/generator/outbound_proxy_generator.go
@@ -66,7 +66,7 @@ func (g OutboundProxyGenerator) Generate(ctx xds_context.Context, proxy *model.P
 	}
 	resources.AddSet(cdsResources)
 
-	edsResources, err := g.generateEDS(ctx, proxy, clusters)
+	edsResources, err := g.generateEDS(ctx, clusters)
 	if err != nil {
 		return nil, err
 	}
@@ -87,28 +87,28 @@ func (_ OutboundProxyGenerator) generateLDS(proxy *model.Proxy, subsets []envoy_
 		case mesh_core.ProtocolGRPC:
 			filterChainBuilder.
 				Configure(envoy_listeners.HttpConnectionManager(serviceName)).
-				Configure(envoy_listeners.Tracing(proxy.TracingBackend)).
-				Configure(envoy_listeners.HttpAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Logs[serviceName], proxy)).
+				Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
+				Configure(envoy_listeners.HttpAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Policies.Logs[serviceName], proxy)).
 				Configure(envoy_listeners.HttpOutboundRoute(serviceName, subsets, proxy.Dataplane.Spec.TagSet())).
 				Configure(envoy_listeners.GrpcStats())
 		case mesh_core.ProtocolHTTP, mesh_core.ProtocolHTTP2:
 			filterChainBuilder.
 				Configure(envoy_listeners.HttpConnectionManager(serviceName)).
-				Configure(envoy_listeners.Tracing(proxy.TracingBackend)).
-				Configure(envoy_listeners.HttpAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Logs[serviceName], proxy)).
+				Configure(envoy_listeners.Tracing(proxy.Policies.TracingBackend)).
+				Configure(envoy_listeners.HttpAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Policies.Logs[serviceName], proxy)).
 				Configure(envoy_listeners.HttpOutboundRoute(serviceName, subsets, proxy.Dataplane.Spec.TagSet()))
 		case mesh_core.ProtocolKafka:
 			filterChainBuilder.
 				Configure(envoy_listeners.Kafka(serviceName)).
 				Configure(envoy_listeners.TcpProxy(serviceName, subsets...)).
-				Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Logs[serviceName], proxy))
+				Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Policies.Logs[serviceName], proxy))
 		case mesh_core.ProtocolTCP:
 			fallthrough
 		default:
 			// configuration for non-HTTP cases
 			filterChainBuilder.
 				Configure(envoy_listeners.TcpProxy(serviceName, subsets...)).
-				Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Logs[serviceName], proxy))
+				Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionOutbound, sourceService, serviceName, proxy.Policies.Logs[serviceName], proxy))
 		}
 		return filterChainBuilder
 	}()
@@ -128,8 +128,8 @@ func (o OutboundProxyGenerator) generateCDS(ctx xds_context.Context, proxy *mode
 	for _, clusterName := range clusters.ClusterNames() {
 		serviceName := clusters.Tags(clusterName)[0][kuma_mesh.ServiceTag]
 		tags := clusters.Tags(clusterName)
-		healthCheck := proxy.HealthChecks[serviceName]
-		circuitBreaker := proxy.CircuitBreakers[serviceName]
+		healthCheck := proxy.Policies.HealthChecks[serviceName]
+		circuitBreaker := proxy.Policies.CircuitBreakers[serviceName]
 		edsClusterBuilder := envoy_clusters.NewClusterBuilder(envoy_common.APIV2).
 			Configure(envoy_clusters.LbSubset(o.lbSubsets(tags))).
 			Configure(envoy_clusters.OutlierDetection(circuitBreaker)).
@@ -137,8 +137,8 @@ func (o OutboundProxyGenerator) generateCDS(ctx xds_context.Context, proxy *mode
 
 		if clusters.Get(clusterName).HasExternalService() {
 			edsClusterBuilder = edsClusterBuilder.
-				Configure(envoy_clusters.StrictDNSCluster(clusterName, proxy.OutboundTargets[serviceName])).
-				Configure(envoy_clusters.ClientSideTLS(proxy.OutboundTargets[serviceName]))
+				Configure(envoy_clusters.StrictDNSCluster(clusterName, proxy.Routing.OutboundTargets[serviceName])).
+				Configure(envoy_clusters.ClientSideTLS(proxy.Routing.OutboundTargets[serviceName]))
 			protocol := o.inferProtocol(proxy, clusters.Get(clusterName).Subsets())
 			switch protocol {
 			case mesh_core.ProtocolHTTP2, mesh_core.ProtocolGRPC:
@@ -178,14 +178,14 @@ func (_ OutboundProxyGenerator) lbSubsets(tagSets []envoy_common.Tags) [][]strin
 	return result
 }
 
-func (_ OutboundProxyGenerator) generateEDS(ctx xds_context.Context, proxy *model.Proxy, clusters envoy_common.Clusters) (*model.ResourceSet, error) {
+func (_ OutboundProxyGenerator) generateEDS(ctx xds_context.Context, clusters envoy_common.Clusters) (*model.ResourceSet, error) {
 	resources := model.NewResourceSet()
 	for _, clusterName := range clusters.ClusterNames() {
 		// Endpoints for ExternalServices are specified in load assignment in DNS Cluster.
 		// We are not allowed to add endpoints with DNS names through EDS.
 		if !clusters.Get(clusterName).HasExternalService() {
 			serviceName := clusters.Tags(clusterName)[0][kuma_mesh.ServiceTag]
-			loadAssignment, err := proxy.CLACache.GetCLA(context.Background(), ctx.Mesh.Resource.Meta.GetName(), ctx.Mesh.Hash, serviceName)
+			loadAssignment, err := ctx.ControlPlane.CLACache.GetCLA(context.Background(), ctx.Mesh.Resource.Meta.GetName(), ctx.Mesh.Hash, serviceName)
 			if err != nil {
 				return nil, errors.Wrapf(err, "could not get ClusterLoadAssingment for %s", serviceName)
 			}
@@ -203,7 +203,7 @@ func (_ OutboundProxyGenerator) inferProtocol(proxy *model.Proxy, clusters []env
 	var allEndpoints []model.Endpoint
 	for _, cluster := range clusters {
 		serviceName := cluster.Tags[kuma_mesh.ServiceTag]
-		endpoints := model.EndpointList(proxy.OutboundTargets[serviceName])
+		endpoints := model.EndpointList(proxy.Routing.OutboundTargets[serviceName])
 		allEndpoints = append(allEndpoints, endpoints...)
 	}
 	return InferServiceProtocol(allEndpoints)
@@ -212,7 +212,7 @@ func (_ OutboundProxyGenerator) inferProtocol(proxy *model.Proxy, clusters []env
 func (_ OutboundProxyGenerator) determineSubsets(proxy *model.Proxy, outbound *kuma_mesh.Dataplane_Networking_Outbound) (subsets []envoy_common.ClusterSubset, err error) {
 	oface := proxy.Dataplane.Spec.Networking.ToOutboundInterface(outbound)
 
-	route := proxy.TrafficRoutes[oface]
+	route := proxy.Routing.TrafficRoutes[oface]
 	if route == nil {
 		outboundLog.Info("there is no selected TrafficRoute for the outbound interface, which means that the traffic won't be routed. Visit https://kuma.io/docs/latest/policies/traffic-route/ to check how to introduce the routing.", "dataplane", proxy.Dataplane.Meta.GetName(), "mesh", proxy.Dataplane.Meta.GetMesh(), "outbound", oface)
 		return nil, nil
@@ -236,7 +236,7 @@ func (_ OutboundProxyGenerator) determineSubsets(proxy *model.Proxy, outbound *k
 
 		// We assume that all the targets are either ExternalServices or not
 		// therefore we check only the first one
-		endpoints := proxy.OutboundTargets[service]
+		endpoints := proxy.Routing.OutboundTargets[service]
 		if len(endpoints) > 0 {
 			ep := endpoints[0]
 			if ep.IsExternalService() {
diff --git a/pkg/xds/generator/prometheus_endpoint_generator.go b/pkg/xds/generator/prometheus_endpoint_generator.go
index 600bae20d..f0e886e08 100644
--- a/pkg/xds/generator/prometheus_endpoint_generator.go
+++ b/pkg/xds/generator/prometheus_endpoint_generator.go
@@ -86,7 +86,7 @@ func (g PrometheusEndpointGenerator) Generate(ctx xds_context.Context, proxy *co
 			Configure(envoy_listeners.FilterChain(envoy_listeners.NewFilterChainBuilder(envoy.APIV2).
 				Configure(envoy_listeners.PrometheusEndpoint(prometheusListenerName, prometheusEndpoint.Path, envoyAdminClusterName)).
 				Configure(envoy_listeners.ServerSideMTLS(ctx, proxy.Metadata)).
-				Configure(envoy_listeners.NetworkRBAC(prometheusListenerName, ctx.Mesh.Resource.MTLSEnabled(), proxy.TrafficPermissions[iface])),
+				Configure(envoy_listeners.NetworkRBAC(prometheusListenerName, ctx.Mesh.Resource.MTLSEnabled(), proxy.Policies.TrafficPermissions[iface])),
 			)).
 			Build()
 	} else {
diff --git a/pkg/xds/generator/tracing_proxy_generator.go b/pkg/xds/generator/tracing_proxy_generator.go
index 87be65043..c50d6232b 100644
--- a/pkg/xds/generator/tracing_proxy_generator.go
+++ b/pkg/xds/generator/tracing_proxy_generator.go
@@ -24,13 +24,13 @@ type TracingProxyGenerator struct {
 var _ ResourceGenerator = TracingProxyGenerator{}
 
 func (t TracingProxyGenerator) Generate(_ xds_context.Context, proxy *core_xds.Proxy) (*core_xds.ResourceSet, error) {
-	if proxy.TracingBackend == nil {
+	if proxy.Policies.TracingBackend == nil {
 		return nil, nil
 	}
 	resources := core_xds.NewResourceSet()
-	switch proxy.TracingBackend.Type {
+	switch proxy.Policies.TracingBackend.Type {
 	case mesh_proto.TracingZipkinType:
-		res, err := t.zipkinCluster(proxy.TracingBackend)
+		res, err := t.zipkinCluster(proxy.Policies.TracingBackend)
 		if err != nil {
 			return nil, errors.Wrap(err, "could not generate zipkin cluster")
 		}
diff --git a/pkg/xds/generator/transparent_proxy_generator.go b/pkg/xds/generator/transparent_proxy_generator.go
index e7324e010..b728d9094 100644
--- a/pkg/xds/generator/transparent_proxy_generator.go
+++ b/pkg/xds/generator/transparent_proxy_generator.go
@@ -47,7 +47,7 @@ func (_ TransparentProxyGenerator) Generate(ctx xds_context.Context, proxy *mode
 		Configure(envoy_listeners.OutboundListener(outboundName, "0.0.0.0", redirectPortOutbound)).
 		Configure(envoy_listeners.FilterChain(envoy_listeners.NewFilterChainBuilder(envoy_common.APIV2).
 			Configure(envoy_listeners.TcpProxy(outboundName, envoy_common.ClusterSubset{ClusterName: outboundName})).
-			Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionUnspecified, sourceService, "external", proxy.Logs[mesh_core.PassThroughService], proxy)))).
+			Configure(envoy_listeners.NetworkAccessLog(meshName, envoy_common.TrafficDirectionUnspecified, sourceService, "external", proxy.Policies.Logs[mesh_core.PassThroughService], proxy)))).
 		Configure(envoy_listeners.OriginalDstForwarder()).
 		Build()
 	if err != nil {
diff --git a/pkg/xds/server/connection_info_tracker.go b/pkg/xds/server/callbacks/connection_info_tracker.go
similarity index 67%
rename from pkg/xds/server/connection_info_tracker.go
rename to pkg/xds/server/callbacks/connection_info_tracker.go
index 62b6d39cc..edacd2700 100644
--- a/pkg/xds/server/connection_info_tracker.go
+++ b/pkg/xds/server/callbacks/connection_info_tracker.go
@@ -1,15 +1,14 @@
-package server
+package callbacks
 
 import (
 	"context"
 	"sync"
 
-	envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	envoy_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
 	"github.com/pkg/errors"
 	"google.golang.org/grpc/metadata"
 
 	core_xds "github.com/kumahq/kuma/pkg/core/xds"
+	util_xds "github.com/kumahq/kuma/pkg/util/xds"
 	xds_context "github.com/kumahq/kuma/pkg/xds/context"
 )
 
@@ -17,10 +16,13 @@ const authorityHeader = ":authority"
 
 // ConnectionInfoTracker tracks the information about the connection itself from the data plane to the control plane
 type ConnectionInfoTracker struct {
+	util_xds.NoopCallbacks
 	sync.RWMutex
 	connectionInfos map[core_xds.StreamID]xds_context.ConnectionInfo
 }
 
+var _ util_xds.Callbacks = &ConnectionInfoTracker{}
+
 func NewConnectionInfoTracker() *ConnectionInfoTracker {
 	return &ConnectionInfoTracker{
 		connectionInfos: map[core_xds.StreamID]xds_context.ConnectionInfo{},
@@ -56,19 +58,3 @@ func (c *ConnectionInfoTracker) OnStreamClosed(streamID core_xds.StreamID) {
 	delete(c.connectionInfos, streamID)
 	c.Unlock()
 }
-
-func (c *ConnectionInfoTracker) OnStreamRequest(core_xds.StreamID, *envoy_api_v2.DiscoveryRequest) error {
-	return nil
-}
-
-func (c *ConnectionInfoTracker) OnStreamResponse(core_xds.StreamID, *envoy_api_v2.DiscoveryRequest, *envoy_api_v2.DiscoveryResponse) {
-}
-
-func (c *ConnectionInfoTracker) OnFetchRequest(context.Context, *envoy_api_v2.DiscoveryRequest) error {
-	return nil
-}
-
-func (c *ConnectionInfoTracker) OnFetchResponse(*envoy_api_v2.DiscoveryRequest, *envoy_api_v2.DiscoveryResponse) {
-}
-
-var _ envoy_server.Callbacks = &ConnectionInfoTracker{}
diff --git a/pkg/xds/server/dataplane_lifecycle.go b/pkg/xds/server/callbacks/dataplane_lifecycle.go
similarity index 83%
rename from pkg/xds/server/dataplane_lifecycle.go
rename to pkg/xds/server/callbacks/dataplane_lifecycle.go
index d6616fbf4..6c5979371 100644
--- a/pkg/xds/server/dataplane_lifecycle.go
+++ b/pkg/xds/server/callbacks/dataplane_lifecycle.go
@@ -1,13 +1,12 @@
-package server
+package callbacks
 
 import (
 	"context"
 	"sync"
 
-	envoy_api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	go_cp_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
 	"github.com/pkg/errors"
 
+	"github.com/kumahq/kuma/pkg/core"
 	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
 	"github.com/kumahq/kuma/pkg/core/resources/manager"
 	"github.com/kumahq/kuma/pkg/core/resources/model"
@@ -16,6 +15,8 @@ import (
 	util_xds "github.com/kumahq/kuma/pkg/util/xds"
 )
 
+var lifecycleLog = core.Log.WithName("xds").WithName("dp-lifecycle")
+
 // DataplaneLifecycle is responsible for creating a deleting dataplanes that are passed through metadata
 // There are two possible workflows
 // 1) apply Dataplane resource before kuma-dp run and run kuma-dp
@@ -34,7 +35,7 @@ type DataplaneLifecycle struct {
 	sync.RWMutex       // protects createdDpForStream
 }
 
-var _ go_cp_server.Callbacks = &DataplaneLifecycle{}
+var _ util_xds.Callbacks = &DataplaneLifecycle{}
 
 func NewDataplaneLifecycle(resManager manager.ResourceManager) *DataplaneLifecycle {
 	return &DataplaneLifecycle{
@@ -49,15 +50,15 @@ func (d *DataplaneLifecycle) OnStreamClosed(streamID int64) {
 	key := d.createdDpForStream[streamID]
 	delete(d.createdDpForStream, streamID)
 	if key != nil {
-		xdsServerLog.Info("unregistering dataplane", "dataplaneKey", key, "streamID", streamID)
+		lifecycleLog.Info("unregistering dataplane", "dataplaneKey", key, "streamID", streamID)
 		if err := d.unregisterDataplane(*key); err != nil {
-			xdsServerLog.Error(err, "could not unregister dataplane")
+			lifecycleLog.Error(err, "could not unregister dataplane")
 		}
 	}
 }
 
-func (d *DataplaneLifecycle) OnStreamRequest(streamID int64, request *envoy_api_v2.DiscoveryRequest) error {
-	if request.Node == nil { // Only the first request on a stream is guaranteed to carry the node identifier.
+func (d *DataplaneLifecycle) OnStreamRequest(streamID int64, request util_xds.DiscoveryRequest) error {
+	if request.NodeId() == "" { // Only the first request on a stream is guaranteed to carry the node identifier.
 		return nil
 	}
 
@@ -67,9 +68,9 @@ func (d *DataplaneLifecycle) OnStreamRequest(streamID int64, request *envoy_api_
 
 	d.Lock()
 	defer d.Unlock()
-	md := xds.DataplaneMetadataFromNode(request.Node)
+	md := xds.DataplaneMetadataFromXdsMetadata(request.Metadata())
 	if md.DataplaneResource != nil {
-		xdsServerLog.Info("registering dataplane", "dataplane", md.DataplaneResource, "streamID", streamID, "nodeID", request.Node.Id)
+		lifecycleLog.Info("registering dataplane", "dataplane", md.DataplaneResource, "streamID", streamID, "nodeID", request.NodeId())
 		if err := d.registerDataplane(md.DataplaneResource); err != nil {
 			return errors.Wrap(err, "could not register dataplane passed in kuma-dp run")
 		}
diff --git a/pkg/xds/server/dataplane_metadata_tracker.go b/pkg/xds/server/callbacks/dataplane_metadata_tracker.go
similarity index 82%
rename from pkg/xds/server/dataplane_metadata_tracker.go
rename to pkg/xds/server/callbacks/dataplane_metadata_tracker.go
index b98c95543..98631ed61 100644
--- a/pkg/xds/server/dataplane_metadata_tracker.go
+++ b/pkg/xds/server/callbacks/dataplane_metadata_tracker.go
@@ -1,11 +1,8 @@
-package server
+package callbacks
 
 import (
 	"sync"
 
-	envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	go_cp_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
-
 	"github.com/kumahq/kuma/pkg/core/xds"
 	util_xds "github.com/kumahq/kuma/pkg/util/xds"
 )
@@ -34,7 +31,7 @@ func (d *DataplaneMetadataTracker) Metadata(streamId int64) *xds.DataplaneMetada
 	}
 }
 
-var _ go_cp_server.Callbacks = &DataplaneMetadataTracker{}
+var _ util_xds.Callbacks = &DataplaneMetadataTracker{}
 
 func (d *DataplaneMetadataTracker) OnStreamClosed(stream int64) {
 	d.mutex.Lock()
@@ -42,8 +39,8 @@ func (d *DataplaneMetadataTracker) OnStreamClosed(stream int64) {
 	delete(d.metadataForStream, stream)
 }
 
-func (d *DataplaneMetadataTracker) OnStreamRequest(stream int64, req *envoy.DiscoveryRequest) error {
-	if req.Node == nil {
+func (d *DataplaneMetadataTracker) OnStreamRequest(stream int64, req util_xds.DiscoveryRequest) error {
+	if req.NodeId() == "" {
 		// from https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol#ack-nack-and-versioning:
 		// Only the first request on a stream is guaranteed to carry the node identifier.
 		// The subsequent discovery requests on the same stream may carry an empty node identifier.
@@ -55,6 +52,6 @@ func (d *DataplaneMetadataTracker) OnStreamRequest(stream int64, req *envoy.Disc
 
 	d.mutex.Lock()
 	defer d.mutex.Unlock()
-	d.metadataForStream[stream] = xds.DataplaneMetadataFromNode(req.Node)
+	d.metadataForStream[stream] = xds.DataplaneMetadataFromXdsMetadata(req.Metadata())
 	return nil
 }
diff --git a/pkg/xds/server/dataplane_status_sink.go b/pkg/xds/server/callbacks/dataplane_status_sink.go
similarity index 85%
rename from pkg/xds/server/dataplane_status_sink.go
rename to pkg/xds/server/callbacks/dataplane_status_sink.go
index 5959e43a7..0d43d558d 100644
--- a/pkg/xds/server/dataplane_status_sink.go
+++ b/pkg/xds/server/callbacks/dataplane_status_sink.go
@@ -1,4 +1,4 @@
-package server
+package callbacks
 
 import (
 	"time"
@@ -6,12 +6,15 @@ import (
 	"github.com/golang/protobuf/proto"
 
 	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
+	"github.com/kumahq/kuma/pkg/core"
 	mesh_core "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
 	"github.com/kumahq/kuma/pkg/core/resources/manager"
 	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
 	"github.com/kumahq/kuma/pkg/core/resources/store"
 )
 
+var sinkLog = core.Log.WithName("xds").WithName("sink")
+
 type DataplaneInsightSink interface {
 	Start(stop <-chan struct{})
 }
@@ -64,14 +67,14 @@ func (s *dataplaneInsightSink) Start(stop <-chan struct{}) {
 				// 2) upsert fail because it tries to create a new insight, but there is no Dataplane so ownership returns an error
 				// We could build a synchronous mechanism that waits for Sink to be stopped before moving on to next Callbacks, but this is potentially dangerous
 				// that we could block waiting for storage instead of executing next callbacks.
-				xdsServerLog.V(1).Info("failed to flush Dataplane status on stream close. It can happen when Dataplane is deleted at the same time", "dataplaneid", dataplaneId, "err", err)
+				sinkLog.V(1).Info("failed to flush Dataplane status on stream close. It can happen when Dataplane is deleted at the same time", "dataplaneid", dataplaneId, "err", err)
 			case store.IsResourceConflict(err):
-				xdsServerLog.V(1).Info("failed to flush DataplaneInsight because it was updated in other place. Will retry in the next tick", "dataplaneid", dataplaneId)
+				sinkLog.V(1).Info("failed to flush DataplaneInsight because it was updated in other place. Will retry in the next tick", "dataplaneid", dataplaneId)
 			default:
-				xdsServerLog.Error(err, "failed to flush DataplaneInsight", "dataplaneid", dataplaneId)
+				sinkLog.Error(err, "failed to flush DataplaneInsight", "dataplaneid", dataplaneId)
 			}
 		} else {
-			xdsServerLog.V(1).Info("DataplaneInsight saved", "dataplaneid", dataplaneId, "subscription", currentState)
+			sinkLog.V(1).Info("DataplaneInsight saved", "dataplaneid", dataplaneId, "subscription", currentState)
 			lastStoredState = currentState
 		}
 	}
diff --git a/pkg/xds/server/dataplane_status_tracker.go b/pkg/xds/server/callbacks/dataplane_status_tracker.go
similarity index 76%
rename from pkg/xds/server/dataplane_status_tracker.go
rename to pkg/xds/server/callbacks/dataplane_status_tracker.go
index 6222f67cf..eea8f9cbd 100644
--- a/pkg/xds/server/dataplane_status_tracker.go
+++ b/pkg/xds/server/callbacks/dataplane_status_tracker.go
@@ -1,14 +1,11 @@
-package server
+package callbacks
 
 import (
 	"context"
 	"sync"
-	"time"
 
 	pstruct "github.com/golang/protobuf/ptypes/struct"
 
-	envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
 	"github.com/golang/protobuf/proto"
 
 	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
@@ -20,14 +17,10 @@ import (
 	util_xds "github.com/kumahq/kuma/pkg/util/xds"
 )
 
-var (
-	// overridable by unit tests
-	now     = time.Now
-	newUUID = core.NewUUID
-)
+var statusTrackerLog = core.Log.WithName("xds").WithName("statusTracker")
 
 type DataplaneStatusTracker interface {
-	envoy_xds.Callbacks
+	util_xds.Callbacks
 	GetStatusAccessor(streamID int64) (SubscriptionStatusAccessor, bool)
 }
 
@@ -71,9 +64,9 @@ func (c *dataplaneStatusTracker) OnStreamOpen(ctx context.Context, streamID int6
 
 	// initialize subscription
 	subscription := &mesh_proto.DiscoverySubscription{
-		Id:                     newUUID(),
+		Id:                     core.NewUUID(),
 		ControlPlaneInstanceId: c.runtimeInfo.GetInstanceId(),
-		ConnectTime:            util_proto.MustTimestampProto(now()),
+		ConnectTime:            util_proto.MustTimestampProto(core.Now()),
 		Status:                 mesh_proto.NewSubscriptionStatus(),
 		Version:                mesh_proto.NewVersion(),
 	}
@@ -85,7 +78,7 @@ func (c *dataplaneStatusTracker) OnStreamOpen(ctx context.Context, streamID int6
 	// save
 	c.streams[streamID] = state
 
-	xdsServerLog.V(1).Info("OnStreamOpen", "context", ctx, "streamid", streamID, "type", typ, "subscription", subscription)
+	statusTrackerLog.V(1).Info("OnStreamOpen", "context", ctx, "streamid", streamID, "type", typ, "subscription", subscription)
 	return nil
 }
 
@@ -101,18 +94,18 @@ func (c *dataplaneStatusTracker) OnStreamClosed(streamID int64) {
 	// finilize subscription
 	state.mu.Lock() // write access to the per Dataplane info
 	subscription := state.subscription
-	subscription.DisconnectTime = util_proto.MustTimestampProto(now())
+	subscription.DisconnectTime = util_proto.MustTimestampProto(core.Now())
 	state.mu.Unlock()
 
 	// trigger final flush
 	state.Close()
 
-	xdsServerLog.V(1).Info("OnStreamClosed", "streamid", streamID, "subscription", subscription)
+	statusTrackerLog.V(1).Info("OnStreamClosed", "streamid", streamID, "subscription", subscription)
 }
 
 // OnStreamRequest is called once a request is received on a stream.
 // Returning an error will end processing and close the stream. OnStreamClosed will still be called.
-func (c *dataplaneStatusTracker) OnStreamRequest(streamID int64, req *envoy.DiscoveryRequest) error {
+func (c *dataplaneStatusTracker) OnStreamRequest(streamID int64, req util_xds.DiscoveryRequest) error {
 	c.mu.RLock() // read access to the map of all ADS streams
 	defer c.mu.RUnlock()
 
@@ -123,37 +116,37 @@ func (c *dataplaneStatusTracker) OnStreamRequest(streamID int64, req *envoy.Disc
 
 	// infer Dataplane id
 	if state.dataplaneId == (core_model.ResourceKey{}) {
-		if id, err := core_xds.ParseProxyId(req.Node); err == nil {
+		if id, err := core_xds.ParseProxyIdFromString(req.NodeId()); err == nil {
 			state.dataplaneId = core_model.ResourceKey{Mesh: id.Mesh, Name: id.Name}
-			if err := readVersion(req.Node.Metadata, state.subscription.Version); err != nil {
-				xdsServerLog.Error(err, "failed to extract version out of the Envoy metadata", "streamid", streamID, "metadata", req.Node.Metadata)
+			if err := readVersion(req.Metadata(), state.subscription.Version); err != nil {
+				statusTrackerLog.Error(err, "failed to extract version out of the Envoy metadata", "streamid", streamID, "metadata", req.Metadata())
 			}
 			// kick off async Dataplane status flusher
 			go c.createStatusSink(state).Start(state.stop)
 		} else {
-			xdsServerLog.Error(err, "failed to parse Dataplane Id out of DiscoveryRequest", "streamid", streamID, "req", req)
+			statusTrackerLog.Error(err, "failed to parse Dataplane Id out of DiscoveryRequest", "streamid", streamID, "req", req)
 		}
 	}
 
 	// update Dataplane status
 	subscription := state.subscription
-	if req.ResponseNonce != "" {
-		subscription.Status.LastUpdateTime = util_proto.MustTimestampProto(now())
-		if req.ErrorDetail != nil {
+	if req.GetResponseNonce() != "" {
+		subscription.Status.LastUpdateTime = util_proto.MustTimestampProto(core.Now())
+		if req.HasErrors() {
 			subscription.Status.Total.ResponsesRejected++
-			subscription.Status.StatsOf(req.TypeUrl).ResponsesRejected++
+			subscription.Status.StatsOf(req.GetTypeUrl()).ResponsesRejected++
 		} else {
 			subscription.Status.Total.ResponsesAcknowledged++
-			subscription.Status.StatsOf(req.TypeUrl).ResponsesAcknowledged++
+			subscription.Status.StatsOf(req.GetTypeUrl()).ResponsesAcknowledged++
 		}
 	}
 
-	xdsServerLog.V(1).Info("OnStreamRequest", "streamid", streamID, "request", req, "subscription", subscription)
+	statusTrackerLog.V(1).Info("OnStreamRequest", "streamid", streamID, "request", req, "subscription", subscription)
 	return nil
 }
 
 // OnStreamResponse is called immediately prior to sending a response on a stream.
-func (c *dataplaneStatusTracker) OnStreamResponse(streamID int64, req *envoy.DiscoveryRequest, resp *envoy.DiscoveryResponse) {
+func (c *dataplaneStatusTracker) OnStreamResponse(streamID int64, req util_xds.DiscoveryRequest, resp util_xds.DiscoveryResponse) {
 	c.mu.RLock() // read access to the map of all ADS streams
 	defer c.mu.RUnlock()
 
@@ -164,11 +157,11 @@ func (c *dataplaneStatusTracker) OnStreamResponse(streamID int64, req *envoy.Dis
 
 	// update Dataplane status
 	subscription := state.subscription
-	subscription.Status.LastUpdateTime = util_proto.MustTimestampProto(now())
+	subscription.Status.LastUpdateTime = util_proto.MustTimestampProto(core.Now())
 	subscription.Status.Total.ResponsesSent++
-	subscription.Status.StatsOf(resp.TypeUrl).ResponsesSent++
+	subscription.Status.StatsOf(resp.GetTypeUrl()).ResponsesSent++
 
-	xdsServerLog.V(1).Info("OnStreamResponse", "streamid", streamID, "request", req, "response", resp, "subscription", subscription)
+	statusTrackerLog.V(1).Info("OnStreamResponse", "streamid", streamID, "request", req, "response", resp, "subscription", subscription)
 }
 
 func (c *dataplaneStatusTracker) GetStatusAccessor(streamID int64) (SubscriptionStatusAccessor, bool) {
diff --git a/pkg/xds/sync/dataplane_sync_tracker.go b/pkg/xds/server/callbacks/dataplane_sync_tracker.go
similarity index 82%
rename from pkg/xds/sync/dataplane_sync_tracker.go
rename to pkg/xds/server/callbacks/dataplane_sync_tracker.go
index dc386a654..1fd65cdbb 100644
--- a/pkg/xds/sync/dataplane_sync_tracker.go
+++ b/pkg/xds/server/callbacks/dataplane_sync_tracker.go
@@ -1,4 +1,4 @@
-package sync
+package callbacks
 
 import (
 	"context"
@@ -8,9 +8,7 @@ import (
 	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
 	core_xds "github.com/kumahq/kuma/pkg/core/xds"
 	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
-
-	envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
+	util_xds "github.com/kumahq/kuma/pkg/util/xds"
 )
 
 var (
@@ -19,7 +17,7 @@ var (
 
 type NewDataplaneWatchdogFunc func(dataplaneId core_model.ResourceKey, streamId core_xds.StreamID) util_watchdog.Watchdog
 
-func NewDataplaneSyncTracker(factoryFunc NewDataplaneWatchdogFunc) envoy_xds.Callbacks {
+func NewDataplaneSyncTracker(factoryFunc NewDataplaneWatchdogFunc) util_xds.Callbacks {
 	return &dataplaneSyncTracker{
 		newDataplaneWatchdog: factoryFunc,
 		streamsAssociation:   make(map[core_xds.StreamID]core_model.ResourceKey),
@@ -27,7 +25,7 @@ func NewDataplaneSyncTracker(factoryFunc NewDataplaneWatchdogFunc) envoy_xds.Cal
 	}
 }
 
-var _ envoy_xds.Callbacks = &dataplaneSyncTracker{}
+var _ util_xds.Callbacks = &dataplaneSyncTracker{}
 
 type streams struct {
 	watchdogCancel context.CancelFunc
@@ -76,7 +74,7 @@ func (t *dataplaneSyncTracker) OnStreamClosed(streamID core_xds.StreamID) {
 
 // OnStreamRequest is called once a request is received on a stream.
 // Returning an error will end processing and close the stream. OnStreamClosed will still be called.
-func (t *dataplaneSyncTracker) OnStreamRequest(streamID core_xds.StreamID, req *envoy.DiscoveryRequest) error {
+func (t *dataplaneSyncTracker) OnStreamRequest(streamID core_xds.StreamID, req util_xds.DiscoveryRequest) error {
 	t.RLock()
 	_, alreadyAssociated := t.streamsAssociation[streamID]
 	t.RUnlock()
@@ -85,7 +83,7 @@ func (t *dataplaneSyncTracker) OnStreamRequest(streamID core_xds.StreamID, req *
 		return nil
 	}
 
-	if id, err := core_xds.ParseProxyId(req.Node); err == nil {
+	if id, err := core_xds.ParseProxyIdFromString(req.NodeId()); err == nil {
 		dataplaneKey := core_model.ResourceKey{Mesh: id.Mesh, Name: id.Name}
 		t.Lock()
 		defer t.Unlock()
@@ -113,15 +111,5 @@ func (t *dataplaneSyncTracker) OnStreamRequest(streamID core_xds.StreamID, req *
 }
 
 // OnStreamResponse is called immediately prior to sending a response on a stream.
-func (t *dataplaneSyncTracker) OnStreamResponse(streamID core_xds.StreamID, req *envoy.DiscoveryRequest, resp *envoy.DiscoveryResponse) {
-}
-
-// OnFetchRequest is called for each Fetch request. Returning an error will end processing of the
-// request and respond with an error.
-func (t *dataplaneSyncTracker) OnFetchRequest(context.Context, *envoy.DiscoveryRequest) error {
-	return nil
-}
-
-// OnFetchResponse is called immediately prior to sending a response.
-func (t *dataplaneSyncTracker) OnFetchResponse(*envoy.DiscoveryRequest, *envoy.DiscoveryResponse) {
+func (t *dataplaneSyncTracker) OnStreamResponse(streamID core_xds.StreamID, req util_xds.DiscoveryRequest, resp util_xds.DiscoveryResponse) {
 }
diff --git a/pkg/xds/server/components.go b/pkg/xds/server/components.go
index 467049675..6daaf5ccf 100644
--- a/pkg/xds/server/components.go
+++ b/pkg/xds/server/components.go
@@ -1,406 +1,22 @@
 package server
 
 import (
-	"context"
 	"time"
 
-	envoy_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
-	"google.golang.org/grpc"
+	xds_callbacks "github.com/kumahq/kuma/pkg/xds/server/callbacks"
 
-	"github.com/kumahq/kuma/pkg/xds/ingress"
-
-	dp_server "github.com/kumahq/kuma/pkg/config/dp-server"
-	core_system "github.com/kumahq/kuma/pkg/core/resources/apis/system"
-	"github.com/kumahq/kuma/pkg/core/resources/registry"
-	"github.com/kumahq/kuma/pkg/xds/cache/cla"
-	"github.com/kumahq/kuma/pkg/xds/cache/mesh"
-
-	envoy_service_discovery_v2 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2"
-	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
-	"github.com/pkg/errors"
-	"github.com/prometheus/client_golang/prometheus"
-	kube_auth "k8s.io/api/authentication/v1"
-
-	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
-	"github.com/kumahq/kuma/pkg/core"
-	"github.com/kumahq/kuma/pkg/core/faultinjections"
-	"github.com/kumahq/kuma/pkg/core/logs"
-	"github.com/kumahq/kuma/pkg/core/permissions"
-	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
-	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
-	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
 	core_runtime "github.com/kumahq/kuma/pkg/core/runtime"
-	"github.com/kumahq/kuma/pkg/core/xds"
-	"github.com/kumahq/kuma/pkg/metrics"
-	k8s_extensions "github.com/kumahq/kuma/pkg/plugins/extensions/k8s"
-	"github.com/kumahq/kuma/pkg/tokens/builtin"
-	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
-	util_xds "github.com/kumahq/kuma/pkg/util/xds"
-	"github.com/kumahq/kuma/pkg/xds/auth"
-	k8s_auth "github.com/kumahq/kuma/pkg/xds/auth/k8s"
-	universal_auth "github.com/kumahq/kuma/pkg/xds/auth/universal"
-	xds_context "github.com/kumahq/kuma/pkg/xds/context"
-	xds_sync "github.com/kumahq/kuma/pkg/xds/sync"
-	xds_template "github.com/kumahq/kuma/pkg/xds/template"
-	xds_topology "github.com/kumahq/kuma/pkg/xds/topology"
-)
-
-var (
-	xdsServerLog  = core.Log.WithName("xds-server")
-	meshResources = meshResourceTypes(map[core_model.ResourceType]bool{
-		core_mesh.DataplaneInsightType:  true,
-		core_mesh.DataplaneOverviewType: true,
-		core_mesh.ServiceInsightType:    true,
-		core_system.ConfigType:          true,
-	})
 )
 
-func meshResourceTypes(exclude map[core_model.ResourceType]bool) []core_model.ResourceType {
-	types := []core_model.ResourceType{}
-	for _, typ := range registry.Global().ListTypes() {
-		r, err := registry.Global().NewObject(typ)
-		if err != nil {
-			panic(err)
-		}
-		if r.Scope() == core_model.ScopeMesh && !exclude[typ] {
-			types = append(types, typ)
-		}
-	}
-	return types
-}
-
-func RegisterXDS(rt core_runtime.Runtime, server *grpc.Server) error {
-	reconciler := DefaultReconciler(rt)
-
-	authenticator, err := DefaultAuthenticator(rt)
-	if err != nil {
-		return err
-	}
-	authCallbacks := auth.NewCallbacks(rt.ResourceManager(), authenticator)
-
-	metadataTracker := NewDataplaneMetadataTracker()
-	lifecycle := NewDataplaneLifecycle(rt.ResourceManager())
-
-	ingressReconciler := DefaultIngressReconciler(rt)
-
-	connectionInfoTracker := NewConnectionInfoTracker()
-
-	syncTracker, err := DefaultDataplaneSyncTracker(rt, reconciler, ingressReconciler, metadataTracker, connectionInfoTracker)
-	if err != nil {
-		return err
-	}
-	statusTracker, err := DefaultDataplaneStatusTracker(rt)
-	if err != nil {
-		return err
-	}
-
-	forcer := newResourceWarmingForcer(rt.XDS().Cache(), rt.XDS().Hasher())
-
-	statsCallbacks, err := util_xds.NewStatsCallbacks(rt.Metrics(), "xds")
-	if err != nil {
-		return err
-	}
-	callbacks := util_xds.CallbacksChain{
-		statsCallbacks,
-		connectionInfoTracker,
-		authCallbacks,
-		syncTracker,
-		metadataTracker,
-		lifecycle,
-		statusTracker,
-		forcer,
-	}
-
-	srv := envoy_server.NewServer(context.Background(), rt.XDS().Cache(), callbacks)
-
-	xdsServerLog.Info("registering Aggregated Discovery Service in Dataplane Server")
-	envoy_service_discovery_v2.RegisterAggregatedDiscoveryServiceServer(server, srv)
-	return nil
-}
-
-func NewKubeAuthenticator(rt core_runtime.Runtime) (auth.Authenticator, error) {
-	mgr, ok := k8s_extensions.FromManagerContext(rt.Extensions())
-	if !ok {
-		return nil, errors.Errorf("k8s controller runtime Manager hasn't been configured")
-	}
-	if err := kube_auth.AddToScheme(mgr.GetScheme()); err != nil {
-		return nil, errors.Wrapf(err, "could not add %q to scheme", kube_auth.SchemeGroupVersion)
-	}
-	return k8s_auth.New(mgr.GetClient()), nil
-}
-
-func NewUniversalAuthenticator(rt core_runtime.Runtime) (auth.Authenticator, error) {
-	issuer, err := builtin.NewDataplaneTokenIssuer(rt.ReadOnlyResourceManager())
-	if err != nil {
-		return nil, err
-	}
-	return universal_auth.NewAuthenticator(issuer), nil
-}
-
-func DefaultAuthenticator(rt core_runtime.Runtime) (auth.Authenticator, error) {
-	switch rt.Config().DpServer.Auth.Type {
-	case dp_server.DpServerAuthServiceAccountToken:
-		return NewKubeAuthenticator(rt)
-	case dp_server.DpServerAuthDpToken:
-		return NewUniversalAuthenticator(rt)
-	case dp_server.DpServerAuthNone:
-		return universal_auth.NewNoopAuthenticator(), nil
-	default:
-		return nil, errors.Errorf("unable to choose authenticator of %q", rt.Config().DpServer.Auth.Type)
-	}
-}
-
-func DefaultReconciler(rt core_runtime.Runtime) SnapshotReconciler {
-	return &reconciler{
-		&templateSnapshotGenerator{
-			ProxyTemplateResolver: &simpleProxyTemplateResolver{
-				ReadOnlyResourceManager: rt.ReadOnlyResourceManager(),
-				DefaultProxyTemplate:    xds_template.DefaultProxyTemplate,
-			},
-		},
-		&simpleSnapshotCacher{rt.XDS().Hasher(), rt.XDS().Cache()},
-	}
-}
-
-func DefaultIngressReconciler(rt core_runtime.Runtime) SnapshotReconciler {
-	return &reconciler{
-		generator: &templateSnapshotGenerator{
-			ProxyTemplateResolver: &staticProxyTemplateResolver{
-				template: xds_template.IngressProxyTemplate,
-			},
-		},
-		cacher: &simpleSnapshotCacher{rt.XDS().Hasher(), rt.XDS().Cache()},
-	}
-}
-
-func DefaultDataplaneSyncTracker(rt core_runtime.Runtime, reconciler, ingressReconciler SnapshotReconciler, metadataTracker *DataplaneMetadataTracker, connectionInfoTracker *ConnectionInfoTracker) (envoy_xds.Callbacks, error) {
-	permissionsMatcher := permissions.TrafficPermissionsMatcher{ResourceManager: rt.ReadOnlyResourceManager()}
-	logsMatcher := logs.TrafficLogsMatcher{ResourceManager: rt.ReadOnlyResourceManager()}
-	faultInjectionMatcher := faultinjections.FaultInjectionMatcher{ResourceManager: rt.ReadOnlyResourceManager()}
-	envoyCpCtx, err := xds_context.BuildControlPlaneContext(rt.Config())
-	if err != nil {
-		return nil, err
-	}
-	xdsGenerations := prometheus.NewSummary(prometheus.SummaryOpts{
-		Name:       "xds_generation",
-		Help:       "Summary of XDS Snapshot generation",
-		Objectives: metrics.DefaultObjectives,
-	})
-	if err := rt.Metrics().Register(xdsGenerations); err != nil {
-		return nil, err
-	}
-	xdsGenerationsErrors := prometheus.NewCounter(prometheus.CounterOpts{
-		Name: "xds_generation_errors",
-		Help: "Counter of errors during XDS generation",
-	})
-	if err := rt.Metrics().Register(xdsGenerationsErrors); err != nil {
-		return nil, err
-	}
-	meshSnapshotCache, err := mesh.NewCache(rt.ReadOnlyResourceManager(),
-		rt.Config().Store.Cache.ExpirationTime, meshResources, rt.LookupIP(), rt.Metrics())
-	if err != nil {
-		return nil, err
-	}
-	claCache, err := cla.NewCache(
-		rt.ReadOnlyResourceManager(), rt.DataSourceLoader(), rt.Config().Multizone.Remote.Zone,
-		rt.Config().Store.Cache.ExpirationTime, rt.LookupIP(), rt.Metrics())
-	if err != nil {
-		return nil, err
-	}
-	return xds_sync.NewDataplaneSyncTracker(func(key core_model.ResourceKey, streamId int64) util_watchdog.Watchdog {
-		log := xdsServerLog.WithName("dataplane-sync-watchdog").WithValues("dataplaneKey", key)
-		prevHash := ""
-		return &util_watchdog.SimpleWatchdog{
-			NewTicker: func() *time.Ticker {
-				return time.NewTicker(rt.Config().XdsServer.DataplaneConfigurationRefreshInterval)
-			},
-			OnTick: func() error {
-				start := core.Now()
-				defer func() {
-					xdsGenerations.Observe(float64(core.Now().Sub(start).Milliseconds()))
-				}()
-
-				ctx := context.Background()
-				proxyID := xds.FromResourceKey(key)
-
-				// first of all calculate Hash before fetching any resources,
-				// otherwise we can have lost updates
-				snapshotHash, err := meshSnapshotCache.GetHash(ctx, proxyID.Mesh)
-				if err != nil {
-					return err
-				}
-
-				dataplane := core_mesh.NewDataplaneResource()
-				if err := rt.ResourceManager().Get(ctx, dataplane, core_store.GetBy(key)); err != nil {
-					if core_store.IsResourceNotFound(err) {
-						return reconciler.Clear(&proxyID)
-					}
-					return err
-				}
-				resolvedDp, err := xds_topology.ResolveAddress(rt.LookupIP(), dataplane)
-				if err != nil {
-					return err
-				}
-				dataplane = resolvedDp
-
-				// hash for Ingress should be calculated based on all dataplanes in all meshes,
-				// we don't do that now, so just ignore existing `snapshotHash` and always reconcile Ingress
-				if dataplane.Spec.IsIngress() {
-					// update Ingress
-					allMeshDataplanes := &core_mesh.DataplaneResourceList{}
-					if err := rt.ReadOnlyResourceManager().List(ctx, allMeshDataplanes); err != nil {
-						return err
-					}
-					allMeshDataplanes.Items = xds_topology.ResolveAddresses(log, rt.LookupIP(), allMeshDataplanes.Items)
-					if err := ingress.UpdateAvailableServices(ctx, rt.ResourceManager(), dataplane, allMeshDataplanes.Items); err != nil {
-						return err
-					}
-					destinations := ingress.BuildDestinationMap(dataplane)
-					endpoints := ingress.BuildEndpointMap(destinations, allMeshDataplanes.Items)
-
-					routes := &core_mesh.TrafficRouteResourceList{}
-					if err := rt.ReadOnlyResourceManager().List(ctx, routes); err != nil {
-						return err
-					}
-
-					proxy := xds.Proxy{
-						Id:               proxyID,
-						Dataplane:        dataplane,
-						OutboundTargets:  endpoints,
-						Metadata:         metadataTracker.Metadata(streamId),
-						TrafficRouteList: routes,
-					}
-					envoyCtx := xds_context.Context{
-						ControlPlane: envoyCpCtx,
-					}
-					return ingressReconciler.Reconcile(envoyCtx, &proxy)
-				}
-
-				// if previous reconciliation was without an error AND current hash is equal to previous hash
-				// then we don't reconcile
-				if prevHash != "" && snapshotHash == prevHash {
-					return nil
-				}
-				log.V(1).Info("snapshot hash updated, reconcile", "prev", prevHash, "current", snapshotHash)
-
-				meshRes := core_mesh.NewMeshResource()
-				if err := rt.ReadOnlyResourceManager().Get(ctx, meshRes, core_store.GetByKey(proxyID.Mesh, core_model.NoMesh)); err != nil {
-					return err
-				}
-
-				dataplanes, err := xds_topology.GetDataplanes(log, ctx, rt.ReadOnlyResourceManager(), rt.LookupIP(), dataplane.Meta.GetMesh())
-				if err != nil {
-					return err
-				}
-				externalServices := &core_mesh.ExternalServiceResourceList{}
-				if err := rt.ReadOnlyResourceManager().List(ctx, externalServices, core_store.ListByMesh(dataplane.Meta.GetMesh())); err != nil {
-					return err
-				}
-				envoyCtx := xds_context.Context{
-					ControlPlane: envoyCpCtx,
-					Mesh: xds_context.MeshContext{
-						Resource:   meshRes,
-						Dataplanes: dataplanes,
-						Hash:       snapshotHash,
-					},
-					ConnectionInfo: connectionInfoTracker.ConnectionInfo(streamId),
-				}
-
-				// pick a single the most specific route for each outbound interface
-				routes, err := xds_topology.GetRoutes(ctx, dataplane, rt.ReadOnlyResourceManager())
-				if err != nil {
-					return err
-				}
-
-				// create creates a map of selectors to match other dataplanes reachable via given routes
-				destinations := xds_topology.BuildDestinationMap(dataplane, routes)
-
-				// resolve all endpoints that match given selectors
-				outbound := xds_topology.BuildEndpointMap(
-					meshRes, rt.Config().Multizone.Remote.Zone,
-					dataplanes.Items, externalServices.Items, rt.DataSourceLoader())
-
-				healthChecks, err := xds_topology.GetHealthChecks(ctx, dataplane, destinations, rt.ReadOnlyResourceManager())
-				if err != nil {
-					return err
-				}
-
-				circuitBreakers, err := xds_topology.GetCircuitBreakers(ctx, dataplane, destinations, rt.ReadOnlyResourceManager())
-				if err != nil {
-					return err
-				}
-
-				trafficTrace, err := xds_topology.GetTrafficTrace(ctx, dataplane, rt.ReadOnlyResourceManager())
-				if err != nil {
-					return err
-				}
-				var tracingBackend *mesh_proto.TracingBackend
-				if trafficTrace != nil {
-					tracingBackend = meshRes.GetTracingBackend(trafficTrace.Spec.GetConf().GetBackend())
-				}
-
-				matchedPermissions, err := permissionsMatcher.Match(ctx, dataplane, meshRes)
-				if err != nil {
-					return err
-				}
-
-				matchedLogs, err := logsMatcher.Match(ctx, dataplane)
-				if err != nil {
-					return err
-				}
-
-				faultInjection, err := faultInjectionMatcher.Match(ctx, dataplane, meshRes)
-				if err != nil {
-					return err
-				}
-
-				proxy := xds.Proxy{
-					Id:                 proxyID,
-					Dataplane:          dataplane,
-					TrafficPermissions: matchedPermissions,
-					TrafficRoutes:      routes,
-					OutboundSelectors:  destinations,
-					OutboundTargets:    outbound,
-					HealthChecks:       healthChecks,
-					CircuitBreakers:    circuitBreakers,
-					Logs:               matchedLogs,
-					TrafficTrace:       trafficTrace,
-					TracingBackend:     tracingBackend,
-					Metadata:           metadataTracker.Metadata(streamId),
-					FaultInjections:    faultInjection,
-					CLACache:           claCache,
-				}
-				err = reconciler.Reconcile(envoyCtx, &proxy)
-				if err != nil {
-					return err
-				}
-				prevHash = snapshotHash
-				return nil
-			},
-			OnError: func(err error) {
-				xdsGenerationsErrors.Inc()
-				log.Error(err, "OnTick() failed")
-			},
-			OnStop: func() {
-				proxyID := xds.FromResourceKey(key)
-				if err := reconciler.Clear(&proxyID); err != nil {
-					log.Error(err, "OnStop() failed")
-				}
-			},
-		}
-	}), nil
-}
-
-func DefaultDataplaneStatusTracker(rt core_runtime.Runtime) (DataplaneStatusTracker, error) {
-	tracker := NewDataplaneStatusTracker(rt, func(accessor SubscriptionStatusAccessor) DataplaneInsightSink {
-		return NewDataplaneInsightSink(
+func DefaultDataplaneStatusTracker(rt core_runtime.Runtime) xds_callbacks.DataplaneStatusTracker {
+	return xds_callbacks.NewDataplaneStatusTracker(rt, func(accessor xds_callbacks.SubscriptionStatusAccessor) xds_callbacks.DataplaneInsightSink {
+		return xds_callbacks.NewDataplaneInsightSink(
 			accessor,
 			func() *time.Ticker {
 				return time.NewTicker(rt.Config().XdsServer.DataplaneStatusFlushInterval)
 			},
 			rt.Config().XdsServer.DataplaneStatusFlushInterval/10,
-			NewDataplaneInsightStore(rt.ResourceManager()),
+			xds_callbacks.NewDataplaneInsightStore(rt.ResourceManager()),
 		)
 	})
-	return tracker, nil
 }
diff --git a/pkg/xds/server/grpc.go b/pkg/xds/server/grpc.go
deleted file mode 100644
index 89f0ec229..000000000
--- a/pkg/xds/server/grpc.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package server
-
-import (
-	"fmt"
-	"net"
-
-	envoy_discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2"
-	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
-	"github.com/pkg/errors"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/credentials"
-
-	"github.com/kumahq/kuma/pkg/core"
-	"github.com/kumahq/kuma/pkg/core/runtime/component"
-	"github.com/kumahq/kuma/pkg/metrics"
-)
-
-const grpcMaxConcurrentStreams = 1000000
-
-var (
-	grpcServerLog = core.Log.WithName("xds-server").WithName("grpc")
-)
-
-type grpcServer struct {
-	server      envoy_xds.Server
-	port        int
-	tlsCertFile string
-	tlsKeyFile  string
-	metrics     metrics.Metrics
-}
-
-func (s *grpcServer) NeedLeaderElection() bool {
-	return false
-}
-
-// Make sure that grpcServer implements all relevant interfaces
-var (
-	_ component.Component = &grpcServer{}
-)
-
-func (s *grpcServer) Start(stop <-chan struct{}) error {
-	grpcOptions := []grpc.ServerOption{
-		grpc.MaxConcurrentStreams(grpcMaxConcurrentStreams),
-	}
-	grpcOptions = append(grpcOptions, s.metrics.GRPCServerInterceptors()...)
-	useTLS := s.tlsCertFile != ""
-	if useTLS {
-		creds, err := credentials.NewServerTLSFromFile(s.tlsCertFile, s.tlsKeyFile)
-		if err != nil {
-			return errors.Wrap(err, "failed to load TLS certificate")
-		}
-		grpcOptions = append(grpcOptions, grpc.Creds(creds))
-	}
-	grpcServer := grpc.NewServer(grpcOptions...)
-
-	// register services
-	envoy_discovery.RegisterAggregatedDiscoveryServiceServer(grpcServer, s.server)
-	s.metrics.RegisterGRPC(grpcServer)
-
-	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", s.port))
-	if err != nil {
-		return err
-	}
-
-	errChan := make(chan error)
-	go func() {
-		defer close(errChan)
-		if err = grpcServer.Serve(lis); err != nil {
-			grpcServerLog.Error(err, "terminated with an error")
-			errChan <- err
-		} else {
-			grpcServerLog.Info("terminated normally")
-		}
-	}()
-	grpcServerLog.Info("starting", "interface", "0.0.0.0", "port", s.port, "tls", useTLS)
-
-	select {
-	case <-stop:
-		grpcServerLog.Info("stopping gracefully")
-		grpcServer.GracefulStop()
-		return nil
-	case err := <-errChan:
-		return err
-	}
-}
diff --git a/pkg/xds/server/v2/components.go b/pkg/xds/server/v2/components.go
new file mode 100644
index 000000000..b4af5efd1
--- /dev/null
+++ b/pkg/xds/server/v2/components.go
@@ -0,0 +1,90 @@
+package v2
+
+import (
+	"context"
+
+	envoy_service_discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2"
+	envoy_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
+	"google.golang.org/grpc"
+
+	"github.com/kumahq/kuma/pkg/core"
+	core_runtime "github.com/kumahq/kuma/pkg/core/runtime"
+	util_xds "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
+	"github.com/kumahq/kuma/pkg/xds/auth"
+	auth_components "github.com/kumahq/kuma/pkg/xds/auth/components"
+	xds_server "github.com/kumahq/kuma/pkg/xds/server"
+	xds_callbacks "github.com/kumahq/kuma/pkg/xds/server/callbacks"
+	xds_sync "github.com/kumahq/kuma/pkg/xds/sync"
+	xds_template "github.com/kumahq/kuma/pkg/xds/template"
+)
+
+var xdsServerLog = core.Log.WithName("xds-server")
+
+func RegisterXDS(rt core_runtime.Runtime, server *grpc.Server) error {
+	callbacks, err := DefaultCallbacks(rt)
+	if err != nil {
+		return err
+	}
+	srv := envoy_server.NewServer(context.Background(), rt.XDS().Cache(), callbacks)
+
+	xdsServerLog.Info("registering Aggregated Discovery Service in Dataplane Server")
+	envoy_service_discovery.RegisterAggregatedDiscoveryServiceServer(server, srv)
+	return nil
+}
+
+func DefaultCallbacks(rt core_runtime.Runtime) (envoy_server.Callbacks, error) {
+	authenticator, err := auth_components.DefaultAuthenticator(rt)
+	if err != nil {
+		return nil, err
+	}
+	authCallbacks := auth.NewCallbacks(rt.ResourceManager(), authenticator)
+
+	metadataTracker := xds_callbacks.NewDataplaneMetadataTracker()
+	connectionInfoTracker := xds_callbacks.NewConnectionInfoTracker()
+
+	reconciler := DefaultReconciler(rt)
+	ingressReconciler := DefaultIngressReconciler(rt)
+	watchdogFactory, err := xds_sync.DefaultDataplaneWatchdogFactory(rt, metadataTracker, connectionInfoTracker, reconciler, ingressReconciler)
+	if err != nil {
+		return nil, err
+	}
+
+	statsCallbacks, err := util_xds.NewStatsCallbacks(rt.Metrics(), "xds")
+	if err != nil {
+		return nil, err
+	}
+	return util_xds_v2.CallbacksChain{
+		util_xds_v2.AdaptCallbacks(statsCallbacks),
+		util_xds_v2.AdaptCallbacks(connectionInfoTracker),
+		util_xds_v2.AdaptCallbacks(authCallbacks),
+		util_xds_v2.AdaptCallbacks(xds_callbacks.NewDataplaneSyncTracker(watchdogFactory.New)),
+		util_xds_v2.AdaptCallbacks(metadataTracker),
+		util_xds_v2.AdaptCallbacks(xds_callbacks.NewDataplaneLifecycle(rt.ResourceManager())),
+		util_xds_v2.AdaptCallbacks(xds_server.DefaultDataplaneStatusTracker(rt)),
+		newResourceWarmingForcer(rt.XDS().Cache(), rt.XDS().Hasher()),
+	}, nil
+}
+
+func DefaultReconciler(rt core_runtime.Runtime) xds_sync.SnapshotReconciler {
+	return &reconciler{
+		&templateSnapshotGenerator{
+			ProxyTemplateResolver: &xds_template.SimpleProxyTemplateResolver{
+				ReadOnlyResourceManager: rt.ReadOnlyResourceManager(),
+				DefaultProxyTemplate:    xds_template.DefaultProxyTemplate,
+			},
+		},
+		&simpleSnapshotCacher{rt.XDS().Hasher(), rt.XDS().Cache()},
+	}
+}
+
+func DefaultIngressReconciler(rt core_runtime.Runtime) xds_sync.SnapshotReconciler {
+	return &reconciler{
+		generator: &templateSnapshotGenerator{
+			ProxyTemplateResolver: &xds_template.StaticProxyTemplateResolver{
+				Template: xds_template.IngressProxyTemplate,
+			},
+		},
+		cacher: &simpleSnapshotCacher{rt.XDS().Hasher(), rt.XDS().Cache()},
+	}
+}
diff --git a/pkg/xds/server/reconcile.go b/pkg/xds/server/v2/reconcile.go
similarity index 95%
rename from pkg/xds/server/reconcile.go
rename to pkg/xds/server/v2/reconcile.go
index e7c96559f..a5cdbfdf4 100644
--- a/pkg/xds/server/reconcile.go
+++ b/pkg/xds/server/v2/reconcile.go
@@ -1,4 +1,4 @@
-package server
+package v2
 
 import (
 	"github.com/golang/protobuf/proto"
@@ -7,6 +7,8 @@ import (
 	model "github.com/kumahq/kuma/pkg/core/xds"
 	xds_context "github.com/kumahq/kuma/pkg/xds/context"
 	"github.com/kumahq/kuma/pkg/xds/generator"
+	xds_sync "github.com/kumahq/kuma/pkg/xds/sync"
+	xds_template "github.com/kumahq/kuma/pkg/xds/template"
 
 	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
 	envoy_types "github.com/envoyproxy/go-control-plane/pkg/cache/types"
@@ -18,12 +20,7 @@ var (
 	reconcileLog = core.Log.WithName("xds-server").WithName("reconcile")
 )
 
-type SnapshotReconciler interface {
-	Reconcile(ctx xds_context.Context, proxy *model.Proxy) error
-	Clear(proxyId *model.ProxyId) error
-}
-
-var _ SnapshotReconciler = &reconciler{}
+var _ xds_sync.SnapshotReconciler = &reconciler{}
 
 type reconciler struct {
 	generator snapshotGenerator
@@ -73,7 +70,7 @@ func (r *reconciler) autoVersion(old envoy_cache.Snapshot, new envoy_cache.Snaps
 func reuseVersion(old, new envoy_cache.Resources) envoy_cache.Resources {
 	new.Version = old.Version
 	if !equalSnapshots(old.Items, new.Items) {
-		new.Version = newUUID()
+		new.Version = core.NewUUID()
 	}
 	return new
 }
@@ -95,7 +92,7 @@ type snapshotGenerator interface {
 }
 
 type templateSnapshotGenerator struct {
-	ProxyTemplateResolver proxyTemplateResolver
+	ProxyTemplateResolver xds_template.ProxyTemplateResolver
 }
 
 func (s *templateSnapshotGenerator) GenerateSnapshot(ctx xds_context.Context, proxy *model.Proxy) (envoy_cache.Snapshot, error) {
diff --git a/pkg/xds/server/resource_warming_forcer.go b/pkg/xds/server/v2/resource_warming_forcer.go
similarity index 98%
rename from pkg/xds/server/resource_warming_forcer.go
rename to pkg/xds/server/v2/resource_warming_forcer.go
index 85ec9fcc8..ee3e3c640 100644
--- a/pkg/xds/server/resource_warming_forcer.go
+++ b/pkg/xds/server/v2/resource_warming_forcer.go
@@ -1,4 +1,4 @@
-package server
+package v2
 
 import (
 	"sync"
@@ -12,7 +12,7 @@ import (
 
 	"github.com/kumahq/kuma/pkg/core"
 	"github.com/kumahq/kuma/pkg/core/xds"
-	util_xds "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 )
 
 var warmingForcerLog = xdsServerLog.WithName("warming-forcer")
@@ -55,7 +55,7 @@ var warmingForcerLog = xdsServerLog.WithName("warming-forcer")
 // The same problem is with Listeners and Routes (change of the Listener that uses RDS requires RDS DiscoveryResponse), but since we don't use RDS now, the implementation is for EDS only.
 // More reading of how Envoy is trying to solve it https://github.com/envoyproxy/envoy/issues/13009
 type resourceWarmingForcer struct {
-	util_xds.NoopCallbacks
+	util_xds_v2.NoopCallbacks
 	cache  envoy_cache.SnapshotCache
 	hasher envoy_cache.NodeHash
 
diff --git a/pkg/xds/server/testdata/dataplane.input.yaml b/pkg/xds/server/v2/testdata/dataplane.input.yaml
similarity index 100%
rename from pkg/xds/server/testdata/dataplane.input.yaml
rename to pkg/xds/server/v2/testdata/dataplane.input.yaml
diff --git a/pkg/xds/server/testdata/envoy-config.golden.yaml b/pkg/xds/server/v2/testdata/envoy-config.golden.yaml
similarity index 100%
rename from pkg/xds/server/testdata/envoy-config.golden.yaml
rename to pkg/xds/server/v2/testdata/envoy-config.golden.yaml
diff --git a/pkg/xds/sync/components.go b/pkg/xds/sync/components.go
new file mode 100644
index 000000000..2638b6747
--- /dev/null
+++ b/pkg/xds/sync/components.go
@@ -0,0 +1,103 @@
+package sync
+
+import (
+	"github.com/kumahq/kuma/pkg/core"
+	"github.com/kumahq/kuma/pkg/core/faultinjections"
+	"github.com/kumahq/kuma/pkg/core/logs"
+	"github.com/kumahq/kuma/pkg/core/permissions"
+	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
+	core_system "github.com/kumahq/kuma/pkg/core/resources/apis/system"
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
+	"github.com/kumahq/kuma/pkg/core/resources/registry"
+	core_runtime "github.com/kumahq/kuma/pkg/core/runtime"
+	"github.com/kumahq/kuma/pkg/xds/cache/cla"
+	"github.com/kumahq/kuma/pkg/xds/cache/mesh"
+	xds_context "github.com/kumahq/kuma/pkg/xds/context"
+)
+
+var (
+	xdsServerLog  = core.Log.WithName("xds-server")
+	meshResources = meshResourceTypes(map[core_model.ResourceType]bool{
+		core_mesh.DataplaneInsightType:  true,
+		core_mesh.DataplaneOverviewType: true,
+		core_mesh.ServiceInsightType:    true,
+		core_system.ConfigType:          true,
+	})
+)
+
+func meshResourceTypes(exclude map[core_model.ResourceType]bool) []core_model.ResourceType {
+	types := []core_model.ResourceType{}
+	for _, typ := range registry.Global().ListTypes() {
+		r, err := registry.Global().NewObject(typ)
+		if err != nil {
+			panic(err)
+		}
+		if r.Scope() == core_model.ScopeMesh && !exclude[typ] {
+			types = append(types, typ)
+		}
+	}
+	return types
+}
+
+func defaultDataplaneProxyBuilder(rt core_runtime.Runtime, metadataTracker DataplaneMetadataTracker) *dataplaneProxyBuilder {
+	return &dataplaneProxyBuilder{
+		ResManager:            rt.ReadOnlyResourceManager(),
+		LookupIP:              rt.LookupIP(),
+		DataSourceLoader:      rt.DataSourceLoader(),
+		MetadataTracker:       metadataTracker,
+		PermissionMatcher:     permissions.TrafficPermissionsMatcher{ResourceManager: rt.ReadOnlyResourceManager()},
+		LogsMatcher:           logs.TrafficLogsMatcher{ResourceManager: rt.ReadOnlyResourceManager()},
+		FaultInjectionMatcher: faultinjections.FaultInjectionMatcher{ResourceManager: rt.ReadOnlyResourceManager()},
+		Zone:                  rt.Config().Multizone.Remote.Zone,
+	}
+}
+
+func defaultIngressProxyBuilder(rt core_runtime.Runtime, metadataTracker DataplaneMetadataTracker) *ingressProxyBuilder {
+	return &ingressProxyBuilder{
+		ResManager:         rt.ResourceManager(),
+		ReadOnlyResManager: rt.ReadOnlyResourceManager(),
+		LookupIP:           rt.LookupIP(),
+		MetadataTracker:    metadataTracker,
+	}
+}
+
+func DefaultDataplaneWatchdogFactory(
+	rt core_runtime.Runtime,
+	metadataTracker DataplaneMetadataTracker,
+	connectionInfoTracker ConnectionInfoTracker,
+	dataplaneReconciler SnapshotReconciler,
+	ingressReconciler SnapshotReconciler,
+) (DataplaneWatchdogFactory, error) {
+	claCache, err := cla.NewCache(rt.ReadOnlyResourceManager(), rt.DataSourceLoader(), rt.Config().Multizone.Remote.Zone, rt.Config().Store.Cache.ExpirationTime, rt.LookupIP(), rt.Metrics())
+	if err != nil {
+		return nil, err
+	}
+	dataplaneProxyBuilder := defaultDataplaneProxyBuilder(rt, metadataTracker)
+	ingressProxyBuilder := defaultIngressProxyBuilder(rt, metadataTracker)
+	meshSnapshotCache, err := mesh.NewCache(rt.ReadOnlyResourceManager(), rt.Config().Store.Cache.ExpirationTime, meshResources, rt.LookupIP(), rt.Metrics())
+	if err != nil {
+		return nil, err
+	}
+
+	envoyCpCtx, err := xds_context.BuildControlPlaneContext(rt.Config(), claCache)
+	if err != nil {
+		return nil, err
+	}
+
+	xdsContextBuilder := newXDSContextBuilder(envoyCpCtx, connectionInfoTracker, rt.ReadOnlyResourceManager(), rt.LookupIP())
+
+	deps := DataplaneWatchdogDependencies{
+		resManager:            rt.ResourceManager(),
+		dataplaneProxyBuilder: dataplaneProxyBuilder,
+		dataplaneReconciler:   dataplaneReconciler,
+		ingressProxyBuilder:   ingressProxyBuilder,
+		ingressReconciler:     ingressReconciler,
+		xdsContextBuilder:     xdsContextBuilder,
+		meshCache:             meshSnapshotCache,
+	}
+	return NewDataplaneWatchdogFactory(
+		rt.Metrics(),
+		rt.Config().XdsServer.DataplaneConfigurationRefreshInterval,
+		deps,
+	)
+}
diff --git a/pkg/xds/sync/dataplane_proxy_builder.go b/pkg/xds/sync/dataplane_proxy_builder.go
new file mode 100644
index 000000000..c349ddfce
--- /dev/null
+++ b/pkg/xds/sync/dataplane_proxy_builder.go
@@ -0,0 +1,155 @@
+package sync
+
+import (
+	"context"
+
+	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
+	"github.com/kumahq/kuma/pkg/core"
+	"github.com/kumahq/kuma/pkg/core/datasource"
+	"github.com/kumahq/kuma/pkg/core/dns/lookup"
+	"github.com/kumahq/kuma/pkg/core/faultinjections"
+	"github.com/kumahq/kuma/pkg/core/logs"
+	"github.com/kumahq/kuma/pkg/core/permissions"
+	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
+	"github.com/kumahq/kuma/pkg/core/resources/manager"
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
+	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
+	"github.com/kumahq/kuma/pkg/core/xds"
+	xds_context "github.com/kumahq/kuma/pkg/xds/context"
+	xds_topology "github.com/kumahq/kuma/pkg/xds/topology"
+)
+
+var syncLog = core.Log.WithName("sync")
+
+type dataplaneProxyBuilder struct {
+	ResManager            manager.ReadOnlyResourceManager
+	LookupIP              lookup.LookupIPFunc
+	DataSourceLoader      datasource.Loader
+	MetadataTracker       DataplaneMetadataTracker
+	PermissionMatcher     permissions.TrafficPermissionsMatcher
+	LogsMatcher           logs.TrafficLogsMatcher
+	FaultInjectionMatcher faultinjections.FaultInjectionMatcher
+
+	Zone string
+}
+
+func (p *dataplaneProxyBuilder) build(key core_model.ResourceKey, streamId int64, meshCtx *xds_context.MeshContext) (*xds.Proxy, error) {
+	ctx := context.Background()
+
+	dp, err := p.resolveDataplane(ctx, key)
+	if err != nil {
+		return nil, err
+	}
+
+	routing, destinations, err := p.resolveRouting(ctx, meshCtx, dp)
+	if err != nil {
+		return nil, err
+	}
+
+	matchedPolicies, err := p.matchPolicies(ctx, meshCtx, dp, destinations)
+	if err != nil {
+		return nil, err
+	}
+
+	proxy := &xds.Proxy{
+		Id:        xds.FromResourceKey(key),
+		Dataplane: dp,
+		Metadata:  p.MetadataTracker.Metadata(streamId),
+		Routing:   *routing,
+		Policies:  *matchedPolicies,
+	}
+	return proxy, nil
+}
+
+func (p *dataplaneProxyBuilder) resolveDataplane(ctx context.Context, key core_model.ResourceKey) (*core_mesh.DataplaneResource, error) {
+	dataplane := core_mesh.NewDataplaneResource()
+
+	// we use non-cached ResourceManager to always fetch fresh version of the Dataplane.
+	// Otherwise, technically MeshCache can use newer version because it uses List operation instead of Get
+	if err := p.ResManager.Get(ctx, dataplane, core_store.GetBy(key)); err != nil {
+		return nil, err
+	}
+
+	// Envoy requires IPs instead of Hostname therefore we need to resolve an address. Consider moving this outside of this component.
+	resolvedDp, err := xds_topology.ResolveAddress(p.LookupIP, dataplane)
+	if err != nil {
+		return nil, err
+	}
+	return resolvedDp, nil
+}
+
+func (p *dataplaneProxyBuilder) resolveRouting(
+	ctx context.Context,
+	meshContext *xds_context.MeshContext,
+	dataplane *core_mesh.DataplaneResource,
+) (*xds.Routing, xds.DestinationMap, error) {
+	externalServices := &core_mesh.ExternalServiceResourceList{}
+	if err := p.ResManager.List(ctx, externalServices, core_store.ListByMesh(dataplane.Meta.GetMesh())); err != nil {
+		return nil, nil, err
+	}
+
+	// pick a single the most specific route for each outbound interface
+	routes, err := xds_topology.GetRoutes(ctx, dataplane, p.ResManager)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// create creates a map of selectors to match other dataplanes reachable via given routes
+	destinations := xds_topology.BuildDestinationMap(dataplane, routes)
+
+	// resolve all endpoints that match given selectors
+	outbound := xds_topology.BuildEndpointMap(meshContext.Resource, p.Zone, meshContext.Dataplanes.Items, externalServices.Items, p.DataSourceLoader)
+
+	routing := &xds.Routing{
+		TrafficRoutes:   routes,
+		OutboundTargets: outbound,
+	}
+	return routing, destinations, nil
+}
+
+func (p *dataplaneProxyBuilder) matchPolicies(ctx context.Context, meshContext *xds_context.MeshContext, dataplane *core_mesh.DataplaneResource, outboundSelectors xds.DestinationMap) (*xds.MatchedPolicies, error) {
+	healthChecks, err := xds_topology.GetHealthChecks(ctx, dataplane, outboundSelectors, p.ResManager)
+	if err != nil {
+		return nil, err
+	}
+
+	circuitBreakers, err := xds_topology.GetCircuitBreakers(ctx, dataplane, outboundSelectors, p.ResManager)
+	if err != nil {
+		return nil, err
+	}
+
+	trafficTrace, err := xds_topology.GetTrafficTrace(ctx, dataplane, p.ResManager)
+	if err != nil {
+		return nil, err
+	}
+	var tracingBackend *mesh_proto.TracingBackend
+	if trafficTrace != nil {
+		tracingBackend = meshContext.Resource.GetTracingBackend(trafficTrace.Spec.GetConf().GetBackend())
+	}
+
+	matchedPermissions, err := p.PermissionMatcher.Match(ctx, dataplane, meshContext.Resource)
+	if err != nil {
+		return nil, err
+	}
+
+	matchedLogs, err := p.LogsMatcher.Match(ctx, dataplane)
+	if err != nil {
+		return nil, err
+	}
+
+	faultInjection, err := p.FaultInjectionMatcher.Match(ctx, dataplane, meshContext.Resource)
+	if err != nil {
+		return nil, err
+	}
+
+	matchedPolicies := &xds.MatchedPolicies{
+		TrafficPermissions: matchedPermissions,
+		Logs:               matchedLogs,
+		HealthChecks:       healthChecks,
+		CircuitBreakers:    circuitBreakers,
+		TrafficTrace:       trafficTrace,
+		TracingBackend:     tracingBackend,
+		FaultInjections:    faultInjection,
+	}
+	return matchedPolicies, nil
+}
diff --git a/pkg/xds/sync/dataplane_watchdog.go b/pkg/xds/sync/dataplane_watchdog.go
new file mode 100644
index 000000000..2560f576e
--- /dev/null
+++ b/pkg/xds/sync/dataplane_watchdog.go
@@ -0,0 +1,126 @@
+package sync
+
+import (
+	"context"
+
+	"github.com/go-logr/logr"
+
+	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
+	"github.com/kumahq/kuma/pkg/core"
+	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
+	"github.com/kumahq/kuma/pkg/core/resources/manager"
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
+	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
+	"github.com/kumahq/kuma/pkg/core/xds"
+	"github.com/kumahq/kuma/pkg/xds/cache/mesh"
+)
+
+type DataplaneWatchdogDependencies struct {
+	resManager            manager.ResourceManager
+	dataplaneProxyBuilder *dataplaneProxyBuilder
+	dataplaneReconciler   SnapshotReconciler
+	ingressProxyBuilder   *ingressProxyBuilder
+	ingressReconciler     SnapshotReconciler
+	xdsContextBuilder     *xdsContextBuilder
+	meshCache             *mesh.Cache
+}
+
+type DataplaneWatchdog struct {
+	DataplaneWatchdogDependencies
+	key      core_model.ResourceKey
+	streamId int64
+	log      logr.Logger
+
+	// state of watchdog
+	lastHash string // last Mesh hash that was used to **successfully** generate Reconcile Envoy config
+	dpType   mesh_proto.DpType
+}
+
+func NewDataplaneWatchdog(deps DataplaneWatchdogDependencies, key core_model.ResourceKey, streamId int64) *DataplaneWatchdog {
+	return &DataplaneWatchdog{
+		DataplaneWatchdogDependencies: deps,
+		key:                           key,
+		streamId:                      streamId,
+		log:                           core.Log.WithValues("key", "key", "streamID", streamId),
+	}
+}
+
+func (d *DataplaneWatchdog) Sync() error {
+	if d.dpType == "" {
+		// Dataplane type does not change over time therefore we need to figure it once per DataplaneWatchdog
+		if err := d.inferDpType(); err != nil {
+			return err
+		}
+	}
+	switch d.dpType {
+	case mesh_proto.RegularDpType, mesh_proto.GatewayDpType:
+		return d.syncDataplane()
+	case mesh_proto.IngressDpType:
+		return d.syncIngress()
+	default:
+		// It might be a case that dp type is not yet inferred because there is no Dataplane definition yet.
+		return nil
+	}
+}
+
+func (d *DataplaneWatchdog) Cleanup() error {
+	proxyID := xds.FromResourceKey(d.key)
+	switch d.dpType {
+	case mesh_proto.RegularDpType, mesh_proto.GatewayDpType:
+		return d.dataplaneReconciler.Clear(&proxyID)
+	case mesh_proto.IngressDpType:
+		return d.ingressReconciler.Clear(&proxyID)
+	default:
+		return nil
+	}
+}
+
+func (d *DataplaneWatchdog) inferDpType() error {
+	dataplane := core_mesh.NewDataplaneResource()
+	if err := d.resManager.Get(context.Background(), dataplane, core_store.GetBy(d.key)); err != nil {
+		if core_store.IsResourceNotFound(err) {
+			return nil
+		}
+		return err
+	}
+	d.dpType = dataplane.Spec.DpType()
+	return nil
+}
+
+// syncDataplane syncs state of the Dataplane.
+// It uses Mesh Hash to decide if we need to regenerate configuration or not.
+func (d *DataplaneWatchdog) syncDataplane() error {
+	snapshotHash, err := d.meshCache.GetHash(context.Background(), d.key.Mesh)
+	if err != nil {
+		return err
+	}
+	if d.lastHash != "" && snapshotHash == d.lastHash {
+		// Kuma policies (including Dataplanes and Mesh) has not change therefore there is no need to regenerate configuration.
+		return nil
+	}
+	d.log.V(1).Info("snapshot hash updated, reconcile", "prev", d.lastHash, "current", snapshotHash)
+
+	envoyCtx, err := d.xdsContextBuilder.buildMeshedContext(d.streamId, d.key.Mesh, d.lastHash)
+	if err != nil {
+		return err
+	}
+	proxy, err := d.dataplaneProxyBuilder.build(d.key, d.streamId, &envoyCtx.Mesh)
+	if err != nil {
+		return err
+	}
+	if err := d.dataplaneReconciler.Reconcile(*envoyCtx, proxy); err != nil {
+		return err
+	}
+	d.lastHash = snapshotHash
+	return nil
+}
+
+// syncIngress synces state of Ingress Dataplane. Notice that it does not use Mesh Hash yet because Ingress supports many Meshes.
+func (d *DataplaneWatchdog) syncIngress() error {
+	envoyCtx := d.xdsContextBuilder.buildContext(d.streamId)
+	proxy, err := d.ingressProxyBuilder.build(d.key, d.streamId)
+	if err != nil {
+		return err
+	}
+	return d.ingressReconciler.Reconcile(*envoyCtx, proxy)
+}
diff --git a/pkg/xds/sync/dataplane_watchdog_factory.go b/pkg/xds/sync/dataplane_watchdog_factory.go
new file mode 100644
index 000000000..63d62748b
--- /dev/null
+++ b/pkg/xds/sync/dataplane_watchdog_factory.go
@@ -0,0 +1,75 @@
+package sync
+
+import (
+	"time"
+
+	"github.com/prometheus/client_golang/prometheus"
+
+	"github.com/kumahq/kuma/pkg/core"
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
+	core_metrics "github.com/kumahq/kuma/pkg/metrics"
+	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
+)
+
+type dataplaneWatchdogFactory struct {
+	xdsGenerations       prometheus.Summary
+	xdsGenerationsErrors prometheus.Counter
+	refreshInterval      time.Duration
+
+	deps DataplaneWatchdogDependencies
+}
+
+func NewDataplaneWatchdogFactory(
+	metrics core_metrics.Metrics,
+	refreshInterval time.Duration,
+	deps DataplaneWatchdogDependencies,
+) (DataplaneWatchdogFactory, error) {
+	xdsGenerations := prometheus.NewSummary(prometheus.SummaryOpts{
+		Name:       "xds_generation",
+		Help:       "Summary of XDS Snapshot generation",
+		Objectives: core_metrics.DefaultObjectives,
+	})
+	if err := metrics.Register(xdsGenerations); err != nil {
+		return nil, err
+	}
+	xdsGenerationsErrors := prometheus.NewCounter(prometheus.CounterOpts{
+		Name: "xds_generation_errors",
+		Help: "Counter of errors during XDS generation",
+	})
+	if err := metrics.Register(xdsGenerationsErrors); err != nil {
+		return nil, err
+	}
+
+	return &dataplaneWatchdogFactory{
+		deps:                 deps,
+		refreshInterval:      refreshInterval,
+		xdsGenerations:       xdsGenerations,
+		xdsGenerationsErrors: xdsGenerationsErrors,
+	}, nil
+}
+
+func (d *dataplaneWatchdogFactory) New(key core_model.ResourceKey, streamId int64) util_watchdog.Watchdog {
+	log := xdsServerLog.WithName("dataplane-sync-watchdog").WithValues("dataplaneKey", key)
+	dataplaneWatchdog := NewDataplaneWatchdog(d.deps, key, streamId)
+	return &util_watchdog.SimpleWatchdog{
+		NewTicker: func() *time.Ticker {
+			return time.NewTicker(d.refreshInterval)
+		},
+		OnTick: func() error {
+			start := core.Now()
+			defer func() {
+				d.xdsGenerations.Observe(float64(core.Now().Sub(start).Milliseconds()))
+			}()
+			return dataplaneWatchdog.Sync()
+		},
+		OnError: func(err error) {
+			d.xdsGenerationsErrors.Inc()
+			log.Error(err, "OnTick() failed")
+		},
+		OnStop: func() {
+			if err := dataplaneWatchdog.Cleanup(); err != nil {
+				log.Error(err, "OnTick() failed")
+			}
+		},
+	}
+}
diff --git a/pkg/xds/sync/ingress_proxy_builder.go b/pkg/xds/sync/ingress_proxy_builder.go
new file mode 100644
index 000000000..ecc5ce538
--- /dev/null
+++ b/pkg/xds/sync/ingress_proxy_builder.go
@@ -0,0 +1,86 @@
+package sync
+
+import (
+	"context"
+
+	"github.com/kumahq/kuma/pkg/core/dns/lookup"
+	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
+	"github.com/kumahq/kuma/pkg/core/resources/manager"
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
+	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
+	"github.com/kumahq/kuma/pkg/core/xds"
+	"github.com/kumahq/kuma/pkg/xds/ingress"
+	xds_topology "github.com/kumahq/kuma/pkg/xds/topology"
+)
+
+type ingressProxyBuilder struct {
+	ResManager         manager.ResourceManager
+	ReadOnlyResManager manager.ReadOnlyResourceManager
+	LookupIP           lookup.LookupIPFunc
+	MetadataTracker    DataplaneMetadataTracker
+}
+
+func (p *ingressProxyBuilder) build(key core_model.ResourceKey, streamId int64) (*xds.Proxy, error) {
+	ctx := context.Background()
+
+	dp, err := p.resolveDataplane(ctx, key)
+	if err != nil {
+		return nil, err
+	}
+
+	allMeshDataplanes := &core_mesh.DataplaneResourceList{}
+	if err := p.ReadOnlyResManager.List(ctx, allMeshDataplanes); err != nil {
+		return nil, err
+	}
+	allMeshDataplanes.Items = xds_topology.ResolveAddresses(syncLog, p.LookupIP, allMeshDataplanes.Items)
+
+	// Update Ingress' Available Services
+	// This was placed as an operation of DataplaneWatchdog out of the convenience.
+	// Consider moving to the outside of this component (follow the pattern of updating VIP outbounds)
+	if err := ingress.UpdateAvailableServices(ctx, p.ResManager, dp, allMeshDataplanes.Items); err != nil {
+		return nil, err
+	}
+
+	routing, err := p.resolveRouting(ctx, dp, allMeshDataplanes)
+	if err != nil {
+		return nil, err
+	}
+
+	proxy := &xds.Proxy{
+		Id:        xds.FromResourceKey(key),
+		Dataplane: dp,
+		Metadata:  p.MetadataTracker.Metadata(streamId),
+		Routing:   *routing,
+	}
+	return proxy, nil
+}
+
+func (p *ingressProxyBuilder) resolveDataplane(ctx context.Context, key core_model.ResourceKey) (*core_mesh.DataplaneResource, error) {
+	dataplane := core_mesh.NewDataplaneResource()
+
+	if err := p.ReadOnlyResManager.Get(ctx, dataplane, core_store.GetBy(key)); err != nil {
+		return nil, err
+	}
+
+	// Envoy requires IPs instead of Hostname therefore we need to resolve an address. Consider moving this outside of this component.
+	resolvedDp, err := xds_topology.ResolveAddress(p.LookupIP, dataplane)
+	if err != nil {
+		return nil, err
+	}
+	return resolvedDp, nil
+}
+
+func (p *ingressProxyBuilder) resolveRouting(ctx context.Context, dataplane *core_mesh.DataplaneResource, dataplanes *core_mesh.DataplaneResourceList) (*xds.Routing, error) {
+	destinations := ingress.BuildDestinationMap(dataplane)
+	endpoints := ingress.BuildEndpointMap(destinations, dataplanes.Items)
+	routes := &core_mesh.TrafficRouteResourceList{}
+	if err := p.ReadOnlyResManager.List(ctx, routes); err != nil {
+		return nil, err
+	}
+
+	routing := &xds.Routing{
+		OutboundTargets:  endpoints,
+		TrafficRouteList: routes,
+	}
+	return routing, nil
+}
diff --git a/pkg/xds/sync/interfaces.go b/pkg/xds/sync/interfaces.go
new file mode 100644
index 000000000..4c5c2f5b0
--- /dev/null
+++ b/pkg/xds/sync/interfaces.go
@@ -0,0 +1,27 @@
+package sync
+
+import (
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
+	core_xds "github.com/kumahq/kuma/pkg/core/xds"
+	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
+	xds_context "github.com/kumahq/kuma/pkg/xds/context"
+)
+
+type DataplaneMetadataTracker interface {
+	Metadata(streamID core_xds.StreamID) *core_xds.DataplaneMetadata
+}
+
+type ConnectionInfoTracker interface {
+	ConnectionInfo(streamID core_xds.StreamID) xds_context.ConnectionInfo
+}
+
+// SnapshotReconciler reconciles Envoy XDS configuration (Snapshot) by executing all generators (pkg/xds/generator)
+type SnapshotReconciler interface {
+	Reconcile(ctx xds_context.Context, proxy *core_xds.Proxy) error
+	Clear(proxyId *core_xds.ProxyId) error
+}
+
+// DataplaneWatchdogFactory returns a Watchdog that creates a new XdsContext and Proxy and executes SnapshotReconciler if there is any change
+type DataplaneWatchdogFactory interface {
+	New(key core_model.ResourceKey, streamId int64) util_watchdog.Watchdog
+}
diff --git a/pkg/xds/sync/xds_context_builder.go b/pkg/xds/sync/xds_context_builder.go
new file mode 100644
index 000000000..e5c4ad945
--- /dev/null
+++ b/pkg/xds/sync/xds_context_builder.go
@@ -0,0 +1,64 @@
+package sync
+
+import (
+	"context"
+
+	"github.com/kumahq/kuma/pkg/core/dns/lookup"
+	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
+	"github.com/kumahq/kuma/pkg/core/resources/manager"
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
+	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
+	xds_context "github.com/kumahq/kuma/pkg/xds/context"
+	xds_topology "github.com/kumahq/kuma/pkg/xds/topology"
+)
+
+type xdsContextBuilder struct {
+	resManager            manager.ReadOnlyResourceManager
+	connectionInfoTracker ConnectionInfoTracker
+	lookupIP              lookup.LookupIPFunc
+
+	cpContext *xds_context.ControlPlaneContext
+}
+
+func newXDSContextBuilder(
+	cpContext *xds_context.ControlPlaneContext,
+	connectionInfoTracker ConnectionInfoTracker,
+	resManager manager.ReadOnlyResourceManager,
+	lookupIP lookup.LookupIPFunc,
+) *xdsContextBuilder {
+	return &xdsContextBuilder{
+		resManager:            resManager,
+		connectionInfoTracker: connectionInfoTracker,
+		lookupIP:              lookupIP,
+		cpContext:             cpContext,
+	}
+}
+
+func (c *xdsContextBuilder) buildMeshedContext(streamId int64, meshName string, meshHash string) (*xds_context.Context, error) {
+	ctx := context.Background()
+	xdsCtx := c.buildContext(streamId)
+
+	mesh := core_mesh.NewMeshResource()
+	if err := c.resManager.Get(ctx, mesh, core_store.GetByKey(meshName, core_model.NoMesh)); err != nil {
+		return nil, err
+	}
+
+	dataplanes, err := xds_topology.GetDataplanes(syncLog, context.Background(), c.resManager, c.lookupIP, meshName)
+	if err != nil {
+		return nil, err
+	}
+	xdsCtx.Mesh = xds_context.MeshContext{
+		Resource:   mesh,
+		Dataplanes: dataplanes,
+		Hash:       meshHash,
+	}
+	return xdsCtx, nil
+}
+
+func (c *xdsContextBuilder) buildContext(streamId int64) *xds_context.Context {
+	return &xds_context.Context{
+		ControlPlane:   c.cpContext,
+		ConnectionInfo: c.connectionInfoTracker.ConnectionInfo(streamId),
+		Mesh:           xds_context.MeshContext{},
+	}
+}
diff --git a/pkg/xds/server/proxy_template_resolver.go b/pkg/xds/template/proxy_template_resolver.go
similarity index 84%
rename from pkg/xds/server/proxy_template_resolver.go
rename to pkg/xds/template/proxy_template_resolver.go
index b6df6dcf6..2c4d7a25d 100644
--- a/pkg/xds/server/proxy_template_resolver.go
+++ b/pkg/xds/template/proxy_template_resolver.go
@@ -1,4 +1,4 @@
-package server
+package template
 
 import (
 	"context"
@@ -17,16 +17,16 @@ var (
 	templateResolverLog = core.Log.WithName("proxy-template-resolver")
 )
 
-type proxyTemplateResolver interface {
+type ProxyTemplateResolver interface {
 	GetTemplate(proxy *model.Proxy) *mesh_proto.ProxyTemplate
 }
 
-type simpleProxyTemplateResolver struct {
+type SimpleProxyTemplateResolver struct {
 	manager.ReadOnlyResourceManager
 	DefaultProxyTemplate *mesh_proto.ProxyTemplate
 }
 
-func (r *simpleProxyTemplateResolver) GetTemplate(proxy *model.Proxy) *mesh_proto.ProxyTemplate {
+func (r *SimpleProxyTemplateResolver) GetTemplate(proxy *model.Proxy) *mesh_proto.ProxyTemplate {
 	log := templateResolverLog.WithValues("dataplane", core_model.MetaToResourceKey(proxy.Dataplane.Meta))
 	ctx := context.Background()
 	templateList := &mesh_core.ProxyTemplateResourceList{}
@@ -48,10 +48,10 @@ func (r *simpleProxyTemplateResolver) GetTemplate(proxy *model.Proxy) *mesh_prot
 	return r.DefaultProxyTemplate
 }
 
-type staticProxyTemplateResolver struct {
-	template *mesh_proto.ProxyTemplate
+type StaticProxyTemplateResolver struct {
+	Template *mesh_proto.ProxyTemplate
 }
 
-func (r *staticProxyTemplateResolver) GetTemplate(proxy *model.Proxy) *mesh_proto.ProxyTemplate {
-	return r.template
+func (r *StaticProxyTemplateResolver) GetTemplate(proxy *model.Proxy) *mesh_proto.ProxyTemplate {
+	return r.Template
 }


Test patch:
diff --git a/app/kuma-cp/cmd/cmd_k8s_test.go b/app/kuma-cp/cmd/cmd_k8s_test.go
index 6f9cd208b..6325bbb2b 100644
--- a/app/kuma-cp/cmd/cmd_k8s_test.go
+++ b/app/kuma-cp/cmd/cmd_k8s_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"path/filepath"
+	"time"
 
 	kube_core "k8s.io/api/core/v1"
 	kube_meta "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -19,14 +20,17 @@ import (
 	"sigs.k8s.io/testing_frameworks/integration/addr"
 )
 
-var _ = Describe("K8S CMD test", func() {
+// Disabling this one as there are potential issues due to https://github.com/kumahq/kuma/issues/1001
+var _ = XDescribe("K8S CMD test", func() {
 	var k8sClient client.Client
 	var testEnv *envtest.Environment
 
 	BeforeEach(func(done Done) {
 		By("bootstrapping test environment")
 		testEnv = &envtest.Environment{
-			CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "pkg", "plugins", "resources", "k8s", "native", "config", "crd", "bases")},
+			CRDDirectoryPaths:        []string{filepath.Join("..", "..", "..", "pkg", "plugins", "resources", "k8s", "native", "config", "crd", "bases")},
+			ControlPlaneStartTimeout: 60 * time.Second,
+			ControlPlaneStopTimeout:  60 * time.Second,
 		}
 
 		cfg, err := testEnv.Start()
@@ -49,9 +53,8 @@ var _ = Describe("K8S CMD test", func() {
 
 	AfterEach(func() {
 		By("tearing down the test environment")
-		err := testEnv.Stop()
-		Expect(err).ToNot(HaveOccurred())
-	})
+		Expect(testEnv.Stop()).To(Succeed())
+	}, 60)
 
 	RunSmokeTest(ConfigFactoryFunc(func() string {
 		admissionServerPort, _, err := addr.Suggest()
diff --git a/app/kuma-cp/cmd/run_test.go b/app/kuma-cp/cmd/run_test.go
index 238ca6d9b..506d6e5b4 100644
--- a/app/kuma-cp/cmd/run_test.go
+++ b/app/kuma-cp/cmd/run_test.go
@@ -107,6 +107,6 @@ func RunSmokeTest(factory ConfigFactory) {
 
 			// complete
 			close(done)
-		}, 15)
+		}, 60)
 	})
 }
diff --git a/pkg/core/xds/metadata_test.go b/pkg/core/xds/metadata_test.go
index 801252307..d3268ea2f 100644
--- a/pkg/core/xds/metadata_test.go
+++ b/pkg/core/xds/metadata_test.go
@@ -1,7 +1,7 @@
 package xds_test
 
 import (
-	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
+	_struct "github.com/golang/protobuf/ptypes/struct"
 	. "github.com/onsi/ginkgo/extensions/table"
 	. "github.com/onsi/gomega"
 	pstruct "google.golang.org/protobuf/types/known/structpb"
@@ -10,35 +10,33 @@ import (
 )
 
 type testCase struct {
-	node     *envoy_core.Node
+	node     *_struct.Struct
 	expected xds.DataplaneMetadata
 }
 
-var _ = DescribeTable("DataplaneMetadataFromNode",
+var _ = DescribeTable("DataplaneMetadataFromXdsMetadata",
 	func(given testCase) {
 		// when
-		metadata := xds.DataplaneMetadataFromNode(given.node)
+		metadata := xds.DataplaneMetadataFromXdsMetadata(given.node)
 
 		// then
 		Expect(*metadata).To(Equal(given.expected))
 	},
 	Entry("should parse metadata from empty node", testCase{
-		node:     &envoy_core.Node{},
+		node:     &_struct.Struct{},
 		expected: xds.DataplaneMetadata{},
 	}),
 	Entry("should parse metadata", testCase{
-		node: &envoy_core.Node{
-			Metadata: &pstruct.Struct{
-				Fields: map[string]*pstruct.Value{
-					"dataplaneTokenPath": &pstruct.Value{
-						Kind: &pstruct.Value_StringValue{
-							StringValue: "/tmp/token",
-						},
+		node: &pstruct.Struct{
+			Fields: map[string]*pstruct.Value{
+				"dataplaneTokenPath": &pstruct.Value{
+					Kind: &pstruct.Value_StringValue{
+						StringValue: "/tmp/token",
 					},
-					"dataplane.admin.port": &pstruct.Value{
-						Kind: &pstruct.Value_StringValue{
-							StringValue: "1234",
-						},
+				},
+				"dataplane.admin.port": &pstruct.Value{
+					Kind: &pstruct.Value_StringValue{
+						StringValue: "1234",
 					},
 				},
 			},
diff --git a/pkg/core/xds/types_test.go b/pkg/core/xds/types_test.go
index 40717cb7b..421c09ab9 100644
--- a/pkg/core/xds/types_test.go
+++ b/pkg/core/xds/types_test.go
@@ -71,7 +71,7 @@ var _ = Describe("xDS", func() {
 				}),
 				Entry("empty", testCase{
 					node:        &envoy_core.Node{},
-					expectedErr: "mesh must not be empty",
+					expectedErr: "Envoy ID must not be nil",
 				}),
 				Entry("mesh without name and namespace", testCase{
 					node: &envoy_core.Node{
diff --git a/pkg/util/xds/callbacks_chain_test.go b/pkg/util/xds/v2/callbacks_chain_test.go
similarity index 95%
rename from pkg/util/xds/callbacks_chain_test.go
rename to pkg/util/xds/v2/callbacks_chain_test.go
index df01f404c..1aa18e113 100644
--- a/pkg/util/xds/callbacks_chain_test.go
+++ b/pkg/util/xds/v2/callbacks_chain_test.go
@@ -1,4 +1,4 @@
-package xds_test
+package v2_test
 
 import (
 	"context"
@@ -7,7 +7,7 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
-	. "github.com/kumahq/kuma/pkg/util/xds"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 
 	envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
 	envoy_xds "github.com/envoyproxy/go-control-plane/pkg/server/v2"
@@ -67,7 +67,7 @@ var _ = Describe("CallbacksChain", func() {
 			streamID := int64(1)
 			typ := "xDS"
 			// setup
-			chain := CallbacksChain{first, second}
+			chain := util_xds_v2.CallbacksChain{first, second}
 
 			// when
 			err := chain.OnStreamOpen(ctx, streamID, typ)
@@ -85,7 +85,7 @@ var _ = Describe("CallbacksChain", func() {
 			// given
 			streamID := int64(1)
 			// setup
-			chain := CallbacksChain{first, second}
+			chain := util_xds_v2.CallbacksChain{first, second}
 
 			// when
 			chain.OnStreamClosed(streamID)
@@ -104,7 +104,7 @@ var _ = Describe("CallbacksChain", func() {
 			req := &envoy.DiscoveryRequest{}
 
 			// setup
-			chain := CallbacksChain{first, second}
+			chain := util_xds_v2.CallbacksChain{first, second}
 
 			// when
 			err := chain.OnStreamRequest(streamID, req)
@@ -120,7 +120,7 @@ var _ = Describe("CallbacksChain", func() {
 	Describe("OnStreamResponse", func() {
 		It("should be called in reverse order", func() {
 			// given
-			chain := CallbacksChain{first, second}
+			chain := util_xds_v2.CallbacksChain{first, second}
 			streamID := int64(1)
 			req := &envoy.DiscoveryRequest{}
 			resp := &envoy.DiscoveryResponse{}
diff --git a/pkg/util/xds/v2/xds_suite_test.go b/pkg/util/xds/v2/xds_suite_test.go
new file mode 100644
index 000000000..fcb3c2232
--- /dev/null
+++ b/pkg/util/xds/v2/xds_suite_test.go
@@ -0,0 +1,13 @@
+package v2_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestXds(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Xds V2 Suite")
+}
diff --git a/pkg/xds/auth/callbacks_test.go b/pkg/xds/auth/callbacks_test.go
index a90172438..2ff4b6cfc 100644
--- a/pkg/xds/auth/callbacks_test.go
+++ b/pkg/xds/auth/callbacks_test.go
@@ -18,6 +18,7 @@ import (
 	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
 	"github.com/kumahq/kuma/pkg/plugins/resources/memory"
 	test_model "github.com/kumahq/kuma/pkg/test/resources/model"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 	"github.com/kumahq/kuma/pkg/xds/auth"
 
 	. "github.com/onsi/ginkgo"
@@ -70,7 +71,7 @@ var _ = Describe("Auth Callbacks", func() {
 		memStore := memory.NewStore()
 		resManager = core_manager.NewResourceManager(memStore)
 		testAuth = &testAuthenticator{}
-		callbacks = auth.NewCallbacks(resManager, testAuth)
+		callbacks = util_xds_v2.AdaptCallbacks(auth.NewCallbacks(resManager, testAuth))
 
 		err := resManager.Create(context.Background(), core_mesh.NewMeshResource(), core_store.CreateByKey(model.DefaultMesh, model.NoMesh))
 		Expect(err).ToNot(HaveOccurred())
diff --git a/pkg/xds/generator/inbound_proxy_generator_test.go b/pkg/xds/generator/inbound_proxy_generator_test.go
index a3bf2e040..b1db38ea8 100644
--- a/pkg/xds/generator/inbound_proxy_generator_test.go
+++ b/pkg/xds/generator/inbound_proxy_generator_test.go
@@ -71,23 +71,50 @@ var _ = Describe("InboundProxyGenerator", func() {
 					},
 					Spec: &dataplane,
 				},
-				TrafficPermissions: model.TrafficPermissionMap{
-					mesh_proto.InboundInterface{
-						DataplaneIP:   "192.168.0.1",
-						DataplanePort: 80,
-						WorkloadIP:    "127.0.0.1",
-						WorkloadPort:  8080,
-					}: &mesh_core.TrafficPermissionResource{
-						Meta: &test_model.ResourceMeta{
-							Name: "tp-1",
-							Mesh: "default",
+				Policies: model.MatchedPolicies{
+
+					TrafficPermissions: model.TrafficPermissionMap{
+						mesh_proto.InboundInterface{
+							DataplaneIP:   "192.168.0.1",
+							DataplanePort: 80,
+							WorkloadIP:    "127.0.0.1",
+							WorkloadPort:  8080,
+						}: &mesh_core.TrafficPermissionResource{
+							Meta: &test_model.ResourceMeta{
+								Name: "tp-1",
+								Mesh: "default",
+							},
+							Spec: &mesh_proto.TrafficPermission{
+								Sources: []*mesh_proto.Selector{
+									{
+										Match: map[string]string{
+											"kuma.io/service": "web1",
+											"version":         "1.0",
+										},
+									},
+								},
+								Destinations: []*mesh_proto.Selector{
+									{
+										Match: map[string]string{
+											"kuma.io/service": "backend1",
+											"env":             "dev",
+										},
+									},
+								},
+							},
 						},
-						Spec: &mesh_proto.TrafficPermission{
+					},
+					FaultInjections: model.FaultInjectionMap{
+						mesh_proto.InboundInterface{
+							DataplaneIP:   "192.168.0.1",
+							DataplanePort: 80,
+							WorkloadIP:    "127.0.0.1",
+							WorkloadPort:  8080,
+						}: &mesh_proto.FaultInjection{
 							Sources: []*mesh_proto.Selector{
 								{
 									Match: map[string]string{
-										"kuma.io/service": "web1",
-										"version":         "1.0",
+										"kuma.io/service": "frontend",
 									},
 								},
 							},
@@ -95,40 +122,16 @@ var _ = Describe("InboundProxyGenerator", func() {
 								{
 									Match: map[string]string{
 										"kuma.io/service": "backend1",
-										"env":             "dev",
 									},
 								},
 							},
-						},
-					},
-				},
-				FaultInjections: model.FaultInjectionMap{
-					mesh_proto.InboundInterface{
-						DataplaneIP:   "192.168.0.1",
-						DataplanePort: 80,
-						WorkloadIP:    "127.0.0.1",
-						WorkloadPort:  8080,
-					}: &mesh_proto.FaultInjection{
-						Sources: []*mesh_proto.Selector{
-							{
-								Match: map[string]string{
-									"kuma.io/service": "frontend",
+							Conf: &mesh_proto.FaultInjection_Conf{
+								Delay: &mesh_proto.FaultInjection_Conf_Delay{
+									Percentage: &wrappers.DoubleValue{Value: 50},
+									Value:      &duration.Duration{Seconds: 5},
 								},
 							},
 						},
-						Destinations: []*mesh_proto.Selector{
-							{
-								Match: map[string]string{
-									"kuma.io/service": "backend1",
-								},
-							},
-						},
-						Conf: &mesh_proto.FaultInjection_Conf{
-							Delay: &mesh_proto.FaultInjection_Conf_Delay{
-								Percentage: &wrappers.DoubleValue{Value: 50},
-								Value:      &duration.Duration{Seconds: 5},
-							},
-						},
 					},
 				},
 				Metadata: &model.DataplaneMetadata{},
diff --git a/pkg/xds/generator/ingress_generator_test.go b/pkg/xds/generator/ingress_generator_test.go
index c89662a4b..037cdbf81 100644
--- a/pkg/xds/generator/ingress_generator_test.go
+++ b/pkg/xds/generator/ingress_generator_test.go
@@ -40,8 +40,10 @@ var _ = Describe("IngressGenerator", func() {
 					},
 					Spec: dataplane,
 				},
-				OutboundTargets:  given.outboundTargets,
-				TrafficRouteList: given.trafficRoutes,
+				Routing: core_xds.Routing{
+					OutboundTargets:  given.outboundTargets,
+					TrafficRouteList: given.trafficRoutes,
+				},
 			}
 
 			// when
diff --git a/pkg/xds/generator/outbound_proxy_generator_test.go b/pkg/xds/generator/outbound_proxy_generator_test.go
index 3a1a99fb1..2b01ef445 100644
--- a/pkg/xds/generator/outbound_proxy_generator_test.go
+++ b/pkg/xds/generator/outbound_proxy_generator_test.go
@@ -167,183 +167,160 @@ var _ = Describe("OutboundProxyGenerator", func() {
 					},
 					Spec: dataplane,
 				},
-				TrafficRoutes: model.RouteMap{
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 40001,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      100,
-									Destination: mesh_proto.MatchService("api-http"),
-								}},
+				Routing: model.Routing{
+					TrafficRoutes: model.RouteMap{
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 40001,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      100,
+										Destination: mesh_proto.MatchService("api-http"),
+									}},
+								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 40002,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      100,
-									Destination: mesh_proto.MatchService("api-tcp"),
-								}},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 40002,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      100,
+										Destination: mesh_proto.MatchService("api-tcp"),
+									}},
+								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 40003,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      100,
-									Destination: mesh_proto.MatchService("api-http2"),
-								}},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 40003,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      100,
+										Destination: mesh_proto.MatchService("api-http2"),
+									}},
+								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 40004,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      100,
-									Destination: mesh_proto.MatchService("api-grpc"),
-								}},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 40004,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      100,
+										Destination: mesh_proto.MatchService("api-grpc"),
+									}},
+								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 18080,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      100,
-									Destination: mesh_proto.MatchService("backend"),
-								}},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 18080,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      100,
+										Destination: mesh_proto.MatchService("backend"),
+									}},
+								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 54321,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      10,
-									Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "role": "master"},
-								}, {
-									Weight:      90,
-									Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "role": "replica"},
-								}, {
-									Weight:      0, // should be excluded from Envoy configuration
-									Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "role": "canary"},
-								}},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 54321,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      10,
+										Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "role": "master"},
+									}, {
+										Weight:      90,
+										Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "role": "replica"},
+									}, {
+										Weight:      0, // should be excluded from Envoy configuration
+										Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "role": "canary"},
+									}},
+								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 18081,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      1,
-									Destination: mesh_proto.TagSelector{"kuma.io/service": "es", "kuma.io/protocol": "http"},
-								}},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 18081,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      1,
+										Destination: mesh_proto.TagSelector{"kuma.io/service": "es", "kuma.io/protocol": "http"},
+									}},
+								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 18082,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{{
-									Weight:      1,
-									Destination: mesh_proto.TagSelector{"kuma.io/service": "es2", "kuma.io/protocol": "http2"},
-								}},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 18082,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{{
+										Weight:      1,
+										Destination: mesh_proto.TagSelector{"kuma.io/service": "es2", "kuma.io/protocol": "http2"},
+									}},
+								},
 							},
 						},
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 4040,
+						}: nil,
 					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 4040,
-					}: nil,
+					OutboundTargets: outboundTargets,
 				},
-				OutboundSelectors: model.DestinationMap{
-					"api-http": model.TagSelectorSet{
-						{"kuma.io/service": "api-http"},
-					},
-					"api-tcp": model.TagSelectorSet{
-						{"kuma.io/service": "api-tcp"},
-					},
-					"api-http2": model.TagSelectorSet{
-						{"kuma.io/service": "api-http2"},
-					},
-					"api-grpc": model.TagSelectorSet{
-						{"kuma.io/service": "api-grpc"},
-					},
-					"backend": model.TagSelectorSet{
-						{"kuma.io/service": "backend"},
-					},
-					"db": model.TagSelectorSet{
-						{"kuma.io/service": "db", "role": "master"},
-						{"kuma.io/service": "db", "role": "replica"},
-						{"kuma.io/service": "db", "role": "canary"},
-					},
-					"es": model.TagSelectorSet{
-						{"kuma.io/service": "es", "kuma.io/protocol": "http"},
-					},
-					"es2": model.TagSelectorSet{
-						{"kuma.io/service": "es2", "kuma.io/protocol": "http2"},
-					},
-				},
-				OutboundTargets: outboundTargets,
-				Logs: model.LogMap{
-					"api-http": &mesh_proto.LoggingBackend{
-						Name: "file",
-						Type: mesh_proto.LoggingFileType,
-						Conf: util_proto.MustToStruct(&mesh_proto.FileLoggingBackendConfig{
-							Path: "/var/log",
-						}),
-					},
-					"api-tcp": &mesh_proto.LoggingBackend{
-						Name: "elk",
-						Type: mesh_proto.LoggingTcpType,
-						Conf: util_proto.MustToStruct(&mesh_proto.TcpLoggingBackendConfig{
-							Address: "logstash:1234",
-						}),
+				Policies: model.MatchedPolicies{
+					Logs: model.LogMap{
+						"api-http": &mesh_proto.LoggingBackend{
+							Name: "file",
+							Type: mesh_proto.LoggingFileType,
+							Conf: util_proto.MustToStruct(&mesh_proto.FileLoggingBackendConfig{
+								Path: "/var/log",
+							}),
+						},
+						"api-tcp": &mesh_proto.LoggingBackend{
+							Name: "elk",
+							Type: mesh_proto.LoggingTcpType,
+							Conf: util_proto.MustToStruct(&mesh_proto.TcpLoggingBackendConfig{
+								Address: "logstash:1234",
+							}),
+						},
 					},
-				},
-				Metadata: &model.DataplaneMetadata{},
-				CircuitBreakers: model.CircuitBreakerMap{
-					"api-http": &mesh_core.CircuitBreakerResource{
-						Spec: &mesh_proto.CircuitBreaker{
-							Conf: &mesh_proto.CircuitBreaker_Conf{
-								Detectors: &mesh_proto.CircuitBreaker_Conf_Detectors{
-									TotalErrors: &mesh_proto.CircuitBreaker_Conf_Detectors_Errors{},
+					CircuitBreakers: model.CircuitBreakerMap{
+						"api-http": &mesh_core.CircuitBreakerResource{
+							Spec: &mesh_proto.CircuitBreaker{
+								Conf: &mesh_proto.CircuitBreaker_Conf{
+									Detectors: &mesh_proto.CircuitBreaker_Conf_Detectors{
+										TotalErrors: &mesh_proto.CircuitBreaker_Conf_Detectors_Errors{},
+									},
 								},
 							},
 						},
 					},
 				},
-				CLACache: &dummyCLACache{outboundTargets: outboundTargets},
+
+				Metadata: &model.DataplaneMetadata{},
 			}
 
 			// when
+			given.ctx.ControlPlane.CLACache = &dummyCLACache{outboundTargets: outboundTargets}
 			rs, err := gen.Generate(given.ctx, proxy)
 
 			// then
@@ -519,47 +496,41 @@ var _ = Describe("OutboundProxyGenerator", func() {
 				},
 				Spec: dataplane,
 			},
-			TrafficRoutes: model.RouteMap{
-				mesh_proto.OutboundInterface{
-					DataplaneIP:   "127.0.0.1",
-					DataplanePort: 18080,
-				}: &mesh_core.TrafficRouteResource{
-					Spec: &mesh_proto.TrafficRoute{
-						Conf: &mesh_proto.TrafficRoute_Conf{
-							Split: []*mesh_proto.TrafficRoute_Split{{
-								Weight:      100,
-								Destination: mesh_proto.MatchService("backend.kuma-system"),
-							}},
+			Routing: model.Routing{
+				TrafficRoutes: model.RouteMap{
+					mesh_proto.OutboundInterface{
+						DataplaneIP:   "127.0.0.1",
+						DataplanePort: 18080,
+					}: &mesh_core.TrafficRouteResource{
+						Spec: &mesh_proto.TrafficRoute{
+							Conf: &mesh_proto.TrafficRoute_Conf{
+								Split: []*mesh_proto.TrafficRoute_Split{{
+									Weight:      100,
+									Destination: mesh_proto.MatchService("backend.kuma-system"),
+								}},
+							},
 						},
 					},
-				},
-				mesh_proto.OutboundInterface{
-					DataplaneIP:   "127.0.0.1",
-					DataplanePort: 54321,
-				}: &mesh_core.TrafficRouteResource{
-					Spec: &mesh_proto.TrafficRoute{
-						Conf: &mesh_proto.TrafficRoute_Conf{
-							Split: []*mesh_proto.TrafficRoute_Split{{
-								Weight:      100,
-								Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "version": "3.2.0"},
+					mesh_proto.OutboundInterface{
+						DataplaneIP:   "127.0.0.1",
+						DataplanePort: 54321,
+					}: &mesh_core.TrafficRouteResource{
+						Spec: &mesh_proto.TrafficRoute{
+							Conf: &mesh_proto.TrafficRoute_Conf{
+								Split: []*mesh_proto.TrafficRoute_Split{{
+									Weight:      100,
+									Destination: mesh_proto.TagSelector{"kuma.io/service": "db", "version": "3.2.0"},
+								}},
 							}},
-						}},
-				},
-			},
-			OutboundSelectors: model.DestinationMap{
-				"backend.kuma-system": model.TagSelectorSet{
-					{"kuma.io/service": "backend.kuma-system"},
-				},
-				"db.kuma-system": model.TagSelectorSet{
-					{"kuma.io/service": "db", "version": "3.2.0"},
+					},
 				},
+				OutboundTargets: outboundTargets,
 			},
-			OutboundTargets: outboundTargets,
-			Metadata:        &model.DataplaneMetadata{},
-			CLACache:        &dummyCLACache{outboundTargets: outboundTargets},
+			Metadata: &model.DataplaneMetadata{},
 		}
 
 		// when
+		plainCtx.ControlPlane.CLACache = &dummyCLACache{outboundTargets: outboundTargets}
 		rs, err := gen.Generate(plainCtx, proxy)
 
 		// then
diff --git a/pkg/xds/generator/proxy_template_profile_source_test.go b/pkg/xds/generator/proxy_template_profile_source_test.go
index d3c64b9b0..4c2121a0d 100644
--- a/pkg/xds/generator/proxy_template_profile_source_test.go
+++ b/pkg/xds/generator/proxy_template_profile_source_test.go
@@ -49,12 +49,31 @@ var _ = Describe("ProxyTemplateProfileSource", func() {
 			}
 
 			// given
+			outboundTargets := model.EndpointMap{
+				"db": []model.Endpoint{
+					{
+						Target: "192.168.0.3",
+						Port:   5432,
+						Tags:   map[string]string{"kuma.io/service": "db", "role": "master"},
+						Weight: 1,
+					},
+				},
+				"elastic": []model.Endpoint{
+					{
+						Target: "192.168.0.4",
+						Port:   9200,
+						Tags:   map[string]string{"kuma.io/service": "elastic"},
+						Weight: 1,
+					},
+				},
+			}
 			ctx := xds_context.Context{
 				ConnectionInfo: xds_context.ConnectionInfo{
 					Authority: "kuma-system:5677",
 				},
 				ControlPlane: &xds_context.ControlPlaneContext{
 					SdsTlsCert: []byte("12345"),
+					CLACache:   &dummyCLACache{outboundTargets: outboundTargets},
 				},
 				Mesh: xds_context.MeshContext{
 					Resource: &mesh_core.MeshResource{
@@ -71,25 +90,6 @@ var _ = Describe("ProxyTemplateProfileSource", func() {
 			dataplane := &mesh_proto.Dataplane{}
 			Expect(util_proto.FromYAML([]byte(given.dataplane), dataplane)).To(Succeed())
 
-			outboundTargets := model.EndpointMap{
-				"db": []model.Endpoint{
-					{
-						Target: "192.168.0.3",
-						Port:   5432,
-						Tags:   map[string]string{"kuma.io/service": "db", "role": "master"},
-						Weight: 1,
-					},
-				},
-				"elastic": []model.Endpoint{
-					{
-						Target: "192.168.0.4",
-						Port:   9200,
-						Tags:   map[string]string{"kuma.io/service": "elastic"},
-						Weight: 1,
-					},
-				},
-			}
-
 			proxy := &model.Proxy{
 				Id: model.ProxyId{Name: "demo.backend-01"},
 				Dataplane: &mesh_core.DataplaneResource{
@@ -100,53 +100,57 @@ var _ = Describe("ProxyTemplateProfileSource", func() {
 					},
 					Spec: dataplane,
 				},
-				TrafficRoutes: model.RouteMap{
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 54321,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{
-									{
-										Weight:      100,
-										Destination: mesh_proto.MatchService("db"),
+				Routing: model.Routing{
+					TrafficRoutes: model.RouteMap{
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 54321,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{
+										{
+											Weight:      100,
+											Destination: mesh_proto.MatchService("db"),
+										},
 									},
 								},
 							},
 						},
-					},
-					mesh_proto.OutboundInterface{
-						DataplaneIP:   "127.0.0.1",
-						DataplanePort: 59200,
-					}: &mesh_core.TrafficRouteResource{
-						Spec: &mesh_proto.TrafficRoute{
-							Conf: &mesh_proto.TrafficRoute_Conf{
-								Split: []*mesh_proto.TrafficRoute_Split{
-									{
-										Weight:      100,
-										Destination: mesh_proto.MatchService("elastic"),
+						mesh_proto.OutboundInterface{
+							DataplaneIP:   "127.0.0.1",
+							DataplanePort: 59200,
+						}: &mesh_core.TrafficRouteResource{
+							Spec: &mesh_proto.TrafficRoute{
+								Conf: &mesh_proto.TrafficRoute_Conf{
+									Split: []*mesh_proto.TrafficRoute_Split{
+										{
+											Weight:      100,
+											Destination: mesh_proto.MatchService("elastic"),
+										},
 									},
 								},
 							},
 						},
 					},
+					OutboundTargets: outboundTargets,
 				},
-				OutboundTargets: outboundTargets,
-				HealthChecks: model.HealthCheckMap{
-					"elastic": &mesh_core.HealthCheckResource{
-						Spec: &mesh_proto.HealthCheck{
-							Sources: []*mesh_proto.Selector{
-								{Match: mesh_proto.TagSelector{"kuma.io/service": "*"}},
-							},
-							Destinations: []*mesh_proto.Selector{
-								{Match: mesh_proto.TagSelector{"kuma.io/service": "elastic"}},
-							},
-							Conf: &mesh_proto.HealthCheck_Conf{
-								Interval:           ptypes.DurationProto(5 * time.Second),
-								Timeout:            ptypes.DurationProto(4 * time.Second),
-								UnhealthyThreshold: 3,
-								HealthyThreshold:   2,
+				Policies: model.MatchedPolicies{
+					HealthChecks: model.HealthCheckMap{
+						"elastic": &mesh_core.HealthCheckResource{
+							Spec: &mesh_proto.HealthCheck{
+								Sources: []*mesh_proto.Selector{
+									{Match: mesh_proto.TagSelector{"kuma.io/service": "*"}},
+								},
+								Destinations: []*mesh_proto.Selector{
+									{Match: mesh_proto.TagSelector{"kuma.io/service": "elastic"}},
+								},
+								Conf: &mesh_proto.HealthCheck_Conf{
+									Interval:           ptypes.DurationProto(5 * time.Second),
+									Timeout:            ptypes.DurationProto(4 * time.Second),
+									UnhealthyThreshold: 3,
+									HealthyThreshold:   2,
+								},
 							},
 						},
 					},
@@ -154,7 +158,6 @@ var _ = Describe("ProxyTemplateProfileSource", func() {
 				Metadata: &model.DataplaneMetadata{
 					AdminPort: 9902,
 				},
-				CLACache: &dummyCLACache{outboundTargets: outboundTargets},
 			}
 
 			// when
diff --git a/pkg/xds/generator/tracing_generator_test.go b/pkg/xds/generator/tracing_generator_test.go
index e26a1aa46..fda52b24b 100644
--- a/pkg/xds/generator/tracing_generator_test.go
+++ b/pkg/xds/generator/tracing_generator_test.go
@@ -50,7 +50,6 @@ var _ = Describe("TracingProxyGenerator", func() {
 						Mesh: "demo",
 					},
 				},
-				TracingBackend: nil,
 			},
 		}),
 	)
@@ -90,12 +89,14 @@ var _ = Describe("TracingProxyGenerator", func() {
 						},
 					},
 				},
-				TracingBackend: &mesh_proto.TracingBackend{
-					Name: "zipkin",
-					Type: mesh_proto.TracingZipkinType,
-					Conf: util_proto.MustToStruct(&mesh_proto.ZipkinTracingBackendConfig{
-						Url: "http://zipkin.us:9090/v2/spans",
-					}),
+				Policies: model.MatchedPolicies{
+					TracingBackend: &mesh_proto.TracingBackend{
+						Name: "zipkin",
+						Type: mesh_proto.TracingZipkinType,
+						Conf: util_proto.MustToStruct(&mesh_proto.ZipkinTracingBackendConfig{
+							Url: "http://zipkin.us:9090/v2/spans",
+						}),
+					},
 				},
 			},
 			expectedFile: "zipkin.envoy-config.golden.yaml",
diff --git a/pkg/xds/generator/transparent_proxy_generator_test.go b/pkg/xds/generator/transparent_proxy_generator_test.go
index 3972f1961..a27518981 100644
--- a/pkg/xds/generator/transparent_proxy_generator_test.go
+++ b/pkg/xds/generator/transparent_proxy_generator_test.go
@@ -83,13 +83,15 @@ var _ = Describe("TransparentProxyGenerator", func() {
 						},
 					},
 				},
-				Logs: map[model.ServiceName]*mesh_proto.LoggingBackend{ // to show that is not picked
-					"some-service": {
-						Name: "file",
-						Type: mesh_proto.LoggingFileType,
-						Conf: util_proto.MustToStruct(&mesh_proto.FileLoggingBackendConfig{
-							Path: "/var/log",
-						}),
+				Policies: model.MatchedPolicies{
+					Logs: map[model.ServiceName]*mesh_proto.LoggingBackend{ // to show that is not picked
+						"some-service": {
+							Name: "file",
+							Type: mesh_proto.LoggingFileType,
+							Conf: util_proto.MustToStruct(&mesh_proto.FileLoggingBackendConfig{
+								Path: "/var/log",
+							}),
+						},
 					},
 				},
 			},
@@ -167,13 +169,15 @@ var _ = Describe("TransparentProxyGenerator", func() {
 						},
 					},
 				},
-				Logs: map[model.ServiceName]*mesh_proto.LoggingBackend{ // to show that is is not picked
-					"pass_through": {
-						Name: "file",
-						Type: mesh_proto.LoggingFileType,
-						Conf: util_proto.MustToStruct(&mesh_proto.FileLoggingBackendConfig{
-							Path: "/var/log",
-						}),
+				Policies: model.MatchedPolicies{
+					Logs: map[model.ServiceName]*mesh_proto.LoggingBackend{ // to show that is is not picked
+						"pass_through": {
+							Name: "file",
+							Type: mesh_proto.LoggingFileType,
+							Conf: util_proto.MustToStruct(&mesh_proto.FileLoggingBackendConfig{
+								Path: "/var/log",
+							}),
+						},
 					},
 				},
 			},
diff --git a/pkg/xds/server/callbacks/callbacks_suite_test.go b/pkg/xds/server/callbacks/callbacks_suite_test.go
new file mode 100644
index 000000000..3a4e2695c
--- /dev/null
+++ b/pkg/xds/server/callbacks/callbacks_suite_test.go
@@ -0,0 +1,13 @@
+package callbacks_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestCallbacks(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "XDS Callbacks Suite")
+}
diff --git a/pkg/xds/server/dataplane_lifecycle_test.go b/pkg/xds/server/callbacks/dataplane_lifecycle_test.go
similarity index 89%
rename from pkg/xds/server/dataplane_lifecycle_test.go
rename to pkg/xds/server/callbacks/dataplane_lifecycle_test.go
index 2b22a3954..9207a09d8 100644
--- a/pkg/xds/server/dataplane_lifecycle_test.go
+++ b/pkg/xds/server/callbacks/dataplane_lifecycle_test.go
@@ -1,10 +1,11 @@
-package server_test
+package callbacks_test
 
 import (
 	"context"
 
 	v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
 	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
+	envoy_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
 	pstruct "github.com/golang/protobuf/ptypes/struct"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
@@ -16,18 +17,21 @@ import (
 	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
 	"github.com/kumahq/kuma/pkg/plugins/resources/memory"
 	"github.com/kumahq/kuma/pkg/test/resources/model"
-	"github.com/kumahq/kuma/pkg/xds/server"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
+	. "github.com/kumahq/kuma/pkg/xds/server/callbacks"
 )
 
 var _ = Describe("Dataplane Lifecycle", func() {
 
 	var resManager core_manager.ResourceManager
-	var dpLifecycle *server.DataplaneLifecycle
+	var dpLifecycle *DataplaneLifecycle
+	var callbacks envoy_server.Callbacks
 
 	BeforeEach(func() {
 		store := memory.NewStore()
 		resManager = core_manager.NewResourceManager(store)
-		dpLifecycle = server.NewDataplaneLifecycle(resManager)
+		dpLifecycle = NewDataplaneLifecycle(resManager)
+		callbacks = util_xds_v2.AdaptCallbacks(dpLifecycle)
 
 		err := resManager.Create(context.Background(), core_mesh.NewMeshResource(), core_store.CreateByKey(core_model.DefaultMesh, core_model.NoMesh))
 		Expect(err).ToNot(HaveOccurred())
@@ -70,7 +74,7 @@ var _ = Describe("Dataplane Lifecycle", func() {
 		const streamId = 123
 
 		// when
-		err := dpLifecycle.OnStreamRequest(streamId, &req)
+		err := callbacks.OnStreamRequest(streamId, &req)
 
 		// then dp is created
 		Expect(err).ToNot(HaveOccurred())
@@ -118,7 +122,7 @@ var _ = Describe("Dataplane Lifecycle", func() {
 		const streamId = 123
 
 		// when
-		err = dpLifecycle.OnStreamRequest(streamId, &req)
+		err = callbacks.OnStreamRequest(streamId, &req)
 
 		// then
 		Expect(err).ToNot(HaveOccurred())
diff --git a/pkg/xds/server/dataplane_metadata_tracker_test.go b/pkg/xds/server/callbacks/dataplane_metadata_tracker_test.go
similarity index 78%
rename from pkg/xds/server/dataplane_metadata_tracker_test.go
rename to pkg/xds/server/callbacks/dataplane_metadata_tracker_test.go
index 9c3cb862b..0eb072441 100644
--- a/pkg/xds/server/dataplane_metadata_tracker_test.go
+++ b/pkg/xds/server/callbacks/dataplane_metadata_tracker_test.go
@@ -1,4 +1,4 @@
-package server_test
+package callbacks_test
 
 import (
 	v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
@@ -8,12 +8,14 @@ import (
 	. "github.com/onsi/gomega"
 
 	"github.com/kumahq/kuma/pkg/core/xds"
-	"github.com/kumahq/kuma/pkg/xds/server"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
+	. "github.com/kumahq/kuma/pkg/xds/server/callbacks"
 )
 
 var _ = Describe("Dataplane Metadata Tracker", func() {
 
-	tracker := server.NewDataplaneMetadataTracker()
+	tracker := NewDataplaneMetadataTracker()
+	callbacks := util_xds_v2.AdaptCallbacks(tracker)
 
 	req := v2.DiscoveryRequest{
 		Node: &envoy_core.Node{
@@ -33,7 +35,7 @@ var _ = Describe("Dataplane Metadata Tracker", func() {
 
 	It("should track metadata", func() {
 		// when
-		err := tracker.OnStreamRequest(streamId, &req)
+		err := callbacks.OnStreamRequest(streamId, &req)
 
 		// then
 		Expect(err).ToNot(HaveOccurred())
@@ -54,13 +56,13 @@ var _ = Describe("Dataplane Metadata Tracker", func() {
 
 	It("should track metadata with empty Node in consecutive DiscoveryRequests", func() {
 		// when
-		err := tracker.OnStreamRequest(streamId, &req)
+		err := callbacks.OnStreamRequest(streamId, &req)
 
 		// then
 		Expect(err).ToNot(HaveOccurred())
 
 		// when
-		err = tracker.OnStreamRequest(streamId, &v2.DiscoveryRequest{})
+		err = callbacks.OnStreamRequest(streamId, &v2.DiscoveryRequest{})
 
 		// then
 		Expect(err).ToNot(HaveOccurred())
diff --git a/pkg/xds/server/dataplane_status_sink_test.go b/pkg/xds/server/callbacks/dataplane_status_sink_test.go
similarity index 94%
rename from pkg/xds/server/dataplane_status_sink_test.go
rename to pkg/xds/server/callbacks/dataplane_status_sink_test.go
index 6bc83f16c..d3de31436 100644
--- a/pkg/xds/server/dataplane_status_sink_test.go
+++ b/pkg/xds/server/callbacks/dataplane_status_sink_test.go
@@ -1,10 +1,11 @@
-package server
+package callbacks_test
 
 import (
 	"context"
 	"time"
 
 	"github.com/kumahq/kuma/pkg/core/resources/manager"
+	"github.com/kumahq/kuma/pkg/xds/server/callbacks"
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
@@ -57,7 +58,7 @@ var _ = Describe("DataplaneInsightSink", func() {
 			var latestUpsert *DataplaneInsightUpsert
 
 			// given
-			sink := NewDataplaneInsightSink(accessor, func() *time.Ticker { return ticker }, 1*time.Millisecond, recorder)
+			sink := callbacks.NewDataplaneInsightSink(accessor, func() *time.Ticker { return ticker }, 1*time.Millisecond, recorder)
 			go sink.Start(stop)
 
 			// when
@@ -152,7 +153,7 @@ var _ = Describe("DataplaneInsightSink", func() {
 			lastSeenVersion := ""
 
 			// given
-			statusStore := NewDataplaneInsightStore(manager.NewResourceManager(store))
+			statusStore := callbacks.NewDataplaneInsightStore(manager.NewResourceManager(store))
 
 			// when
 			err := statusStore.Upsert(key, proto.Clone(subscription).(*mesh_proto.DiscoverySubscription))
@@ -224,7 +225,7 @@ var _ = Describe("DataplaneInsightSink", func() {
 	})
 })
 
-var _ SubscriptionStatusAccessor = &SubscriptionStatusHolder{}
+var _ callbacks.SubscriptionStatusAccessor = &SubscriptionStatusHolder{}
 
 type SubscriptionStatusHolder struct {
 	core_model.ResourceKey
@@ -235,7 +236,7 @@ func (h *SubscriptionStatusHolder) GetStatus() (core_model.ResourceKey, *mesh_pr
 	return h.ResourceKey, proto.Clone(h.DiscoverySubscription).(*mesh_proto.DiscoverySubscription)
 }
 
-var _ DataplaneInsightStore = &DataplaneInsightStoreRecorder{}
+var _ callbacks.DataplaneInsightStore = &DataplaneInsightStoreRecorder{}
 
 type DataplaneInsightUpsert struct {
 	core_model.ResourceKey
diff --git a/pkg/xds/server/dataplane_status_tracker_test.go b/pkg/xds/server/callbacks/dataplane_status_tracker_test.go
similarity index 91%
rename from pkg/xds/server/dataplane_status_tracker_test.go
rename to pkg/xds/server/callbacks/dataplane_status_tracker_test.go
index b9ad0e701..4a2202bf6 100644
--- a/pkg/xds/server/dataplane_status_tracker_test.go
+++ b/pkg/xds/server/callbacks/dataplane_status_tracker_test.go
@@ -1,12 +1,16 @@
-package server
+package callbacks_test
 
 import (
 	"context"
 	"time"
 
+	envoy_server "github.com/envoyproxy/go-control-plane/pkg/server/v2"
 	pstruct "github.com/golang/protobuf/ptypes/struct"
 
 	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
+	"github.com/kumahq/kuma/pkg/core"
+	. "github.com/kumahq/kuma/pkg/test/matchers"
+	v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/ginkgo/extensions/table"
@@ -21,6 +25,7 @@ import (
 	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
 
 	test_runtime "github.com/kumahq/kuma/pkg/test/runtime"
+	. "github.com/kumahq/kuma/pkg/xds/server/callbacks"
 )
 
 var _ = Describe("DataplaneStatusTracker", func() {
@@ -28,6 +33,8 @@ var _ = Describe("DataplaneStatusTracker", func() {
 	var t0 time.Time
 
 	var tracker DataplaneStatusTracker
+	var callbacks envoy_server.Callbacks
+
 	var runtimeInfo = test_runtime.TestRuntimeInfo{InstanceId: "test"}
 	var ctx context.Context
 
@@ -36,22 +43,22 @@ var _ = Describe("DataplaneStatusTracker", func() {
 	var backupNewUUID func() string
 
 	BeforeEach(func() {
-		backupNow = now
-		backupNewUUID = newUUID
+		backupNow = core.Now
+		backupNewUUID = core.NewUUID
 	})
 
 	AfterEach(func() {
-		now = backupNow
-		newUUID = backupNewUUID
+		core.Now = backupNow
+		core.NewUUID = backupNewUUID
 	})
 
 	BeforeEach(func() {
 		t0, _ = time.Parse(time.RFC3339, "2019-07-01T00:00:00+00:00")
-		now = func() time.Time {
+		core.Now = func() time.Time {
 			defer func() { t0 = t0.Add(1 * time.Second) }()
 			return t0
 		}
-		newUUID = func() string {
+		core.NewUUID = func() string {
 			return "a9680ef2-aa57-11e9-85b6-acde48001122"
 		}
 	})
@@ -60,6 +67,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 		tracker = NewDataplaneStatusTracker(runtimeInfo, func(accessor SubscriptionStatusAccessor) DataplaneInsightSink {
 			return DataplaneInsightSinkFunc(func(<-chan struct{}) {})
 		})
+		callbacks = v2.AdaptCallbacks(tracker)
 		ctx = context.Background()
 	})
 
@@ -69,7 +77,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 
 		By("simulating start of ADS subscription")
 		// when
-		err := tracker.OnStreamOpen(ctx, streamID, "")
+		err := callbacks.OnStreamOpen(ctx, streamID, "")
 		// then
 		Expect(err).ToNot(HaveOccurred())
 
@@ -100,7 +108,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 
 		By("simulating end of ADS subscription")
 		// when
-		tracker.OnStreamClosed(streamID)
+		callbacks.OnStreamClosed(streamID)
 
 		By("ensuring ADS subscription final state")
 		// when
@@ -130,7 +138,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 
 		By("simulating start of ADS subscription")
 		// when
-		err := tracker.OnStreamOpen(ctx, streamID, "")
+		err := callbacks.OnStreamOpen(ctx, streamID, "")
 		// then
 		Expect(err).ToNot(HaveOccurred())
 
@@ -144,7 +152,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 		discoveryRequest := &envoy.DiscoveryRequest{
 			TypeUrl: "type.googleapis.com/envoy.api.v2.Listener",
 		}
-		err = tracker.OnStreamRequest(streamID, discoveryRequest)
+		err = callbacks.OnStreamRequest(streamID, discoveryRequest)
 		// then
 		Expect(err).ToNot(HaveOccurred())
 
@@ -195,7 +203,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 
 			By("simulating start of subscription")
 			// when
-			err := tracker.OnStreamOpen(ctx, streamID, "")
+			err := callbacks.OnStreamOpen(ctx, streamID, "")
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
@@ -226,7 +234,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 				},
 				TypeUrl: given.TypeUrl,
 			}
-			err = tracker.OnStreamRequest(streamID, discoveryRequest)
+			err = callbacks.OnStreamRequest(streamID, discoveryRequest)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
@@ -265,7 +273,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 				TypeUrl: given.TypeUrl,
 				Nonce:   "1",
 			}
-			tracker.OnStreamResponse(streamID, discoveryRequest, discoveryResponse)
+			callbacks.OnStreamResponse(streamID, discoveryRequest, discoveryResponse)
 			// and
 			key, subscription = accessor.GetStatus()
 			// then
@@ -281,7 +289,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 				TypeUrl:       given.TypeUrl,
 				ResponseNonce: "1",
 			}
-			err = tracker.OnStreamRequest(streamID, discoveryRequest)
+			err = callbacks.OnStreamRequest(streamID, discoveryRequest)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
@@ -304,7 +312,7 @@ var _ = Describe("DataplaneStatusTracker", func() {
 					Message: "failed to apply LDS response",
 				},
 			}
-			err = tracker.OnStreamRequest(streamID, discoveryRequest)
+			err = callbacks.OnStreamRequest(streamID, discoveryRequest)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
@@ -639,26 +647,31 @@ var _ = Describe("DataplaneStatusTracker", func() {
 	DescribeTable("should read node.metadata without error",
 		func(given versionTestCase) {
 			// given
-			version := mesh_proto.NewVersion()
-			node := &envoy_core.Node{
-				Metadata: &pstruct.Struct{
-					Fields: map[string]*pstruct.Value{
-						"dataplaneTokenPath": {
-							Kind: &pstruct.Value_StringValue{
-								StringValue: "/tmp/token",
-							},
+			streamID := int64(1)
+			discoveryRequest := &envoy.DiscoveryRequest{
+				TypeUrl: "type.googleapis.com/envoy.api.v2.Listener",
+				Node: &envoy_core.Node{
+					Id: "default.example-001",
+					Metadata: &pstruct.Struct{
+						Fields: map[string]*pstruct.Value{
+							"version": given.version,
 						},
-						"version": given.version,
 					},
 				},
 			}
 
 			// when
-			err := readVersion(node.Metadata, version)
+			err := callbacks.OnStreamOpen(context.Background(), streamID, "")
+			Expect(err).ToNot(HaveOccurred())
+			err = callbacks.OnStreamRequest(streamID, discoveryRequest)
 
 			// then
-			Expect(err).To(BeNil())
-			Expect(version).To(Equal(mesh_proto.NewVersion()))
+			Expect(err).ToNot(HaveOccurred())
+
+			// and
+			accessor, _ := tracker.GetStatusAccessor(streamID)
+			_, sub := accessor.GetStatus()
+			Expect(sub.GetVersion()).To(MatchProto(mesh_proto.NewVersion()))
 		},
 		Entry("when version is a nil struct", versionTestCase{
 			version: &pstruct.Value{
diff --git a/pkg/xds/sync/dataplane_sync_tracker_test.go b/pkg/xds/server/callbacks/dataplane_sync_tracker_test.go
similarity index 82%
rename from pkg/xds/sync/dataplane_sync_tracker_test.go
rename to pkg/xds/server/callbacks/dataplane_sync_tracker_test.go
index 53db94789..3f38b0bf6 100644
--- a/pkg/xds/sync/dataplane_sync_tracker_test.go
+++ b/pkg/xds/server/callbacks/dataplane_sync_tracker_test.go
@@ -1,4 +1,4 @@
-package sync_test
+package callbacks_test
 
 import (
 	"context"
@@ -9,8 +9,9 @@ import (
 
 	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
 	util_watchdog "github.com/kumahq/kuma/pkg/util/watchdog"
+	util_xds_v2 "github.com/kumahq/kuma/pkg/util/xds/v2"
 
-	. "github.com/kumahq/kuma/pkg/xds/sync"
+	. "github.com/kumahq/kuma/pkg/xds/server/callbacks"
 
 	envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
 	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
@@ -44,6 +45,7 @@ var _ = Describe("Sync", func() {
 		It("should not fail when Envoy presents invalid Node ID", func() {
 			// setup
 			tracker := NewDataplaneSyncTracker(nil)
+			callbacks := util_xds_v2.AdaptCallbacks(tracker)
 
 			// given
 			ctx := context.Background()
@@ -53,19 +55,19 @@ var _ = Describe("Sync", func() {
 
 			By("simulating Envoy connecting to the Control Plane")
 			// when
-			err := tracker.OnStreamOpen(ctx, streamID, typ)
+			err := callbacks.OnStreamOpen(ctx, streamID, typ)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
 			By("simulating DiscoveryRequest")
 			// when
-			err = tracker.OnStreamRequest(streamID, req)
+			err = callbacks.OnStreamRequest(streamID, req)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
 			By("simulating Envoy disconnecting from the Control Plane")
 			// and
-			tracker.OnStreamClosed(streamID)
+			callbacks.OnStreamClosed(streamID)
 
 			// then
 			// expect no panic
@@ -82,6 +84,7 @@ var _ = Describe("Sync", func() {
 					close(watchdogCh)
 				})
 			}))
+			callbacks := util_xds_v2.AdaptCallbacks(tracker)
 
 			// given
 			ctx := context.Background()
@@ -95,13 +98,13 @@ var _ = Describe("Sync", func() {
 
 			By("simulating Envoy connecting to the Control Plane")
 			// when
-			err := tracker.OnStreamOpen(ctx, streamID, typ)
+			err := callbacks.OnStreamOpen(ctx, streamID, typ)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
 			By("simulating DiscoveryRequest")
 			// when
-			err = tracker.OnStreamRequest(streamID, req)
+			err = callbacks.OnStreamRequest(streamID, req)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
@@ -113,13 +116,13 @@ var _ = Describe("Sync", func() {
 
 			By("simulating another DiscoveryRequest")
 			// when
-			err = tracker.OnStreamRequest(streamID, req)
+			err = callbacks.OnStreamRequest(streamID, req)
 			// then
 			Expect(err).ToNot(HaveOccurred())
 
 			By("simulating Envoy disconnecting from the Control Plane")
 			// and
-			tracker.OnStreamClosed(streamID)
+			callbacks.OnStreamClosed(streamID)
 
 			By("waiting for Watchdog to get stopped")
 			// when
@@ -140,12 +143,13 @@ var _ = Describe("Sync", func() {
 					atomic.AddInt32(&activeWatchdogs, -1)
 				})
 			})
+			callbacks := util_xds_v2.AdaptCallbacks(tracker)
 
 			// when one stream for backend-01 is connected and request is sent
 			streamID := int64(1)
-			err := tracker.OnStreamOpen(context.Background(), streamID, "")
+			err := callbacks.OnStreamOpen(context.Background(), streamID, "")
 			Expect(err).ToNot(HaveOccurred())
-			err = tracker.OnStreamRequest(streamID, &envoy.DiscoveryRequest{
+			err = callbacks.OnStreamRequest(streamID, &envoy.DiscoveryRequest{
 				Node: &envoy_core.Node{
 					Id: "default.backend-01",
 				},
@@ -154,9 +158,9 @@ var _ = Describe("Sync", func() {
 
 			// and when new stream from backend-01 is connected  and request is sent
 			streamID = 2
-			err = tracker.OnStreamOpen(context.Background(), streamID, "")
+			err = callbacks.OnStreamOpen(context.Background(), streamID, "")
 			Expect(err).ToNot(HaveOccurred())
-			err = tracker.OnStreamRequest(streamID, &envoy.DiscoveryRequest{
+			err = callbacks.OnStreamRequest(streamID, &envoy.DiscoveryRequest{
 				Node: &envoy_core.Node{
 					Id: "default.backend-01",
 				},
@@ -169,7 +173,7 @@ var _ = Describe("Sync", func() {
 			}, "5s", "10ms").Should(Equal(int32(1)))
 
 			// when first stream is closed
-			tracker.OnStreamClosed(1)
+			callbacks.OnStreamClosed(1)
 
 			// then watchdog is still active because other stream is opened
 			Eventually(func() int32 {
@@ -177,7 +181,7 @@ var _ = Describe("Sync", func() {
 			}, "5s", "10ms").Should(Equal(int32(1)))
 
 			// when other stream is closed
-			tracker.OnStreamClosed(2)
+			callbacks.OnStreamClosed(2)
 
 			// then no watchdog is stopped
 			Eventually(func() int32 {
diff --git a/pkg/xds/server/components_test.go b/pkg/xds/server/components_test.go
deleted file mode 100644
index 117112dc4..000000000
--- a/pkg/xds/server/components_test.go
+++ /dev/null
@@ -1,135 +0,0 @@
-package server_test
-
-import (
-	"context"
-	"time"
-
-	envoy "github.com/envoyproxy/go-control-plane/envoy/api/v2"
-	envoy_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
-	. "github.com/onsi/ginkgo"
-	. "github.com/onsi/gomega"
-
-	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
-	kuma_cp "github.com/kumahq/kuma/pkg/config/app/kuma-cp"
-	mesh_core "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
-	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
-	core_store "github.com/kumahq/kuma/pkg/core/resources/store"
-	"github.com/kumahq/kuma/pkg/core/xds"
-	test_metrics "github.com/kumahq/kuma/pkg/test/metrics"
-	test_runtime "github.com/kumahq/kuma/pkg/test/runtime"
-	xds_context "github.com/kumahq/kuma/pkg/xds/context"
-	. "github.com/kumahq/kuma/pkg/xds/server"
-)
-
-type event struct {
-	Update *mesh_core.DataplaneResource
-	Delete core_model.ResourceKey
-}
-
-type eventSnapshotReconciler struct {
-	events chan event
-}
-
-func (e *eventSnapshotReconciler) Reconcile(ctx xds_context.Context, proxy *xds.Proxy) error {
-	e.events <- event{Update: proxy.Dataplane}
-	return nil
-}
-
-func (e *eventSnapshotReconciler) Clear(proxyId *xds.ProxyId) error {
-	e.events <- event{Delete: proxyId.ToResourceKey()}
-	return nil
-}
-
-var _ SnapshotReconciler = &eventSnapshotReconciler{}
-
-var _ = Describe("Components", func() {
-	Describe("DefaultDataplaneSyncTracker", func() {
-		It("", func(done Done) {
-			// given
-			cfg := kuma_cp.DefaultConfig()
-			cfg.XdsServer.DataplaneConfigurationRefreshInterval = 1 * time.Millisecond
-
-			// and
-			runtime, err := test_runtime.BuilderFor(cfg).Build()
-			Expect(err).ToNot(HaveOccurred())
-
-			// and example mesh
-			opts := core_store.CreateByKey("demo", core_model.NoMesh)
-			err = runtime.ResourceManager().Create(context.Background(), mesh_core.NewMeshResource(), opts)
-			Expect(err).ToNot(HaveOccurred())
-
-			// setup
-			reconciler := eventSnapshotReconciler{}
-			reconciler.events = make(chan event)
-			// and
-			tracker, err := DefaultDataplaneSyncTracker(runtime, &reconciler, nil, NewDataplaneMetadataTracker(), NewConnectionInfoTracker())
-			Expect(err).ToNot(HaveOccurred())
-
-			// given
-			ctx := context.Background()
-			streamID := int64(1)
-			typ := ""
-			req := &envoy.DiscoveryRequest{
-				Node: &envoy_core.Node{
-					Id: "demo.example",
-				},
-			}
-
-			By("simulating Envoy connecting to the Control Plane")
-			// when
-			err = tracker.OnStreamOpen(ctx, streamID, typ)
-			// then
-			Expect(err).ToNot(HaveOccurred())
-
-			By("simulating DiscoveryRequest")
-			// when
-			err = tracker.OnStreamRequest(streamID, req)
-			// then
-			Expect(err).ToNot(HaveOccurred())
-
-			By("waiting for Watchdog to trigger Dataplane configuration refresh (delete)")
-			// when
-			nextEvent := <-reconciler.events
-			// then
-			Expect(nextEvent.Delete).To(Equal(core_model.ResourceKey{Mesh: "demo", Name: "example"}))
-
-			By("creating Dataplane definition")
-			// when
-			resource := &mesh_core.DataplaneResource{
-				Spec: &mesh_proto.Dataplane{
-					Networking: &mesh_proto.Dataplane_Networking{
-						Address: "127.0.0.1",
-						Inbound: []*mesh_proto.Dataplane_Networking_Inbound{
-							{
-								Port:        9090,
-								ServicePort: 8080,
-								Tags: map[string]string{
-									"kuma.io/service": "backend",
-								},
-							},
-						},
-					},
-				},
-			}
-			err = runtime.ResourceManager().Create(ctx, resource, core_store.CreateBy(core_model.ResourceKey{Mesh: "demo", Name: "example"}))
-			// then
-			Expect(err).ToNot(HaveOccurred())
-
-			By("waiting for Watchdog to trigger Dataplane configuration refresh (update)")
-			// expect
-			Eventually(func() bool {
-				nextEvent := <-reconciler.events
-				return nextEvent.Update != nil
-			}, "1s", "1ms").Should(BeTrue())
-
-			// and metrics are published
-			Expect(test_metrics.FindMetric(runtime.Metrics(), "xds_generation")).ToNot(BeNil())
-
-			By("simulating Envoy disconnecting from the Control Plane")
-			// and
-			tracker.OnStreamClosed(streamID)
-
-			close(done)
-		}, 10)
-	})
-})
diff --git a/pkg/xds/server/reconcile_test.go b/pkg/xds/server/v2/reconcile_test.go
similarity index 97%
rename from pkg/xds/server/reconcile_test.go
rename to pkg/xds/server/v2/reconcile_test.go
index 1faf10c1d..667070180 100644
--- a/pkg/xds/server/reconcile_test.go
+++ b/pkg/xds/server/v2/reconcile_test.go
@@ -1,4 +1,4 @@
-package server
+package v2
 
 import (
 	"fmt"
@@ -12,6 +12,7 @@ import (
 	. "github.com/onsi/gomega"
 
 	mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
+	"github.com/kumahq/kuma/pkg/core"
 	mesh_core "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
 	core_xds "github.com/kumahq/kuma/pkg/core/xds"
 	xds_model "github.com/kumahq/kuma/pkg/core/xds"
@@ -25,16 +26,16 @@ var _ = Describe("Reconcile", func() {
 		var backupNewUUID func() string
 
 		BeforeEach(func() {
-			backupNewUUID = newUUID
+			backupNewUUID = core.NewUUID
 		})
 		AfterEach(func() {
-			newUUID = backupNewUUID
+			core.NewUUID = backupNewUUID
 		})
 
 		var serial uint64
 
 		BeforeEach(func() {
-			newUUID = func() string {
+			core.NewUUID = func() string {
 				uuid := atomic.AddUint64(&serial, 1)
 				return fmt.Sprintf("v%d", uuid)
 			}
diff --git a/pkg/xds/server/v2/server_suite_test.go b/pkg/xds/server/v2/server_suite_test.go
new file mode 100644
index 000000000..5d5802b93
--- /dev/null
+++ b/pkg/xds/server/v2/server_suite_test.go
@@ -0,0 +1,13 @@
+package v2_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestXDSServer(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "XDS Server V2 Suite")
+}
diff --git a/pkg/xds/server/snapshot_generator_test.go b/pkg/xds/server/v2/snapshot_generator_test.go
similarity index 76%
rename from pkg/xds/server/snapshot_generator_test.go
rename to pkg/xds/server/v2/snapshot_generator_test.go
index 2ab72e28c..90199754b 100644
--- a/pkg/xds/server/snapshot_generator_test.go
+++ b/pkg/xds/server/v2/snapshot_generator_test.go
@@ -1,4 +1,4 @@
-package server
+package v2
 
 import (
 	"io/ioutil"
@@ -23,7 +23,7 @@ var _ = Describe("Reconcile", func() {
 	Describe("templateSnapshotGenerator", func() {
 
 		gen := templateSnapshotGenerator{
-			ProxyTemplateResolver: &simpleProxyTemplateResolver{
+			ProxyTemplateResolver: &template.SimpleProxyTemplateResolver{
 				ReadOnlyResourceManager: manager.NewResourceManager(memory.NewStore()),
 				DefaultProxyTemplate:    template.DefaultProxyTemplate,
 			},
@@ -73,31 +73,33 @@ var _ = Describe("Reconcile", func() {
 					},
 					Spec: &dataplane,
 				},
-				TrafficPermissions: model.TrafficPermissionMap{
-					mesh_proto.InboundInterface{
-						DataplaneIP:   "192.168.0.1",
-						DataplanePort: 80,
-						WorkloadIP:    "127.0.0.1",
-						WorkloadPort:  8080,
-					}: &mesh_core.TrafficPermissionResource{
-						Meta: &test_model.ResourceMeta{
-							Name: "tp-1",
-							Mesh: "default",
-						},
-						Spec: &mesh_proto.TrafficPermission{
-							Sources: []*mesh_proto.Selector{
-								{
-									Match: map[string]string{
-										"kuma.io/service": "web1",
-										"version":         "1.0",
+				Policies: model.MatchedPolicies{
+					TrafficPermissions: model.TrafficPermissionMap{
+						mesh_proto.InboundInterface{
+							DataplaneIP:   "192.168.0.1",
+							DataplanePort: 80,
+							WorkloadIP:    "127.0.0.1",
+							WorkloadPort:  8080,
+						}: &mesh_core.TrafficPermissionResource{
+							Meta: &test_model.ResourceMeta{
+								Name: "tp-1",
+								Mesh: "default",
+							},
+							Spec: &mesh_proto.TrafficPermission{
+								Sources: []*mesh_proto.Selector{
+									{
+										Match: map[string]string{
+											"kuma.io/service": "web1",
+											"version":         "1.0",
+										},
 									},
 								},
-							},
-							Destinations: []*mesh_proto.Selector{
-								{
-									Match: map[string]string{
-										"kuma.io/service": "backend1",
-										"env":             "dev",
+								Destinations: []*mesh_proto.Selector{
+									{
+										Match: map[string]string{
+											"kuma.io/service": "backend1",
+											"env":             "dev",
+										},
 									},
 								},
 							},
diff --git a/pkg/xds/server/proxy_template_resolver_test.go b/pkg/xds/template/proxy_template_resolver_test.go
similarity index 94%
rename from pkg/xds/server/proxy_template_resolver_test.go
rename to pkg/xds/template/proxy_template_resolver_test.go
index 44fa9f881..3012a4ca9 100644
--- a/pkg/xds/server/proxy_template_resolver_test.go
+++ b/pkg/xds/template/proxy_template_resolver_test.go
@@ -1,4 +1,4 @@
-package server
+package template
 
 import (
 	"context"
@@ -17,7 +17,7 @@ import (
 )
 
 var _ = Describe("Reconcile", func() {
-	Describe("simpleProxyTemplateResolver", func() {
+	Describe("SimpleProxyTemplateResolver", func() {
 		It("should fallback to the default ProxyTemplate when there are no other candidates", func() {
 			// given
 			proxy := &model.Proxy{
@@ -29,7 +29,7 @@ var _ = Describe("Reconcile", func() {
 			}
 
 			// setup
-			resolver := &simpleProxyTemplateResolver{
+			resolver := &SimpleProxyTemplateResolver{
 				ReadOnlyResourceManager: manager.NewResourceManager(memory.NewStore()),
 				DefaultProxyTemplate:    &mesh_proto.ProxyTemplate{},
 			}
@@ -93,7 +93,7 @@ var _ = Describe("Reconcile", func() {
 				Expect(err).ToNot(HaveOccurred())
 			}
 
-			resolver := &simpleProxyTemplateResolver{
+			resolver := &SimpleProxyTemplateResolver{
 				ReadOnlyResourceManager: manager.NewResourceManager(memStore),
 				DefaultProxyTemplate:    &mesh_proto.ProxyTemplate{},
 			}
@@ -120,7 +120,7 @@ var _ = Describe("Reconcile", func() {
 			}
 
 			// setup
-			resolver := &simpleProxyTemplateResolver{
+			resolver := &SimpleProxyTemplateResolver{
 				ReadOnlyResourceManager: manager.NewResourceManager(memory.NewStore()),
 				DefaultProxyTemplate:    &mesh_proto.ProxyTemplate{},
 			}