Repository: kubernetes-sigs/node-feature-discovery
Pull request #994 (2022-12-14 14:13:43)

E2E: default kubeconfig location to ${HOME}/.kube/config
In most of the cases we fall back to `${HOME}/.kube/config` anyways.

netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *kubernetes-sigs-nfd* processing.


|  Name | Link |
|---------------------------------|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 4dd0f0b12c7a0e33496daf60e5a92ba212969f68 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/kubernetes-sigs-nfd/deploys/6399da1949b6f2000929018d |
fmuyassarov: bot is still loading my CLA ....

Patch:
diff --git a/Makefile b/Makefile
index 3a116678c..47a736d54 100644
--- a/Makefile
+++ b/Makefile
@@ -51,7 +51,7 @@ else
 endif
 HOSTMOUNT_PREFIX ?= /
 
-KUBECONFIG ?=
+KUBECONFIG ?= ${HOME}/.kube/config
 E2E_TEST_CONFIG ?=
 E2E_PULL_IF_NOT_PRESENT ?= false
 
diff --git a/cmd/nfd-master/main.go b/cmd/nfd-master/main.go
index b42cc6286..07c41c50f 100644
--- a/cmd/nfd-master/main.go
+++ b/cmd/nfd-master/main.go
@@ -50,14 +50,6 @@ func main() {
 		os.Exit(2)
 	}
 
-	// Check deprecated flags
-	flags.Visit(func(f *flag.Flag) {
-		switch f.Name {
-		case "featurerules-controller":
-			klog.Warningf("-featurerules-controller is deprecated, use '-crd-controller' flag instead")
-		}
-	})
-
 	if *printVersion {
 		fmt.Println(ProgramName, version.Get())
 		os.Exit(0)
@@ -102,16 +94,10 @@ func initFlags(flagset *flag.FlagSet) *master.Args {
 	flagset.Var(&args.LabelWhiteList, "label-whitelist",
 		"Regular expression to filter label names to publish to the Kubernetes API server. "+
 			"NB: the label namespace is omitted i.e. the filter is only applied to the name part after '/'.")
-	flagset.BoolVar(&args.EnableNodeFeatureApi, "enable-nodefeature-api", false,
-		"Enable the NodeFeature CRD API for receiving node features. This will automatically disable the gRPC communication.")
 	flagset.BoolVar(&args.NoPublish, "no-publish", false,
 		"Do not publish feature labels")
-	flagset.BoolVar(&args.EnableTaints, "enable-taints", false,
-		"Enable node tainting feature")
-	flagset.BoolVar(&args.CrdController, "featurerules-controller", true,
-		"Enable NFD CRD API controller. DEPRECATED: use -crd-controller instead")
-	flagset.BoolVar(&args.CrdController, "crd-controller", true,
-		"Enable NFD CRD API controller for processing NodeFeature and NodeFeatureRule objects.")
+	flagset.BoolVar(&args.FeatureRulesController, "featurerules-controller", true,
+		"Enable controller for NodeFeatureRule objects. Generates node labels based on the rules in these CRs.")
 	flagset.IntVar(&args.Port, "port", 8080,
 		"Port on which to listen for connections.")
 	flagset.BoolVar(&args.Prune, "prune", false,
diff --git a/cmd/nfd-topology-updater/main.go b/cmd/nfd-topology-updater/main.go
index e6115b3ee..0b9bef9e8 100644
--- a/cmd/nfd-topology-updater/main.go
+++ b/cmd/nfd-topology-updater/main.go
@@ -93,7 +93,10 @@ func main() {
 	klog.Infof("detected kubelet Topology Manager policy %q", tmPolicy)
 
 	// Get new TopologyUpdater instance
-	instance := topology.NewTopologyUpdater(*args, *resourcemonitorArgs, tmPolicy)
+	instance, err := topology.NewTopologyUpdater(*args, *resourcemonitorArgs, tmPolicy)
+	if err != nil {
+		klog.Exitf("failed to initialize TopologyUpdater instance: %v", err)
+	}
 
 	if err = instance.Run(); err != nil {
 		klog.Exit(err)
@@ -126,6 +129,12 @@ func initFlags(flagset *flag.FlagSet) (*topology.Args, *resourcemonitor.Args) {
 	args := &topology.Args{}
 	resourcemonitorArgs := &resourcemonitor.Args{}
 
+	flagset.StringVar(&args.CaFile, "ca-file", "",
+		"Root certificate for verifying connections")
+	flagset.StringVar(&args.CertFile, "cert-file", "",
+		"Certificate used for authenticating connections")
+	flagset.StringVar(&args.KeyFile, "key-file", "",
+		"Private key matching -cert-file")
 	flagset.BoolVar(&args.Oneshot, "oneshot", false,
 		"Update once and exit")
 	flagset.BoolVar(&args.NoPublish, "no-publish", false,
@@ -142,6 +151,10 @@ func initFlags(flagset *flag.FlagSet) (*topology.Args, *resourcemonitor.Args) {
 		"API auth token file path. It is used to request kubelet configz endpoint, only takes effect when kubelet-config-uri is https. Default to /var/run/secrets/kubernetes.io/serviceaccount/token.")
 	flagset.StringVar(&resourcemonitorArgs.PodResourceSocketPath, "podresources-socket", hostpath.VarDir.Path("lib/kubelet/pod-resources/kubelet.sock"),
 		"Pod Resource Socket path to use.")
+	flagset.StringVar(&args.Server, "server", "localhost:8080",
+		"NFD server address to connecto to.")
+	flagset.StringVar(&args.ServerNameOverride, "server-name-override", "",
+		"Hostname expected from server certificate, useful in testing")
 	flagset.StringVar(&args.ConfigFile, "config", "/etc/kubernetes/node-feature-discovery/nfd-topology-updater.conf",
 		"Config file to use.")
 
diff --git a/cmd/nfd-worker/main.go b/cmd/nfd-worker/main.go
index 30e3290d1..90892380f 100644
--- a/cmd/nfd-worker/main.go
+++ b/cmd/nfd-worker/main.go
@@ -101,10 +101,6 @@ func initFlags(flagset *flag.FlagSet) (*worker.Args, *worker.ConfigOverrideArgs)
 		"Config file to use.")
 	flagset.StringVar(&args.KeyFile, "key-file", "",
 		"Private key matching -cert-file")
-	flagset.BoolVar(&args.EnableNodeFeatureApi, "enable-nodefeature-api", false,
-		"Enable the NodeFeature CRD API for communicating with nfd-master. This will automatically disable the gRPC communication.")
-	flagset.StringVar(&args.Kubeconfig, "kubeconfig", "",
-		"Kubeconfig to use")
 	flagset.BoolVar(&args.Oneshot, "oneshot", false,
 		"Do not publish feature labels")
 	flagset.StringVar(&args.Options, "options", "",
@@ -123,7 +119,7 @@ func initFlags(flagset *flag.FlagSet) (*worker.Args, *worker.ConfigOverrideArgs)
 		LabelSources:   &utils.StringSliceVal{},
 	}
 	overrides.NoPublish = flagset.Bool("no-publish", false,
-		"Do not publish discovered features, disable connection to nfd-master and don't create NodeFeature object.")
+		"Do not publish discovered features, disable connection to nfd-master.")
 	flagset.Var(overrides.FeatureSources, "feature-sources",
 		"Comma separated list of feature sources. Special value 'all' enables all sources. "+
 			"Prefix the source name with '-' to disable it.")
diff --git a/deployment/base/nfd-crds/cr-sample.yaml b/deployment/base/nfd-crds/cr-sample.yaml
index 539757209..dad9405d0 100644
--- a/deployment/base/nfd-crds/cr-sample.yaml
+++ b/deployment/base/nfd-crds/cr-sample.yaml
@@ -7,12 +7,6 @@ spec:
     # The following feature demonstrates the capabilities of the matchFeatures and
     # matchAny matchers.
     - name: "my feature rule"
-      taints:
-        - effect: PreferNoSchedule
-          key: "feature.node.kubernetes.io/special-node"
-          value: "true"
-        - effect: NoExecute
-          key: "feature.node.kubernetes.io/dedicated-node"
       labels:
         "my-complex-feature": "my-value"
       # matchFeatures implements a logical AND over feature matchers.
diff --git a/deployment/base/nfd-crds/kustomization.yaml b/deployment/base/nfd-crds/kustomization.yaml
index b7f95447e..73fd8cc08 100644
--- a/deployment/base/nfd-crds/kustomization.yaml
+++ b/deployment/base/nfd-crds/kustomization.yaml
@@ -2,4 +2,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 
 resources:
-- nfd-api-crds.yaml
+- nodefeaturerule-crd.yaml
diff --git a/deployment/base/nfd-crds/nfd-api-crds.yaml b/deployment/base/nfd-crds/nodefeaturerule-crd.yaml
similarity index 66%
rename from deployment/base/nfd-crds/nfd-api-crds.yaml
rename to deployment/base/nfd-crds/nodefeaturerule-crd.yaml
index ab10f15a9..e8e6004d1 100644
--- a/deployment/base/nfd-crds/nfd-api-crds.yaml
+++ b/deployment/base/nfd-crds/nodefeaturerule-crd.yaml
@@ -1,117 +1,6 @@
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
-metadata:
-  annotations:
-    controller-gen.kubebuilder.io/version: v0.9.2
-  creationTimestamp: null
-  name: nodefeatures.nfd.k8s-sigs.io
-spec:
-  group: nfd.k8s-sigs.io
-  names:
-    kind: NodeFeature
-    listKind: NodeFeatureList
-    plural: nodefeatures
-    singular: nodefeature
-  scope: Namespaced
-  versions:
-  - name: v1alpha1
-    schema:
-      openAPIV3Schema:
-        description: NodeFeature resource holds the features discovered for one node
-          in the cluster.
-        properties:
-          apiVersion:
-            description: 'APIVersion defines the versioned schema of this representation
-              of an object. Servers should convert recognized schemas to the latest
-              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
-            type: string
-          kind:
-            description: 'Kind is a string value representing the REST resource this
-              object represents. Servers may infer this from the endpoint the client
-              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-            type: string
-          metadata:
-            type: object
-          spec:
-            description: NodeFeatureSpec describes a NodeFeature object.
-            properties:
-              features:
-                description: Features is the full "raw" features data that has been
-                  discovered.
-                properties:
-                  attributes:
-                    additionalProperties:
-                      description: AttributeFeatureSet is a set of features having
-                        string value.
-                      properties:
-                        elements:
-                          additionalProperties:
-                            type: string
-                          type: object
-                      required:
-                      - elements
-                      type: object
-                    type: object
-                  flags:
-                    additionalProperties:
-                      description: FlagFeatureSet is a set of simple features only
-                        containing names without values.
-                      properties:
-                        elements:
-                          additionalProperties:
-                            description: Nil is a dummy empty struct for protobuf
-                              compatibility
-                            type: object
-                          type: object
-                      required:
-                      - elements
-                      type: object
-                    type: object
-                  instances:
-                    additionalProperties:
-                      description: InstanceFeatureSet is a set of features each of
-                        which is an instance having multiple attributes.
-                      properties:
-                        elements:
-                          items:
-                            description: InstanceFeature represents one instance of
-                              a complex features, e.g. a device.
-                            properties:
-                              attributes:
-                                additionalProperties:
-                                  type: string
-                                type: object
-                            required:
-                            - attributes
-                            type: object
-                          type: array
-                      required:
-                      - elements
-                      type: object
-                    type: object
-                required:
-                - attributes
-                - flags
-                - instances
-                type: object
-              labels:
-                additionalProperties:
-                  type: string
-                description: Labels is the set of node labels that are requested to
-                  be created.
-                type: object
-            required:
-            - features
-            type: object
-        required:
-        - spec
-        type: object
-    served: true
-    storage: true
----
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
 metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.9.2
@@ -300,35 +189,6 @@ spec:
                     name:
                       description: Name of the rule.
                       type: string
-                    taints:
-                      description: Taints to create if the rule matches.
-                      items:
-                        description: The node this Taint is attached to has the "effect"
-                          on any pod that does not tolerate the Taint.
-                        properties:
-                          effect:
-                            description: Required. The effect of the taint on pods
-                              that do not tolerate the taint. Valid effects are NoSchedule,
-                              PreferNoSchedule and NoExecute.
-                            type: string
-                          key:
-                            description: Required. The taint key to be applied to
-                              a node.
-                            type: string
-                          timeAdded:
-                            description: TimeAdded represents the time at which the
-                              taint was added. It is only written for NoExecute taints.
-                            format: date-time
-                            type: string
-                          value:
-                            description: The taint value corresponding to the taint
-                              key.
-                            type: string
-                        required:
-                        - effect
-                        - key
-                        type: object
-                      type: array
                     vars:
                       additionalProperties:
                         type: string
diff --git a/deployment/base/rbac-topologyupdater/topologyupdater-clusterrole.yaml b/deployment/base/rbac-topologyupdater/topologyupdater-clusterrole.yaml
index 493f396c1..1719edbe0 100644
--- a/deployment/base/rbac-topologyupdater/topologyupdater-clusterrole.yaml
+++ b/deployment/base/rbac-topologyupdater/topologyupdater-clusterrole.yaml
@@ -22,11 +22,3 @@ rules:
   - pods
   verbs:
   - get
-- apiGroups:
-  - topology.node.k8s.io
-  resources:
-  - noderesourcetopologies
-  verbs:
-  - create
-  - get
-  - update
diff --git a/deployment/base/rbac/kustomization.yaml b/deployment/base/rbac/kustomization.yaml
index 6eb2d8a8c..fdadb5675 100644
--- a/deployment/base/rbac/kustomization.yaml
+++ b/deployment/base/rbac/kustomization.yaml
@@ -7,6 +7,3 @@ resources:
 - master-serviceaccount.yaml
 - master-clusterrole.yaml
 - master-clusterrolebinding.yaml
-- worker-serviceaccount.yaml
-- worker-role.yaml
-- worker-rolebinding.yaml
diff --git a/deployment/base/rbac/master-clusterrole.yaml b/deployment/base/rbac/master-clusterrole.yaml
index d464e546e..975616ecf 100644
--- a/deployment/base/rbac/master-clusterrole.yaml
+++ b/deployment/base/rbac/master-clusterrole.yaml
@@ -12,10 +12,17 @@ rules:
   - patch
   - update
   - list
+- apiGroups:
+  - topology.node.k8s.io
+  resources:
+  - noderesourcetopologies
+  verbs:
+  - create
+  - get
+  - update
 - apiGroups:
   - nfd.k8s-sigs.io
   resources:
-  - nodefeatures
   - nodefeaturerules
   verbs:
   - get
diff --git a/deployment/base/rbac/worker-role.yaml b/deployment/base/rbac/worker-role.yaml
deleted file mode 100644
index 72f261e9e..000000000
--- a/deployment/base/rbac/worker-role.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-apiVersion: rbac.authorization.k8s.io/v1
-kind: Role
-metadata:
-  name: nfd-worker
-rules:
-- apiGroups:
-  - nfd.k8s-sigs.io
-  resources:
-  - nodefeatures
-  verbs:
-  - create
-  - get
-  - update
diff --git a/deployment/base/rbac/worker-rolebinding.yaml b/deployment/base/rbac/worker-rolebinding.yaml
deleted file mode 100644
index 707c75fbb..000000000
--- a/deployment/base/rbac/worker-rolebinding.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-apiVersion: rbac.authorization.k8s.io/v1
-kind: RoleBinding
-metadata:
-  name: nfd-worker
-roleRef:
-  apiGroup: rbac.authorization.k8s.io
-  kind: Role
-  name: nfd-worker
-subjects:
-- kind: ServiceAccount
-  name: nfd-worker
-  namespace: default
diff --git a/deployment/base/rbac/worker-serviceaccount.yaml b/deployment/base/rbac/worker-serviceaccount.yaml
deleted file mode 100644
index 442b06c5e..000000000
--- a/deployment/base/rbac/worker-serviceaccount.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: nfd-worker
diff --git a/deployment/base/topologyupdater-daemonset/topologyupdater-daemonset.yaml b/deployment/base/topologyupdater-daemonset/topologyupdater-daemonset.yaml
index 8971ea8ab..b89483148 100644
--- a/deployment/base/topologyupdater-daemonset/topologyupdater-daemonset.yaml
+++ b/deployment/base/topologyupdater-daemonset/topologyupdater-daemonset.yaml
@@ -21,4 +21,5 @@ spec:
           imagePullPolicy: Always
           command:
             - "nfd-topology-updater"
-          args: []
+          args:
+            - "-server=nfd-master:8080"
diff --git a/deployment/base/worker-daemonset/worker-daemonset.yaml b/deployment/base/worker-daemonset/worker-daemonset.yaml
index f93bf175f..8f02fd0e1 100644
--- a/deployment/base/worker-daemonset/worker-daemonset.yaml
+++ b/deployment/base/worker-daemonset/worker-daemonset.yaml
@@ -13,7 +13,6 @@ spec:
       labels:
         app: nfd-worker
     spec:
-      serviceAccount: nfd-worker
       dnsPolicy: ClusterFirstWithHostNet
       containers:
         - name: nfd-worker
diff --git a/deployment/base/worker-job/worker-job.yaml b/deployment/base/worker-job/worker-job.yaml
index 6cf2c9dbf..dd2f671dc 100644
--- a/deployment/base/worker-job/worker-job.yaml
+++ b/deployment/base/worker-job/worker-job.yaml
@@ -12,7 +12,6 @@ spec:
       labels:
         app: nfd-worker
     spec:
-      serviceAccount: nfd-worker
       dnsPolicy: ClusterFirstWithHostNet
       restartPolicy: Never
       affinity:
diff --git a/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml b/deployment/helm/node-feature-discovery/crds/nodefeaturerule-crd.yaml
similarity index 66%
rename from deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml
rename to deployment/helm/node-feature-discovery/crds/nodefeaturerule-crd.yaml
index ab10f15a9..e8e6004d1 100644
--- a/deployment/helm/node-feature-discovery/crds/nfd-api-crds.yaml
+++ b/deployment/helm/node-feature-discovery/crds/nodefeaturerule-crd.yaml
@@ -1,117 +1,6 @@
 ---
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
-metadata:
-  annotations:
-    controller-gen.kubebuilder.io/version: v0.9.2
-  creationTimestamp: null
-  name: nodefeatures.nfd.k8s-sigs.io
-spec:
-  group: nfd.k8s-sigs.io
-  names:
-    kind: NodeFeature
-    listKind: NodeFeatureList
-    plural: nodefeatures
-    singular: nodefeature
-  scope: Namespaced
-  versions:
-  - name: v1alpha1
-    schema:
-      openAPIV3Schema:
-        description: NodeFeature resource holds the features discovered for one node
-          in the cluster.
-        properties:
-          apiVersion:
-            description: 'APIVersion defines the versioned schema of this representation
-              of an object. Servers should convert recognized schemas to the latest
-              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
-            type: string
-          kind:
-            description: 'Kind is a string value representing the REST resource this
-              object represents. Servers may infer this from the endpoint the client
-              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-            type: string
-          metadata:
-            type: object
-          spec:
-            description: NodeFeatureSpec describes a NodeFeature object.
-            properties:
-              features:
-                description: Features is the full "raw" features data that has been
-                  discovered.
-                properties:
-                  attributes:
-                    additionalProperties:
-                      description: AttributeFeatureSet is a set of features having
-                        string value.
-                      properties:
-                        elements:
-                          additionalProperties:
-                            type: string
-                          type: object
-                      required:
-                      - elements
-                      type: object
-                    type: object
-                  flags:
-                    additionalProperties:
-                      description: FlagFeatureSet is a set of simple features only
-                        containing names without values.
-                      properties:
-                        elements:
-                          additionalProperties:
-                            description: Nil is a dummy empty struct for protobuf
-                              compatibility
-                            type: object
-                          type: object
-                      required:
-                      - elements
-                      type: object
-                    type: object
-                  instances:
-                    additionalProperties:
-                      description: InstanceFeatureSet is a set of features each of
-                        which is an instance having multiple attributes.
-                      properties:
-                        elements:
-                          items:
-                            description: InstanceFeature represents one instance of
-                              a complex features, e.g. a device.
-                            properties:
-                              attributes:
-                                additionalProperties:
-                                  type: string
-                                type: object
-                            required:
-                            - attributes
-                            type: object
-                          type: array
-                      required:
-                      - elements
-                      type: object
-                    type: object
-                required:
-                - attributes
-                - flags
-                - instances
-                type: object
-              labels:
-                additionalProperties:
-                  type: string
-                description: Labels is the set of node labels that are requested to
-                  be created.
-                type: object
-            required:
-            - features
-            type: object
-        required:
-        - spec
-        type: object
-    served: true
-    storage: true
----
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
 metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.9.2
@@ -300,35 +189,6 @@ spec:
                     name:
                       description: Name of the rule.
                       type: string
-                    taints:
-                      description: Taints to create if the rule matches.
-                      items:
-                        description: The node this Taint is attached to has the "effect"
-                          on any pod that does not tolerate the Taint.
-                        properties:
-                          effect:
-                            description: Required. The effect of the taint on pods
-                              that do not tolerate the taint. Valid effects are NoSchedule,
-                              PreferNoSchedule and NoExecute.
-                            type: string
-                          key:
-                            description: Required. The taint key to be applied to
-                              a node.
-                            type: string
-                          timeAdded:
-                            description: TimeAdded represents the time at which the
-                              taint was added. It is only written for NoExecute taints.
-                            format: date-time
-                            type: string
-                          value:
-                            description: The taint value corresponding to the taint
-                              key.
-                            type: string
-                        required:
-                        - effect
-                        - key
-                        type: object
-                      type: array
                     vars:
                       additionalProperties:
                         type: string
diff --git a/deployment/helm/node-feature-discovery/templates/clusterrole.yaml b/deployment/helm/node-feature-discovery/templates/clusterrole.yaml
index 3dd6f6f3b..587a5a955 100644
--- a/deployment/helm/node-feature-discovery/templates/clusterrole.yaml
+++ b/deployment/helm/node-feature-discovery/templates/clusterrole.yaml
@@ -27,12 +27,21 @@ rules:
 - apiGroups:
   - nfd.k8s-sigs.io
   resources:
-  - nodefeatures
   - nodefeaturerules
   verbs:
   - get
   - list
   - watch
+{{- if .Values.topologyUpdater.enable }}
+- apiGroups:
+  - topology.node.k8s.io
+  resources:
+  - noderesourcetopologies
+  verbs:
+  - create
+  - get
+  - update
+{{- end }}
 {{- end }}
 
 ---
@@ -57,12 +66,4 @@ rules:
   - pods
   verbs:
   - get
-- apiGroups:
-  - topology.node.k8s.io
-  resources:
-  - noderesourcetopologies
-  verbs:
-  - create
-  - get
-  - update
 {{- end }}
diff --git a/deployment/helm/node-feature-discovery/templates/master.yaml b/deployment/helm/node-feature-discovery/templates/master.yaml
index 26a326cb8..498964f8a 100644
--- a/deployment/helm/node-feature-discovery/templates/master.yaml
+++ b/deployment/helm/node-feature-discovery/templates/master.yaml
@@ -78,23 +78,17 @@ spec:
             {{- if .Values.master.instance | empty | not }}
             - "--instance={{ .Values.master.instance }}"
             {{- end }}
-            {{- if .Values.enableNodeFeatureApi }}
-            - "-enable-nodefeature-api"
-            {{- end }}
             {{- if .Values.master.extraLabelNs | empty | not }}
             - "--extra-label-ns={{- join "," .Values.master.extraLabelNs }}"
             {{- end }}
             {{- if .Values.master.resourceLabels | empty | not }}
             - "--resource-labels={{- join "," .Values.master.resourceLabels }}"
             {{- end }}
-            {{- if .Values.master.crdController | kindIs "invalid" | not }}
-            - "-crd-controller={{ .Values.master.crdController }}"
-            {{- else }}
-            ## By default, disable crd controller for other than the default instances
-            - "-featurerules-controller={{ .Values.master.instance | empty }}"
-            {{- end }}
             {{- if .Values.master.featureRulesController | kindIs "invalid" | not }}
             - "-featurerules-controller={{ .Values.master.featureRulesController }}"
+            {{- else }}
+            ## By default, disable NodeFeatureRules controller for other than the default instances
+            - "-featurerules-controller={{ .Values.master.instance | empty }}"
             {{- end }}
     {{- if .Values.tls.enable }}
             - "--ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
diff --git a/deployment/helm/node-feature-discovery/templates/nodefeaturerule-crd.yaml b/deployment/helm/node-feature-discovery/templates/nodefeaturerule-crd.yaml
new file mode 100644
index 000000000..c02c633d8
--- /dev/null
+++ b/deployment/helm/node-feature-discovery/templates/nodefeaturerule-crd.yaml
@@ -0,0 +1,3 @@
+{{- if .Values.nodeFeatureRule.createCRD }}
+{{ .Files.Get "crds/nodefeaturerule-crd.yaml" }}
+{{- end}}
diff --git a/deployment/helm/node-feature-discovery/templates/role.yaml b/deployment/helm/node-feature-discovery/templates/role.yaml
deleted file mode 100644
index f63cb8ff4..000000000
--- a/deployment/helm/node-feature-discovery/templates/role.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-{{- if .Values.worker.rbac.create }}
-apiVersion: rbac.authorization.k8s.io/v1
-kind: Role
-metadata:
-  name: {{ include "node-feature-discovery.fullname" . }}-worker
-  labels:
-    {{- include "node-feature-discovery.labels" . | nindent 4 }}
-rules:
-- apiGroups:
-  - nfd.k8s-sigs.io
-  resources:
-  - nodefeatures
-  verbs:
-  - create
-  - get
-  - update
-{{- end }}
-
diff --git a/deployment/helm/node-feature-discovery/templates/rolebinding.yaml b/deployment/helm/node-feature-discovery/templates/rolebinding.yaml
deleted file mode 100644
index 30a00381f..000000000
--- a/deployment/helm/node-feature-discovery/templates/rolebinding.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-{{- if .Values.worker.rbac.create }}
-apiVersion: rbac.authorization.k8s.io/v1
-kind: RoleBinding
-metadata:
-  name: {{ include "node-feature-discovery.fullname" . }}-worker
-  labels:
-    {{- include "node-feature-discovery.labels" . | nindent 4 }}
-roleRef:
-  apiGroup: rbac.authorization.k8s.io
-  kind: Role
-  name: {{ include "node-feature-discovery.fullname" . }}-worker
-subjects:
-- kind: ServiceAccount
-  name: {{ include "node-feature-discovery.worker.serviceAccountName" . }}
-  namespace: {{ include "node-feature-discovery.namespace" .  }}
-{{- end }}
-
diff --git a/deployment/helm/node-feature-discovery/templates/service.yaml b/deployment/helm/node-feature-discovery/templates/service.yaml
index 6731ca43a..95b6d10b4 100644
--- a/deployment/helm/node-feature-discovery/templates/service.yaml
+++ b/deployment/helm/node-feature-discovery/templates/service.yaml
@@ -15,4 +15,3 @@ spec:
       name: grpc
   selector:
     {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }}
-    role: master
diff --git a/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml b/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml
index 2f28b969f..a53a6033c 100644
--- a/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml
+++ b/deployment/helm/node-feature-discovery/templates/topologyupdater.yaml
@@ -40,6 +40,7 @@ spec:
         command:
           - "nfd-topology-updater"
         args:
+          - "--server={{ include "node-feature-discovery.fullname" . }}-master:{{ .Values.master.service.port }}"
           {{- if .Values.topologyUpdater.updateInterval | empty | not }}
           - "--sleep-interval={{ .Values.topologyUpdater.updateInterval }}"
           {{- else }}
@@ -67,7 +68,7 @@ spec:
           mountPath: "/etc/kubernetes/node-feature-discovery/certs"
           readOnly: true
         {{- end }}
-        - name: nfd-topology-updater-conf
+        - name: topology-updater-conf
           mountPath: "/etc/kubernetes/node-feature-discovery"
           readOnly: true
 
diff --git a/deployment/helm/node-feature-discovery/templates/worker.yaml b/deployment/helm/node-feature-discovery/templates/worker.yaml
index e723cc5cb..f48aade32 100644
--- a/deployment/helm/node-feature-discovery/templates/worker.yaml
+++ b/deployment/helm/node-feature-discovery/templates/worker.yaml
@@ -46,9 +46,6 @@ spec:
         - "nfd-worker"
         args:
         - "--server={{ include "node-feature-discovery.fullname" . }}-master:{{ .Values.master.service.port }}"
-        {{- if .Values.enableNodeFeatureApi }}
-        - "-enable-nodefeature-api"
-        {{- end }}
 {{- if .Values.tls.enable }}
         - "--ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
         - "--key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key"
diff --git a/deployment/helm/node-feature-discovery/values.yaml b/deployment/helm/node-feature-discovery/values.yaml
index 8531e963a..477f16297 100644
--- a/deployment/helm/node-feature-discovery/values.yaml
+++ b/deployment/helm/node-feature-discovery/values.yaml
@@ -10,14 +10,13 @@ nameOverride: ""
 fullnameOverride: ""
 namespaceOverride: ""
 
-enableNodeFeatureApi: false
+nodeFeatureRule:
+  createCRD: true
 
 master:
   instance:
-  featureApi:
   extraLabelNs: []
   resourceLabels: []
-  crdController: null
   featureRulesController: null
   deploymentAnnotations: {}
   replicaCount: 1
@@ -342,9 +341,6 @@ worker:
     # If not set and create is true, a name is generated using the fullname template
     name:
 
-  rbac:
-    create: true
-
   # Allow users to mount the hostPath /usr/src, useful for RHCOS on s390x
   # Does not work on systems without /usr/src AND a read-only /usr, such as Talos
   mountUsrSrc: false
diff --git a/deployment/overlays/topologyupdater/kustomization.yaml b/deployment/overlays/topologyupdater/kustomization.yaml
index b344d993b..e007b40a0 100644
--- a/deployment/overlays/topologyupdater/kustomization.yaml
+++ b/deployment/overlays/topologyupdater/kustomization.yaml
@@ -4,7 +4,9 @@ kind: Kustomization
 namespace: node-feature-discovery
 
 bases:
+- ../../base/rbac
 - ../../base/rbac-topologyupdater
+- ../../base/master
 - ../../base/noderesourcetopologies-crd
 - ../../base/topologyupdater-daemonset
 
diff --git a/docs/deployment/helm.md b/docs/deployment/helm.md
index 03115988e..ef5821332 100644
--- a/docs/deployment/helm.md
+++ b/docs/deployment/helm.md
@@ -95,9 +95,9 @@ We have introduced the following Chart parameters.
 | `imagePullSecrets` | list | [] | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. [More info](https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod) |
 | `nameOverride` | string |  | Override the name of the chart |
 | `fullnameOverride` | string |  | Override a default fully qualified app name |
+| `nodeFeatureRule.createCRD` | bool | true | Specifies whether to create the NodeFeatureRule CRD |
 | `tls.enable` | bool | false | Specifies whether to use TLS for communications between components |
 | `tls.certManager` | bool | false | If enabled, requires [cert-manager](https://cert-manager.io/docs/) to be installed and will automatically create the required TLS certificates |
-| `enableNodeFeatureApi` | bool  | false | Enable the NodeFeature CRD API for communicating node features. This will automatically disable the gRPC communication.
 
 ### Master pod parameters
 
@@ -107,8 +107,7 @@ We have introduced the following Chart parameters.
 | `master.instance`           | string  |                                         | Instance name. Used to separate annotation namespaces for multiple parallel deployments                                                  |
 | `master.extraLabelNs`       | array   | []                                      | List of allowed extra label namespaces                                                                                                   |
 | `master.resourceLabels`     | array   | []                                      | List of labels to be registered as extended resources                                                                                          |
-| `master.crdController`      | bool    | null                                    | Specifies whether the NFD CRD API controller is enabled. If not set, controller will be enabled if `master.instance` is empty. |
-| `master.featureRulesController` | bool | null                                   | DEPRECATED: use `master.crdController` instead |
+| `master.featureRulesController` | bool | null                                   | Specifies whether the controller for processing of NodeFeatureRule objects is enabled. If not set, controller will be enabled if `master.instance` is empty. |
 | `master.replicaCount`       | integer | 1                                       | Number of desired pods. This is a pointer to distinguish between explicit zero and not specified                                         |
 | `master.podSecurityContext` | dict    | {}                                      | [PodSecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) holds pod-level security attributes and common container settings |
 | `master.securityContext`    | dict    | {}                                      | Container [security settings](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container)|
@@ -136,7 +135,6 @@ We have introduced the following Chart parameters.
 | `worker.serviceAccount.create`      | bool   | true | Specifies whether a service account for nfd-worker should be created
 | `worker.serviceAccount.annotations` | dict   | {}   | Annotations to add to the service account for nfd-worker
 | `worker.serviceAccount.name`        | string |      | The name of the service account to use for nfd-worker. If not set and create is true, a name is generated using the fullname template (suffixed with `-worker`)
-| `worker.rbac.create`  | bool | true | Specifies whether to create [RBAC][rbac] configuration for nfd-worker
 | `worker.mountUsrSrc` | bool | false | Specifies whether to allow users to mount the hostpath /user/src. Does not work on systems without /usr/src AND a read-only /usr |
 | `worker.resources` | dict | {} | NFD worker pod [resources management](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) |
 | `worker.nodeSelector` | dict | {} | NFD worker pod [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) |
diff --git a/docs/deployment/kustomize.md b/docs/deployment/kustomize.md
index b5d84a0d7..75fd504d9 100644
--- a/docs/deployment/kustomize.md
+++ b/docs/deployment/kustomize.md
@@ -101,9 +101,9 @@ node(s) will run extra job instance(s) to satisfy the request.
 
 ### Master Worker Topologyupdater
 
-NFD-Master, nfd-worker and nfd-topology-updater can be configured to be
-deployed as separate pods. The `master-worker-topologyupdater` overlay may be
-used to achieve this:
+NFD Master, NFD worker and NFD Topologyupdater can be configured to be deployed
+as separate pods. The `master-worker-topologyupdater` overlay may be used to
+achieve this:
 
 ```bash
 kubectl apply -k https://github.com/kubernetes-sigs/node-feature-discovery/deployment/overlays/master-worker-topologyupdater?ref={{ site.release }}
@@ -112,7 +112,7 @@ kubectl apply -k https://github.com/kubernetes-sigs/node-feature-discovery/deplo
 
 ### Topologyupdater
 
-In order to deploy just nfd-topology-updater (without nfd-master and nfd-worker)
+In order to deploy just NFD master and NFD Topologyupdater (without nfd-worker)
 use the `topologyupdater` overlay:
 
 ```bash
@@ -120,9 +120,10 @@ kubectl apply -k https://github.com/kubernetes-sigs/node-feature-discovery/deplo
 
 ```
 
-NFD-Topology-Updater can be configured along with the `default` overlay
-(which deploys nfd-worker and nfd-master) where all the software components
-are deployed as separate pods;
+NFD Topologyupdater can be configured along with the `default` overlay
+(which deploys NFD worker and NFD master) where all the software components
+are deployed as separate pods. The `topologyupdater` overlay may be used
+along with `default` overlay to achieve this:
 
 ```bash
 
diff --git a/docs/get-started/introduction.md b/docs/get-started/introduction.md
index 3c6cac09a..f17f13bc5 100644
--- a/docs/get-started/introduction.md
+++ b/docs/get-started/introduction.md
@@ -42,9 +42,9 @@ instance of nfd-worker is supposed to be running on each node of the cluster,
 NFD-Topology-Updater is a daemon responsible for examining allocated
 resources on a worker node to account for resources available to be allocated
 to new pod on a per-zone basis (where a zone can be a NUMA node). It then
-creates or updates a
-[NodeResourceTopology](../usage/custom-resources#noderesourcetopology) custom
-resource object specific to this node. One instance of nfd-topology-updater is
+communicates the information to nfd-master which does the
+[NodeResourceTopology CR](#noderesourcetopology-cr) creation corresponding
+to all the nodes in the cluster. One instance of nfd-topology-updater is
 supposed to be running on each node of the cluster.
 
 ## Feature Discovery
diff --git a/docs/get-started/quick-start.md b/docs/get-started/quick-start.md
index b169ca9c9..b2c234200 100644
--- a/docs/get-started/quick-start.md
+++ b/docs/get-started/quick-start.md
@@ -78,8 +78,8 @@ feature-dependent-pod   1/1     Running   0          23s   10.36.0.4   node-2
 
 ### Deploy nfd-topology-updater
 
-In order to deploy nfd-topology-updater use the `topologyupdater` kustomize
-overlay.
+In order to deploy nfd-master and nfd-topology-updater daemons
+use `topologyupdater` kustomize overlay.
 
 ```bash
 kubectl apply -k https://github.com/kubernetes-sigs/node-feature-discovery/deployment/overlays/topologyupdater?ref={{ site.release }}
@@ -87,13 +87,16 @@ kubectl apply -k https://github.com/kubernetes-sigs/node-feature-discovery/deplo
 
 ### Verify nfd-topology-updater
 
-Wait until nfd-topology-updater is running.
+Wait until NFD topologyupdater (and NFD master) are running.
 
 ```bash
-$ kubectl -n node-feature-discovery get ds
+$ kubectl -n node-feature-discovery get ds,deploy
 NAME                                  DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
 daemonset.apps/nfd-topology-updater   2         2         2       2            2           <none>          5s
 
+NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
+deployment.apps/nfd-master   1/1     1            1           17s
+
 ```
 
 Check that the NodeResourceTopology objects are created
diff --git a/docs/reference/master-commandline-reference.md b/docs/reference/master-commandline-reference.md
index 6bda05d50..aed737857 100644
--- a/docs/reference/master-commandline-reference.md
+++ b/docs/reference/master-commandline-reference.md
@@ -137,32 +137,6 @@ nfd-master -verify-node-name -ca-file=/opt/nfd/ca.crt \
     -cert-file=/opt/nfd/master.crt -key-file=/opt/nfd/master.key
 ```
 
-### -enable-nodefeature-api
-
-The `-enable-nodefeature-api` flag enables the NodeFeature CRD API for
-receiving feature requests. This will also automatically disable the gRPC
-interface.
-
-Default: false
-
-Example:
-
-```bash
-nfd-master -enable-nodefeature-api
-```
-
-### -enable-taints
-
-The `-enable-taints` flag enables/disables node tainting feature of NFD.
-
-Default: *false*
-
-Example:
-
-```bash
-nfd-master -enable-taints=true
-```
-
 ### -no-publish
 
 The `-no-publish` flag disables updates to the Node objects in the Kubernetes
@@ -177,24 +151,20 @@ Example:
 nfd-master -no-publish
 ```
 
-### -crd-controller
+### -featurerules-controller
 
-The `-crd-controller` flag specifies whether the NFD CRD API controller is
-enabled or not. The controller is responsible for processing NodeFeature and
-NodeFeatureRule objects.
+The `-featurerules-controller` flag controlers the processing of
+NodeFeatureRule objects, effectively enabling/disabling labels from these
+custom labeling rules.
 
 Default: *true*
 
 Example:
 
 ```bash
-nfd-master -crd-controller=false
+nfd-master -featurerules-controller=false
 ```
 
-### -featurerules-controller
-
-**DEPRECATED**: use [`-crd-controller`](#-crd-controller) instead.
-
 ### -label-whitelist
 
 The `-label-whitelist` specifies a regular expression for filtering feature
diff --git a/docs/reference/topology-updater-commandline-reference.md b/docs/reference/topology-updater-commandline-reference.md
index 101824a67..197d95042 100644
--- a/docs/reference/topology-updater-commandline-reference.md
+++ b/docs/reference/topology-updater-commandline-reference.md
@@ -46,6 +46,84 @@ Example:
 nfd-topology-updater -config=/opt/nfd/nfd-topology-updater.conf
 ```
 
+### -server
+
+The `-server` flag specifies the address of the nfd-master endpoint where to
+connect to.
+
+Default: localhost:8080
+
+Example:
+
+```bash
+nfd-topology-updater -server=nfd-master.nfd.svc.cluster.local:443
+```
+
+### -ca-file
+
+The `-ca-file` is one of the three flags (together with `-cert-file` and
+`-key-file`) controlling the mutual TLS authentication on the topology-updater side.
+This flag specifies the TLS root certificate that is used for verifying the
+authenticity of nfd-master.
+
+Default: *empty*
+
+Note: Must be specified together with `-cert-file` and `-key-file`
+
+Example:
+
+```bash
+nfd-topology-updater -ca-file=/opt/nfd/ca.crt -cert-file=/opt/nfd/updater.crt -key-file=/opt/nfd/updater.key
+```
+
+### -cert-file
+
+The `-cert-file` is one of the three flags (together with `-ca-file` and
+`-key-file`) controlling mutual TLS authentication on the topology-updater
+side. This flag specifies the TLS certificate presented for authenticating
+outgoing requests.
+
+Default: *empty*
+
+Note: Must be specified together with `-ca-file` and `-key-file`
+
+Example:
+
+```bash
+nfd-topology-updater -cert-file=/opt/nfd/updater.crt -key-file=/opt/nfd/updater.key -ca-file=/opt/nfd/ca.crt
+```
+
+### -key-file
+
+The `-key-file` is one of the three flags (together with `-ca-file` and
+`-cert-file`) controlling the mutual TLS authentication on topology-updater
+side. This flag specifies the private key corresponding the given certificate file
+(`-cert-file`) that is used for authenticating outgoing requests.
+
+Default: *empty*
+
+Note: Must be specified together with `-cert-file` and `-ca-file`
+
+Example:
+
+```bash
+nfd-topology-updater -key-file=/opt/nfd/updater.key -cert-file=/opt/nfd/updater.crt -ca-file=/opt/nfd/ca.crt
+```
+
+### -server-name-override
+
+The `-server-name-override` flag specifies the common name (CN) which to
+expect from the nfd-master TLS certificate. This flag is mostly intended for
+development and debugging purposes.
+
+Default: *empty*
+
+Example:
+
+```bash
+nfd-topology-updater -server-name-override=localhost
+```
+
 ### -no-publish
 
 The `-no-publish` flag disables all communication with the nfd-master, making
diff --git a/docs/reference/worker-commandline-reference.md b/docs/reference/worker-commandline-reference.md
index cf6651b8f..886faf4c7 100644
--- a/docs/reference/worker-commandline-reference.md
+++ b/docs/reference/worker-commandline-reference.md
@@ -122,22 +122,6 @@ Example:
 nfd-worker -key-file=/opt/nfd/worker.key -cert-file=/opt/nfd/worker.crt -ca-file=/opt/nfd/ca.crt
 ```
 
-### -kubeconfig
-
-The `-kubeconfig` flag specifies the kubeconfig to use for connecting to the
-Kubernetes API server. It is only needed for manipulating NodeFeature
-objects, and thus the flag only takes effect when
-[`-enable-nodefeature-api`](#-enable-nodefeature-api)) is specified. An empty
-value (which is also the default) implies in-cluster kubeconfig.
-
-Default: *empty*
-
-Example:
-
-```bash
-nfd-worker -kubeconfig ${HOME}/.kube/config
-```
-
 ### -server-name-override
 
 The `-server-name-override` flag specifies the common name (CN) which to
@@ -194,33 +178,11 @@ Example:
 nfd-worker -label-sources=kernel,system,local
 ```
 
-### -enable-nodefeature-api
-
-The `-enable-nodefeature-api` flag enables the experimental NodeFeature CRD API
-for communicating with nfd-master. This will also automatically disable the
-gRPC communication to nfd-master. When enabled, nfd-worker will create per-node
-NodeFeature objects the contain all discovered node features and the set of
-feature labels to be created.
-
-Default: false
-
-Example:
-
-```bash
-nfd-worker -enable-nodefeature-api
-```
-
 ### -no-publish
 
-The `-no-publish` flag disables all communication with the nfd-master and the
-Kubernetes API server. It is effectively a "dry-run" flag for nfd-worker.
-NFD-Worker runs feature detection normally, but no labeling requests are sent
-to nfd-master and no NodeFeature objects are created or updated in the API
-server.
-
-Note: This flag takes precedence over the
-[`core.noPublish`](worker-configuration-reference#corenopublish)
-configuration file option.
+The `-no-publish` flag disables all communication with the nfd-master, making
+it a "dry-run" flag for nfd-worker. NFD-Worker runs feature detection normally,
+but no labeling requests are sent to nfd-master.
 
 Default: *false*
 
diff --git a/docs/reference/worker-configuration-reference.md b/docs/reference/worker-configuration-reference.md
index 48b13307c..5dd239e81 100644
--- a/docs/reference/worker-configuration-reference.md
+++ b/docs/reference/worker-configuration-reference.md
@@ -131,14 +131,10 @@ core:
 ### core.noPublish
 
 Setting `core.noPublish` to `true` disables all communication with the
-nfd-master and the Kubernetes API server. It is effectively a "dry-run" option.
-NFD-Worker runs feature detection normally, but no labeling requests are sent
-to nfd-master and no NodeFeature objects are created or updated in the API
-server.
-
-Note: Overridden by the
-[`-no-publish`](worker-commandline-reference#-no-publish) command line flag (if
-specified).
+nfd-master. It is effectively a "dry-run" flag: nfd-worker runs feature
+detection normally, but no labeling requests are sent to nfd-master.
+
+Note: Overridden by the `-no-publish` command line flag (if specified).
 
 Default: `false`
 
diff --git a/docs/usage/customization-guide.md b/docs/usage/customization-guide.md
index a9dba14eb..f6ad998a8 100644
--- a/docs/usage/customization-guide.md
+++ b/docs/usage/customization-guide.md
@@ -30,8 +30,8 @@ labeling:
 ## NodeFeatureRule custom resource
 
 `NodeFeatureRule` objects provide an easy way to create vendor or application
-specific labels and taints. It uses a flexible rule-based mechanism for creating
-labels and optionally taints based on node features.
+specific labels. It uses a flexible rule-based mechanism for creating labels
+based on node feature.
 
 ### A NodeFeatureRule example
 
@@ -76,54 +76,6 @@ re-labeling delay up to the sleep-interval of nfd-worker (1 minute by default).
 
 See [Label rule format](#label-rule-format) for detailed description of
 available fields and how to write labeling rules.
-### NodeFeatureRule tainting feature
-
-This feature is experimental.
-
-In some circumstances it is desirable keep nodes with specialized hardware away from
-running general workload and instead leave them for workloads that need the specialized
-hardware. One way to achieve it is to taint the nodes with the specialized hardware
-and add corresponding toleration to pods that require the special hardware. NFD
-offers node tainting functionality which is disabled by default. User can define
-one or more custom taints via the `taints` field of the NodeFeatureRule CR. The
-same rule-based mechanism is applied here and the NFD taints only rule matching nodes.
-
-To enable the tainting feature, `--enable-taints` flag needs to be set to `true`.
-If the flag `--enable-taints` is set to `false` (i.e. disabled), taints defined in
-the NodeFeatureRule CR have no effect and will be ignored by the NFD master.
-
-**NOTE**: Before enabling any taints, make sure to edit nfd-worker daemonset to
-tolerate the taints to be created. Otherwise, already running pods that do not
-tolerate the taint are evicted immediately from the node including the nfd-worker
-pod.
-
-Example NodeFeatureRule with custom taints:
-
-```yaml
-apiVersion: nfd.k8s-sigs.io/v1alpha1
-kind: NodeFeatureRule
-metadata:
-  name: my-sample-rule-object
-spec:
-  rules:
-    - name: "my sample taint rule"
-      taints:
-        - effect: PreferNoSchedule
-          key: "feature.node.kubernetes.io/special-node"
-          value: "true"
-        - effect: NoExecute
-          key: "feature.node.kubernetes.io/dedicated-node"
-      matchFeatures:
-        - feature: kernel.loadedmodule
-          matchExpressions:
-            dummy: {op: Exists}
-        - feature: kernel.config
-          matchExpressions:
-            X86: {op: In, value: ["y"]}
-```
-
-In this example, if the `my sample taint rule` rule is matched, `feature.node.kubernetes.io/pci-0300_1d0f.present=true:NoExecute`
-and `feature.node.kubernetes.io/cpu-cpuid.ADX:NoExecute` taints are set on the node.
 
 ### NodeFeatureRule controller
 
@@ -413,15 +365,6 @@ details.
 labels specified in the `labels` field will override anything
 originating from `labelsTemplate`.
 
-### Taints
-
-*taints* is a list of taint entries and each entry can have `key`, `value` and `effect`,
-where the `value` is optional. Effect could be `NoSchedule`, `PreferNoSchedule`
-or `NoExecute`. To learn more about the meaning of these effects, check out k8s [documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/).
-
-**NOTE** taints field is not available for the custom rules of nfd-worker and only
-for NodeFeatureRule objects.
-
 #### Vars
 
 The `.vars` field is a map of values (key-value pairs) to store for subsequent
diff --git a/docs/usage/features.md b/docs/usage/features.md
index 56b61478a..24797e8aa 100644
--- a/docs/usage/features.md
+++ b/docs/usage/features.md
@@ -79,7 +79,6 @@ configuration options for details.
 | AVXVNNI            | AVX (VEX encoded) VNNI neural network instructions
 | AMXBF16            | Advanced Matrix Extension, tile multiplication operations on BFLOAT16 numbers
 | AMXINT8            | Advanced Matrix Extension, tile multiplication operations on 8-bit integers
-| AMXFP16            | Advanced Matrix Extension, tile multiplication operations on FP16 numbers
 | AMXTILE            | Advanced Matrix Extension, base tile architecture support
 | AVX512BF16         | AVX-512 BFLOAT16 instructions
 | AVX512BITALG       | AVX-512 bit Algorithms
@@ -100,7 +99,6 @@ configuration options for details.
 | ENQCMD             | Enqueue Command
 | GFNI               | Galois Field New Instructions
 | HYPERVISOR         | Running under hypervisor
-| PREFETCHI          | PREFETCHIT0/1 instructions
 | VAES               | AVX-512 vector AES instructions
 | VPCLMULQDQ         | Carry-less multiplication quadword
 
diff --git a/docs/usage/nfd-topology-updater.md b/docs/usage/nfd-topology-updater.md
index c4a6b1be1..bb2ad7f1f 100644
--- a/docs/usage/nfd-topology-updater.md
+++ b/docs/usage/nfd-topology-updater.md
@@ -10,11 +10,11 @@ sort: 5
 ---
 
 NFD-Topology-Updater is preferably run as a Kubernetes DaemonSet. This assures
-re-examination on regular intervals, capturing changes in the allocated
-resources and hence the allocatable resources on a per zone basis by updating
-[NodeResourceTopology](custom-resources#noderesourcetopology) custom resources.
-It makes sure that new NodeResourceTopology instances are created for each new
-nodes that get added to the cluster.
+re-examination (and CR updates) on regular intervals capturing changes in
+the allocated resources and hence the allocatable resources on a per zone
+basis. It makes sure that more CR instances are created as new nodes get
+added to the cluster. Topology-Updater connects to the nfd-master service
+to create CR instances corresponding to nodes.
 
 When run as a daemonset, nodes are re-examined for the allocated resources
 (to determine the information of the allocatable resources on a per zone basis
diff --git a/go.mod b/go.mod
index bc723481c..074e4dae8 100644
--- a/go.mod
+++ b/go.mod
@@ -3,34 +3,33 @@ module sigs.k8s.io/node-feature-discovery
 go 1.19
 
 require (
-	github.com/fsnotify/fsnotify v1.6.0
+	github.com/fsnotify/fsnotify v1.4.9
 	github.com/ghodss/yaml v1.0.0
 	github.com/gogo/protobuf v1.3.2
 	github.com/golang/protobuf v1.5.2
-	github.com/google/go-cmp v0.5.9
+	github.com/google/go-cmp v0.5.8
 	github.com/jaypipes/ghw v0.8.1-0.20210827132705-c7224150a17e
 	github.com/k8stopologyawareschedwg/noderesourcetopology-api v0.0.12
-	github.com/klauspost/cpuid/v2 v2.2.2
-	github.com/onsi/ginkgo/v2 v2.4.0
-	github.com/onsi/gomega v1.23.0
+	github.com/klauspost/cpuid/v2 v2.1.0
+	github.com/onsi/ginkgo/v2 v2.3.1
+	github.com/onsi/gomega v1.22.1
 	github.com/smartystreets/assertions v1.2.0
 	github.com/smartystreets/goconvey v1.6.4
 	github.com/stretchr/testify v1.8.0
 	github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a
-	golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10
-	google.golang.org/grpc v1.49.0
-	google.golang.org/protobuf v1.28.1
-	k8s.io/api v0.26.0
-	k8s.io/apiextensions-apiserver v0.26.0
-	k8s.io/apimachinery v0.26.0
-	k8s.io/client-go v0.26.0
-	k8s.io/klog/v2 v2.80.1
-	k8s.io/kubectl v0.26.0
-	k8s.io/kubelet v0.26.0
-	k8s.io/kubernetes v1.26.0
-	k8s.io/pod-security-admission v0.0.0
-	k8s.io/utils v0.0.0-20221128185143-99ec85e7a448
-	sigs.k8s.io/yaml v1.3.0
+	golang.org/x/net v0.0.0-20220722155237-a158d28d115b
+	google.golang.org/grpc v1.47.0
+	google.golang.org/protobuf v1.28.0
+	k8s.io/api v0.25.3
+	k8s.io/apiextensions-apiserver v0.25.3
+	k8s.io/apimachinery v0.25.3
+	k8s.io/client-go v0.25.3
+	k8s.io/klog/v2 v2.70.1
+	k8s.io/kubectl v0.25.3
+	k8s.io/kubelet v0.25.3
+	k8s.io/kubernetes v1.25.3
+	k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
+	sigs.k8s.io/yaml v1.2.0
 )
 
 require (
@@ -50,68 +49,72 @@ require (
 	github.com/Microsoft/go-winio v0.4.17 // indirect
 	github.com/Microsoft/hcsshim v0.8.22 // indirect
 	github.com/NYTimes/gziphandler v1.1.1 // indirect
+	github.com/PuerkitoBio/purell v1.1.1 // indirect
+	github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
 	github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
-	github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
 	github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e // indirect
-	github.com/aws/aws-sdk-go v1.44.116 // indirect
+	github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
+	github.com/aws/aws-sdk-go v1.38.49 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/blang/semver/v4 v4.0.0 // indirect
-	github.com/cenkalti/backoff/v4 v4.1.3 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/checkpoint-restore/go-criu/v5 v5.3.0 // indirect
 	github.com/cilium/ebpf v0.7.0 // indirect
-	github.com/container-storage-interface/spec v1.7.0 // indirect
+	github.com/container-storage-interface/spec v1.6.0 // indirect
 	github.com/containerd/cgroups v1.0.1 // indirect
 	github.com/containerd/console v1.0.3 // indirect
-	github.com/containerd/ttrpc v1.1.0 // indirect
+	github.com/containerd/ttrpc v1.0.2 // indirect
 	github.com/coreos/go-semver v0.3.0 // indirect
 	github.com/coreos/go-systemd/v22 v22.3.2 // indirect
 	github.com/cyphar/filepath-securejoin v0.2.3 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/docker/distribution v2.8.1+incompatible // indirect
-	github.com/docker/go-units v0.5.0 // indirect
-	github.com/emicklei/go-restful/v3 v3.9.0 // indirect
+	github.com/docker/go-units v0.4.0 // indirect
+	github.com/emicklei/go-restful/v3 v3.8.0 // indirect
 	github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect
 	github.com/evanphx/json-patch v4.12.0+incompatible // indirect
-	github.com/felixge/httpsnoop v1.0.3 // indirect
+	github.com/felixge/httpsnoop v1.0.1 // indirect
+	github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
 	github.com/go-logr/logr v1.2.3 // indirect
-	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/go-ole/go-ole v1.2.4 // indirect
 	github.com/go-openapi/jsonpointer v0.19.5 // indirect
-	github.com/go-openapi/jsonreference v0.20.0 // indirect
+	github.com/go-openapi/jsonreference v0.19.5 // indirect
 	github.com/go-openapi/swag v0.19.14 // indirect
+	github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect
 	github.com/godbus/dbus/v5 v5.0.6 // indirect
 	github.com/gofrs/uuid v4.0.0+incompatible // indirect
 	github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/mock v1.6.0 // indirect
-	github.com/google/cadvisor v0.46.0 // indirect
-	github.com/google/cel-go v0.12.5 // indirect
+	github.com/google/cadvisor v0.45.0 // indirect
 	github.com/google/gnostic v0.5.7-v3refs // indirect
 	github.com/google/gofuzz v1.1.0 // indirect
 	github.com/google/uuid v1.1.2 // indirect
 	github.com/googleapis/gax-go/v2 v2.1.1 // indirect
+	github.com/gophercloud/gophercloud v0.1.0 // indirect
 	github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
+	github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
+	github.com/heketi/heketi v10.3.0+incompatible // indirect
 	github.com/imdario/mergo v0.3.6 // indirect
-	github.com/inconshreveable/mousetrap v1.0.1 // indirect
+	github.com/inconshreveable/mousetrap v1.0.0 // indirect
 	github.com/jaypipes/pcidb v0.6.0 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/jtolds/gls v4.20.0+incompatible // indirect
-	github.com/karrick/godirwalk v1.17.0 // indirect
+	github.com/karrick/godirwalk v1.16.1 // indirect
 	github.com/libopenstorage/openstorage v1.0.0 // indirect
 	github.com/lithammer/dedent v1.1.0 // indirect
 	github.com/mailru/easyjson v0.7.6 // indirect
-	github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
+	github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
 	github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 // indirect
 	github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
+	github.com/mitchellh/mapstructure v1.4.1 // indirect
 	github.com/moby/ipvs v1.0.1 // indirect
 	github.com/moby/spdystream v0.2.0 // indirect
-	github.com/moby/sys/mountinfo v0.6.2 // indirect
+	github.com/moby/sys/mountinfo v0.6.0 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb // indirect
@@ -119,50 +122,50 @@ require (
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
 	github.com/opencontainers/go-digest v1.0.0 // indirect
-	github.com/opencontainers/runc v1.1.4 // indirect
+	github.com/opencontainers/runc v1.1.3 // indirect
 	github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect
 	github.com/opencontainers/selinux v1.10.0 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/prometheus/client_golang v1.14.0 // indirect
-	github.com/prometheus/client_model v0.3.0 // indirect
-	github.com/prometheus/common v0.37.0 // indirect
-	github.com/prometheus/procfs v0.8.0 // indirect
+	github.com/prometheus/client_golang v1.12.1 // indirect
+	github.com/prometheus/client_model v0.2.0 // indirect
+	github.com/prometheus/common v0.32.1 // indirect
+	github.com/prometheus/procfs v0.7.3 // indirect
 	github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 // indirect
 	github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 // indirect
 	github.com/sirupsen/logrus v1.8.1 // indirect
-	github.com/spf13/cobra v1.6.0 // indirect
+	github.com/spf13/cobra v1.4.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
-	github.com/stoewer/go-strcase v1.2.0 // indirect
 	github.com/stretchr/objx v0.4.0 // indirect
 	github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
 	github.com/vishvananda/netlink v1.1.0 // indirect
 	github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
 	github.com/vmware/govmomi v0.20.3 // indirect
-	go.etcd.io/etcd/api/v3 v3.5.5 // indirect
-	go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect
-	go.etcd.io/etcd/client/v3 v3.5.5 // indirect
+	go.etcd.io/etcd/api/v3 v3.5.4 // indirect
+	go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
+	go.etcd.io/etcd/client/v3 v3.5.4 // indirect
 	go.opencensus.io v0.23.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.35.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0 // indirect
-	go.opentelemetry.io/otel v1.10.0 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 // indirect
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 // indirect
-	go.opentelemetry.io/otel/metric v0.31.0 // indirect
-	go.opentelemetry.io/otel/sdk v1.10.0 // indirect
-	go.opentelemetry.io/otel/trace v1.10.0 // indirect
-	go.opentelemetry.io/proto/otlp v0.19.0 // indirect
+	go.opentelemetry.io/contrib v0.20.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.20.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect
+	go.opentelemetry.io/otel v0.20.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
+	go.opentelemetry.io/otel/metric v0.20.0 // indirect
+	go.opentelemetry.io/otel/sdk v0.20.0 // indirect
+	go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect
+	go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
+	go.opentelemetry.io/otel/trace v0.20.0 // indirect
+	go.opentelemetry.io/proto/otlp v0.7.0 // indirect
 	go.uber.org/atomic v1.7.0 // indirect
 	go.uber.org/multierr v1.6.0 // indirect
 	go.uber.org/zap v1.19.0 // indirect
-	golang.org/x/crypto v0.1.0 // indirect
-	golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
+	golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
+	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
 	golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
-	golang.org/x/sys v0.3.0 // indirect
-	golang.org/x/term v0.3.0 // indirect
-	golang.org/x/text v0.5.0 // indirect
+	golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
+	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
+	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
 	google.golang.org/api v0.60.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
@@ -174,19 +177,18 @@ require (
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
-	k8s.io/apiserver v0.26.0 // indirect
-	k8s.io/cloud-provider v0.26.0 // indirect
-	k8s.io/component-base v0.26.0 // indirect
-	k8s.io/component-helpers v0.26.0 // indirect
+	k8s.io/apiserver v0.25.0 // indirect
+	k8s.io/cloud-provider v0.25.0 // indirect
+	k8s.io/component-base v0.25.0 // indirect
+	k8s.io/component-helpers v0.25.0 // indirect
 	k8s.io/cri-api v0.0.0 // indirect
-	k8s.io/csi-translation-lib v0.26.0 // indirect
-	k8s.io/dynamic-resource-allocation v0.26.0 // indirect
-	k8s.io/kms v0.26.0 // indirect
-	k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
+	k8s.io/csi-translation-lib v0.25.0 // indirect
+	k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
 	k8s.io/kube-proxy v0.0.0 // indirect
 	k8s.io/kube-scheduler v0.0.0 // indirect
 	k8s.io/legacy-cloud-providers v0.0.0 // indirect
 	k8s.io/mount-utils v0.25.0 // indirect
+	k8s.io/pod-security-admission v0.0.0 // indirect
 	sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 // indirect
 	sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
@@ -196,29 +198,29 @@ require (
 // need to override with commits (corresponding their kubernetes-* tags)
 replace (
 	github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
-	k8s.io/api => k8s.io/api v0.26.0
-	k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.0
-	k8s.io/apimachinery => k8s.io/apimachinery v0.26.0
-	k8s.io/apiserver => k8s.io/apiserver v0.26.0
-	k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.0
-	k8s.io/client-go => k8s.io/client-go v0.26.0
-	k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.0
-	k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.0
-	k8s.io/code-generator => k8s.io/code-generator v0.26.0
-	k8s.io/component-base => k8s.io/component-base v0.26.0
-	k8s.io/component-helpers => k8s.io/component-helpers v0.26.0
-	k8s.io/controller-manager => k8s.io/controller-manager v0.26.0
-	k8s.io/cri-api => k8s.io/cri-api v0.26.0
-	k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.0
-	k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.0
-	k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.0
-	k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.0
-	k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.0
-	k8s.io/kubectl => k8s.io/kubectl v0.26.0
-	k8s.io/kubelet => k8s.io/kubelet v0.26.0
-	k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.0
-	k8s.io/metrics => k8s.io/metrics v0.26.0
-	k8s.io/mount-utils => k8s.io/mount-utils v0.26.0
-	k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.26.0
-	k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.0
+	k8s.io/api => k8s.io/api v0.25.0
+	k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.25.0
+	k8s.io/apimachinery => k8s.io/apimachinery v0.25.0
+	k8s.io/apiserver => k8s.io/apiserver v0.25.0
+	k8s.io/cli-runtime => k8s.io/cli-runtime v0.25.0
+	k8s.io/client-go => k8s.io/client-go v0.25.0
+	k8s.io/cloud-provider => k8s.io/cloud-provider v0.25.0
+	k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.25.0
+	k8s.io/code-generator => k8s.io/code-generator v0.25.0
+	k8s.io/component-base => k8s.io/component-base v0.25.0
+	k8s.io/component-helpers => k8s.io/component-helpers v0.25.0
+	k8s.io/controller-manager => k8s.io/controller-manager v0.25.0
+	k8s.io/cri-api => k8s.io/cri-api v0.25.0
+	k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.25.0
+	k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.25.0
+	k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.25.0
+	k8s.io/kube-proxy => k8s.io/kube-proxy v0.25.0
+	k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.25.0
+	k8s.io/kubectl => k8s.io/kubectl v0.25.0
+	k8s.io/kubelet => k8s.io/kubelet v0.25.0
+	k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.25.0
+	k8s.io/metrics => k8s.io/metrics v0.25.0
+	k8s.io/mount-utils => k8s.io/mount-utils v0.25.0
+	k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.25.0
+	k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.25.0
 )
diff --git a/go.sum b/go.sum
index 60f8d38c7..84056b467 100644
--- a/go.sum
+++ b/go.sum
@@ -86,7 +86,9 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
 github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
 github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
 github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
@@ -96,8 +98,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
 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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
+github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed h1:ue9pVfIcP+QMEjfgo/Ez4ZjNZfonGgR6NgjMaJMu1Cg=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -105,9 +106,11 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/auth0/go-jwt-middleware v1.0.1 h1:/fsQ4vRr4zod1wKReUH+0A3ySRjGiT9G34kypO/EKwI=
 github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
-github.com/aws/aws-sdk-go v1.44.116 h1:NpLIhcvLWXJZAEwvPj3TDHeqp7DleK6ZUVYyW01WNHY=
-github.com/aws/aws-sdk-go v1.44.116/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
+github.com/aws/aws-sdk-go v1.38.49 h1:E31vxjCe6a5I+mJLmUGaZobiWmg9KdWaud9IfceYeYQ=
+github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
+github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
 github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
 github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -118,8 +121,7 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn
 github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
 github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
 github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
-github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
-github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
+github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -140,12 +142,11 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
 github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/container-storage-interface/spec v1.7.0 h1:gW8eyFQUZWWrMWa8p1seJ28gwDoN5CVJ4uAbQ+Hdycw=
-github.com/container-storage-interface/spec v1.7.0/go.mod h1:JYuzLqr9VVNoDJl44xp/8fmCOvWPDKzuGTwCoklhuqk=
+github.com/container-storage-interface/spec v1.6.0 h1:vwN9uCciKygX/a0toYryoYD5+qI9ZFeAMuhEEKO+JBA=
+github.com/container-storage-interface/spec v1.6.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s=
 github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
 github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
 github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
@@ -156,9 +157,8 @@ github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX
 github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
 github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
 github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
+github.com/containerd/ttrpc v1.0.2 h1:2/O3oTZN36q2xRolk0a2WWGgh7/Vf/liElg5hFYLX9U=
 github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
-github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI=
-github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
 github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY=
 github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -173,7 +173,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
@@ -183,24 +183,23 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
-github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
+github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
 github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
 github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v20.10.18+incompatible h1:SN84VYXTBNGn92T/QwIRPlum9zfemfitN7pbsp26WSc=
-github.com/docker/docker v20.10.18+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
+github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
 github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
-github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
 github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+github.com/emicklei/go-restful/v3 v3.5.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
 github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
-github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 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=
@@ -208,7 +207,6 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
 github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
-github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/euank/go-kmsg-parser v2.0.0+incompatible h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY=
@@ -217,15 +215,16 @@ github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH
 github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
 github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
-github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
-github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
+github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
+github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
 github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
@@ -235,30 +234,27 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
-github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
 github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
-github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
 github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
 github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
 github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
-github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
-github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
+github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
+github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
 github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-ozzo/ozzo-validation v3.5.0+incompatible h1:sUy/in/P6askYr16XJgTKq/0SZhiWsdg4WZGaLsGQkM=
+github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -274,8 +270,6 @@ github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
 github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
 github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
-github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -315,10 +309,9 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
 github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
-github.com/google/cadvisor v0.46.0 h1:ryTIniqhN8/wR8UA1RuYSXHvsAtdpk/01XwTZtYHekY=
-github.com/google/cadvisor v0.46.0/go.mod h1:YnCDnR8amaS0HoMEjheOI0TMPzFKCBLc30mciLEjwGI=
+github.com/google/cadvisor v0.45.0 h1:bXQze1sd8srZiQwiQ19Qaq/AoMIZS8YceBXrIaEvkX0=
+github.com/google/cadvisor v0.45.0/go.mod h1:vsMT3Uv2XjQ8M7WUtKARV74mU/HN64C4XtM1bJhUKcU=
 github.com/google/cel-go v0.12.5 h1:DmzaiSgoaqGCjtpPQWl26/gND+yRpim56H1jCVev6d8=
-github.com/google/cel-go v0.12.5/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw=
 github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
 github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -333,9 +326,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
 github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 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=
@@ -367,9 +359,13 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
 github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
 github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU=
 github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
+github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
+github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -382,19 +378,19 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/heketi/heketi v10.3.0+incompatible h1:X4DBFPzcyWZWhia32d94UhDECQJHH0M5kpRb1gxxUHk=
+github.com/heketi/heketi v10.3.0+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o=
+github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6 h1:oJ/NLadJn5HoxvonA6VxG31lg0d6XOURNA09BTtM4fY=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
 github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/jaypipes/ghw v0.8.1-0.20210827132705-c7224150a17e h1:XTXPzmyiwx2uxk8JaU4mxmBZ+rzZtmEwkNm9H9ETzV0=
 github.com/jaypipes/ghw v0.8.1-0.20210827132705-c7224150a17e/go.mod h1:+gR9bjm3W/HnFi90liF+Fj9GpCe/Dsibl9Im8KmC7c4=
 github.com/jaypipes/pcidb v0.6.0 h1:VIM7GKVaW4qba30cvB67xSCgJPTzkG8Kzw/cbs5PHWU=
@@ -422,12 +418,12 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/k8stopologyawareschedwg/noderesourcetopology-api v0.0.12 h1:NhXbOjO1st8hIcVpegr3zw/AGG12vs3z//tCDDcfPpE=
 github.com/k8stopologyawareschedwg/noderesourcetopology-api v0.0.12/go.mod h1:AkACMQGiTgCt0lQw3m7TTU8PLH9lYKNK5e9DqFf5VuM=
-github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI=
-github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
+github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
+github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/cpuid/v2 v2.2.2 h1:xPMwiykqNK9VK0NYC3+jTMYv9I6Vl3YdjZgPZKG3zO0=
-github.com/klauspost/cpuid/v2 v2.2.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
+github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -445,14 +441,15 @@ github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wn
 github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
 github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
 github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
+github.com/lpabon/godbc v0.1.1 h1:ilqjArN1UOENJJdM34I2YHKmF/B0gGq4VLoSGy9iAao=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
 github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
-github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
+github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 h1:PS1dLCGtD8bb9RPKJrc8bS7qHL6JnW1CZvwzH9dPoUs=
 github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY=
 github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1:aKW/4cBs+yK6gpqU3K/oIwk9Q/XICqd3zOX/UFuvqmk=
@@ -463,15 +460,16 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
 github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/moby/ipvs v1.0.1 h1:aoZ7fhLTXgDbzVrAnvV+XbKOU8kOET7B3+xULDF/1o0=
 github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ=
 github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
 github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
 github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
-github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
-github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
-github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI=
-github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
+github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo=
+github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
+github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=
+github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -502,25 +500,20 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
 github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
 github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
 github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
-github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
-github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
-github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
-github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
+github.com/onsi/ginkgo/v2 v2.3.1 h1:8SbseP7qM32WcvE6VaN6vfXxv698izmsJ1UQX9ve7T8=
+github.com/onsi/ginkgo/v2 v2.3.1/go.mod h1:Sv4yQXwG5VmF7tm3Q5Z+RWUpPo24LF1mpnz2crUb8Ys=
 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.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
 github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
-github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
-github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
+github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI=
 github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
-github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
-github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
 github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg=
-github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
+github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
+github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
 github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
@@ -542,41 +535,36 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
 github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
 github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
-github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
-github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
-github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
 github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
 github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
 github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
-github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
-github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 h1:if3/24+h9Sq6eDx8UUz1SO9cT9tizyIsATfB7b4D3tc=
 github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
+github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 h1:RpforrEYXWkmGwJHIGnLZ3tTWStkjVVstwzNGqxX2Ds=
 github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
@@ -598,11 +586,12 @@ github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
+github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
-github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
-github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
+github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
+github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -631,6 +620,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
 github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a h1:lUVfiMMY/te9icPKBqOKkBIMZNxSpM90dxokDeCcfBg=
 github.com/vektra/errors v0.0.0-20140903201135-c64d83aba85a/go.mod h1:KUxJS71XlMs+ztT+RzsLRoWUQRUpECo/+Rb0EBk8/Wc=
 github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
@@ -653,16 +643,16 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
-go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0=
-go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
-go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8=
-go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
-go.etcd.io/etcd/client/v2 v2.305.5 h1:DktRP60//JJpnPC0VBymAN/7V71GHMdjDCBt4ZPXDjI=
-go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI=
-go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c=
-go.etcd.io/etcd/pkg/v3 v3.5.5 h1:Ablg7T7OkR+AeeeU32kdVhw/AGDsitkKPl7aW73ssjU=
-go.etcd.io/etcd/raft/v3 v3.5.5 h1:Ibz6XyZ60OYyRopu73lLM/P+qco3YtlZMOhnXNS051I=
-go.etcd.io/etcd/server/v3 v3.5.5 h1:jNjYm/9s+f9A9r6+SC4RvNaz6AqixpOvhrFdT0PvIj0=
+go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc=
+go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
+go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg=
+go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/v2 v2.305.4 h1:Dcx3/MYyfKcPNLpR4VVQUP5KgYrBeJtktBwEKkw08Ao=
+go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4=
+go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
+go.etcd.io/etcd/pkg/v3 v3.5.4 h1:V5Dvl7S39ZDwjkKqJG2BfXgxZ3QREqqKifWQgIw5IM0=
+go.etcd.io/etcd/raft/v3 v3.5.4 h1:YGrnAgRfgXloBNuqa+oBI/aRZMcK/1GS6trJePJ/Gqc=
+go.etcd.io/etcd/server/v3 v3.5.4 h1:CMAZd0g8Bn5NRhynW6pKhc4FRg41/0QYy3d7aNm9874=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -671,30 +661,34 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
 go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
 go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.35.0 h1:KQjX0qQ8H21oBUAvFp4ZLKJMMLIluONvSPDAFIGmX58=
-go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.35.0/go.mod h1:DQYkU9srMFqLUTVA/7/WlRHdnYDB7wyMMlle2ktMjfI=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0 h1:Ajldaqhxqw/gNzQA45IKFWLdG7jZuXX/wBW1d5qvbUI=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c=
-go.opentelemetry.io/contrib/propagators/b3 v1.10.0 h1:6AD2VV8edRdEYNaD8cNckpzgdMLU2kbV9OYyxt2kvCg=
-go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4=
-go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ=
-go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y=
-go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0=
-go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs=
-go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A=
-go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY=
-go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE=
-go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E=
-go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM=
+go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0=
+go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
+go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.20.0 h1:8YW+SL62UmcwRQJFZVfnyOlIUUtmlR13NaMKi+Fa6Fo=
+go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.20.0/go.mod h1:oQkZOyq61qZBItEFqhfpobK6X/oDPR7/Qr+MXjVSTks=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
+go.opentelemetry.io/contrib/propagators v0.20.0 h1:IrLQng5Z7AfzkS4sEsYaj2ejkO4FCkgKdAr1aYKOfNc=
+go.opentelemetry.io/contrib/propagators v0.20.0/go.mod h1:yLmt93MeSiARUwrK57bOZ4FBruRN4taLiW1lcGfnOes=
+go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g=
+go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
+go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg=
+go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
+go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8=
+go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
+go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw=
+go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
+go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8=
+go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
+go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g=
+go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
+go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8=
+go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
+go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw=
+go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
+go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
-go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
 go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
@@ -709,6 +703,7 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
 go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 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=
@@ -716,8 +711,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
-golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -755,7 +750,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
 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=
@@ -803,13 +797,9 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
-golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc=
-golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
 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/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -826,9 +816,8 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
 golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg=
-golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
 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=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -840,7 +829,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -848,6 +836,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -919,19 +908,13 @@ golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
-golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
-golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
 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=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -940,10 +923,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
-golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1009,7 +990,6 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1112,7 +1092,6 @@ google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEc
 google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
 google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I=
 google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1141,11 +1120,9 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
 google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
 google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
 google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw=
-google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
+google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
+google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 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=
@@ -1160,9 +1137,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 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=
@@ -1209,65 +1185,61 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
 howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
-k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I=
-k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg=
-k8s.io/apiextensions-apiserver v0.26.0 h1:Gy93Xo1eg2ZIkNX/8vy5xviVSxwQulsnUdQ00nEdpDo=
-k8s.io/apiextensions-apiserver v0.26.0/go.mod h1:7ez0LTiyW5nq3vADtK6C3kMESxadD51Bh6uz3JOlqWQ=
-k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg=
-k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
-k8s.io/apiserver v0.26.0 h1:q+LqIK5EZwdznGZb8bq0+a+vCqdeEEe4Ux3zsOjbc4o=
-k8s.io/apiserver v0.26.0/go.mod h1:aWhlLD+mU+xRo+zhkvP/gFNbShI4wBDHS33o0+JGI84=
-k8s.io/cli-runtime v0.26.0 h1:aQHa1SyUhpqxAw1fY21x2z2OS5RLtMJOCj7tN4oq8mw=
-k8s.io/client-go v0.26.0 h1:lT1D3OfO+wIi9UFolCrifbjUUgu7CpLca0AD8ghRLI8=
-k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg=
-k8s.io/cloud-provider v0.26.0 h1:kO2BIgCou71QNRHGkpFi/8lnas9UIr+fJz1l/nuiOMo=
-k8s.io/cloud-provider v0.26.0/go.mod h1:JwfUAH67C8f7t6tOC4v4ty+DuvIYVjNF6bGVYSDCqqs=
-k8s.io/cluster-bootstrap v0.26.0 h1:jd6T3WmpZo6TpmIHqg1wc4bX/BLsGC8Tzle/VKI9vRo=
-k8s.io/code-generator v0.26.0/go.mod h1:OMoJ5Dqx1wgaQzKgc+ZWaZPfGjdRq/Y3WubFrZmeI3I=
-k8s.io/component-base v0.26.0 h1:0IkChOCohtDHttmKuz+EP3j3+qKmV55rM9gIFTXA7Vs=
-k8s.io/component-base v0.26.0/go.mod h1:lqHwlfV1/haa14F/Z5Zizk5QmzaVf23nQzCwVOQpfC8=
-k8s.io/component-helpers v0.26.0 h1:KNgwqs3EUdK0HLfW4GhnbD+q/Zl9U021VfIU7qoVYFk=
-k8s.io/component-helpers v0.26.0/go.mod h1:jHN01qS/Jdj95WCbTe9S2VZ9yxpxXNY488WjF+yW4fo=
-k8s.io/cri-api v0.26.0 h1:/Cfs9BUtGwYWjRCscd/4q+uJ0UqCzwcIZDI+Eyvle78=
-k8s.io/cri-api v0.26.0/go.mod h1:I5TGOn/ziMzqIcUvsYZzVE8xDAB1JBkvcwvR0yDreuw=
-k8s.io/csi-translation-lib v0.26.0 h1:bCvlfw53Kmyn7cvXeYGe9aqqzR1b0xrGs2XEWHFW+es=
-k8s.io/csi-translation-lib v0.26.0/go.mod h1:zRKLRqER6rA8NCKQBhVIdkyDHKgNlu2BK1RKTHjcw+8=
-k8s.io/dynamic-resource-allocation v0.26.0 h1:zljrsqa0PxrIwNklTnGBA/az6+33SUQwsNNNKdVTzwg=
-k8s.io/dynamic-resource-allocation v0.26.0/go.mod h1:K+hO5A+QsSknRjlhfbUtvZVYUblOldvYyT51eGrZyWI=
+k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0=
+k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk=
+k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY=
+k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E=
+k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU=
+k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0=
+k8s.io/apiserver v0.25.0 h1:8kl2ifbNffD440MyvHtPaIz1mw4mGKVgWqM0nL+oyu4=
+k8s.io/apiserver v0.25.0/go.mod h1:BKwsE+PTC+aZK+6OJQDPr0v6uS91/HWxX7evElAH6xo=
+k8s.io/cli-runtime v0.25.0 h1:XBnTc2Fi+w818jcJGzhiJKQuXl8479sZ4FhtV5hVJ1Q=
+k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E=
+k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8=
+k8s.io/cloud-provider v0.25.0 h1:ONX5BON6f1Mxa2GWvPyKn+QsZXaLauPUte7MZxfWUro=
+k8s.io/cloud-provider v0.25.0/go.mod h1:afVfVCIYOUER914WmSp0QpAtJn12gv4qu9NMT4XBxZo=
+k8s.io/cluster-bootstrap v0.25.0 h1:KJ2/r0dV+bLfTK5EBobAVKvjGel3N4Qqh3bvnzh9qPk=
+k8s.io/code-generator v0.25.0/go.mod h1:B6jZgI3DvDFAualltPitbYMQ74NjaCFxum3YeKZZ+3w=
+k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y=
+k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk=
+k8s.io/component-helpers v0.25.0 h1:vNzYfqnVXj7f+CPksduKVv2Z9kC+IDsOs9yaOyxZrj0=
+k8s.io/component-helpers v0.25.0/go.mod h1:auaFj2bvb5Zmy0mLk4WJNmwP0w4e7Zk+/Tu9FFBGA20=
+k8s.io/cri-api v0.25.0 h1:INwdXsCDSA/0hGNdPxdE2dQD6ft/5K1EaKXZixvSQxg=
+k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc=
+k8s.io/csi-translation-lib v0.25.0 h1:Jh3kn5p3kEGGA/q1fovTNIG9fypzt2c34sm+qij2W/8=
+k8s.io/csi-translation-lib v0.25.0/go.mod h1:Wb80CDywP4753F6wWkIyOuJIQtQAbhgw985veSgAn/4=
 k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
-k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
-k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
-k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/kms v0.26.0 h1:5+GOQLvUajSd0z5ODF52RzB2rHo1HJUSYsVC3Ri3VgI=
-k8s.io/kms v0.26.0/go.mod h1:ReC1IEGuxgfN+PDCIpR6w8+XMmDE7uJhxcCwMZFdIYc=
-k8s.io/kube-aggregator v0.26.0 h1:XF/Q5FwdLmCsK1RKGFNWfIo/b+r63sXOu+KKcaIFa/M=
-k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
-k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
-k8s.io/kube-proxy v0.26.0 h1:VBC83bWr5L4GKSxRFz0YBbwGgQITc0+p8avGzw0LNKo=
-k8s.io/kube-proxy v0.26.0/go.mod h1:4kz3dPdMUnspJnFgoJG9lWn1UCiho85Gyn1WLInK0XA=
-k8s.io/kube-scheduler v0.26.0 h1:PjSF4cF9X7cAMj5MZ9ZSq2RJ2VkcKKCKj6fy/EbxtA0=
-k8s.io/kube-scheduler v0.26.0/go.mod h1:FmptJbq36ATKYxeR+UqAvUtFaLeoFWgoDk1cdCpVPYQ=
-k8s.io/kubectl v0.26.0 h1:xmrzoKR9CyNdzxBmXV7jW9Ln8WMrwRK6hGbbf69o4T0=
-k8s.io/kubectl v0.26.0/go.mod h1:eInP0b+U9XUJWSYeU9XZnTA+cVYuWyl3iYPGtru0qhQ=
-k8s.io/kubelet v0.26.0 h1:08bDb5IoUH/1K1t2NUwnGIIWxjm9LSqn6k3FWw1tJGI=
-k8s.io/kubelet v0.26.0/go.mod h1:DluF+d8jS2nE/Hs7CC3QM+OZlIEb22NTOihQ3EDwCQ4=
-k8s.io/kubernetes v1.26.0 h1:fL8VMr4xlfTazPORLhz5fsvO5I3bsFpmynVxZTH1ItQ=
-k8s.io/kubernetes v1.26.0/go.mod h1:z0aCJwn6DxzB/dDiWLbQaJO5jWOR2qoaCMnmSAx45XM=
-k8s.io/legacy-cloud-providers v0.26.0 h1:PudIbGlvQLwSkden/vSfRE4YtsyKCRjQs0OAiP1w8M8=
-k8s.io/legacy-cloud-providers v0.26.0/go.mod h1:dOOgYhHiMNWNla/XyM4Ppgjcrn3HulGa93/0vUO5/z4=
-k8s.io/metrics v0.26.0 h1:U/NzZHKDrIVGL93AUMRkqqXjOah3wGvjSnKmG/5NVCs=
-k8s.io/mount-utils v0.26.0 h1:MG5oXE2aF1UHMJ3KFbVtBtiRA4J/2u0sijrkfsoaMwU=
-k8s.io/mount-utils v0.26.0/go.mod h1:au99w4FWU5ZWelLb3Yx6kJc8RZ387IyWVM9tN65Yhxo=
-k8s.io/pod-security-admission v0.26.0 h1:XBG/uyP2cYwSFr5IWAQ1IIArxMYARJKzEzSmP4ZbC1s=
-k8s.io/pod-security-admission v0.26.0/go.mod h1:HQHvpCrn6KQLKRUqFvWkHCVKet3X62fn2F3j5anYiEM=
-k8s.io/sample-apiserver v0.26.0 h1:8ackiudVsxJhfdUxIw+ftG14+5AYr51RYhcO/+xeZYY=
+k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
+k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
+k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kube-aggregator v0.25.0 h1:T0AZZh5nkEcXJnK1o87IghRCZf/KDtzJQWIPulQQlHU=
+k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
+k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
+k8s.io/kube-proxy v0.25.0 h1:QuoKEyXV+NNMXEh8oqlthUlHkmWF+WBnYUMHCf817k0=
+k8s.io/kube-proxy v0.25.0/go.mod h1:uHv1HwMVDYgl1pU2PTDKLRlxtNOf4z2M5YPYC6NP1CU=
+k8s.io/kube-scheduler v0.25.0 h1:Up2rW+1H3JsgcpfdMcj/kVbYtgoxpiwxKLg5L4PaZ98=
+k8s.io/kube-scheduler v0.25.0/go.mod h1:cwiyJeImgFbhmbnImzvuhbiJayNngRNEe3FJkZDPw9Y=
+k8s.io/kubectl v0.25.0 h1:/Wn1cFqo8ik3iee1EvpxYre3bkWsGLXzLQI6uCCAkQc=
+k8s.io/kubectl v0.25.0/go.mod h1:n16ULWsOl2jmQpzt2o7Dud1t4o0+Y186ICb4O+GwKAU=
+k8s.io/kubelet v0.25.0 h1:eTS5B1u1o63ndExAHKLJytzz/GBy86ROcxYtu0VK3RA=
+k8s.io/kubelet v0.25.0/go.mod h1:J6aQxrZdSsGPrskYrhZdEn6PCnGha+GNvF0g9aWfQnw=
+k8s.io/kubernetes v1.25.3 h1:Ljx/Ew9+dt7rN9ob3V+N/aoDy7nDSbmr35IbYGRTyqE=
+k8s.io/kubernetes v1.25.3/go.mod h1:lvEY+3iJhh+sGIK1LorGkI56rW0eLGsfalnp68wQwYU=
+k8s.io/legacy-cloud-providers v0.25.0 h1:c+boKaCw/2ZzvA8/XgTIeDrGUJJ2Ucy+jLJFf02+huE=
+k8s.io/legacy-cloud-providers v0.25.0/go.mod h1:bnmUgHHeBmK3M9JgQzu+ne6UCUVURDzkpF0Y7VeypVE=
+k8s.io/metrics v0.25.0 h1:z/tyqXUCxvmFsKIO7GH6ulvogYvGp+pDmlz5ANSQVPE=
+k8s.io/mount-utils v0.25.0 h1:dx+SKXBVjskPgkpv9Mk0mAfbLNOxz8jAqTXGTZJnd8I=
+k8s.io/mount-utils v0.25.0/go.mod h1:WTYq8Ev/JrnkqK2h1jFUnC8qWGuqzMb9XDC+Lu3WNU0=
+k8s.io/pod-security-admission v0.25.0 h1:Sceq45pO7E7RTaYAr3Br94ZMDISJIngvXXcAfcZJufk=
+k8s.io/pod-security-admission v0.25.0/go.mod h1:b/UC586Th2LijoNV+ssyyAryUvmaTrEWms5ZzBEkVsA=
+k8s.io/sample-apiserver v0.25.0 h1:YvpJa31xRnNzFfkiF9/8gT0AzxMWwGlamT/aEClhHPo=
 k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y=
-k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
+k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
@@ -1279,6 +1251,5 @@ sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM
 sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
+sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
-sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
diff --git a/hack/generate.sh b/hack/generate.sh
index 0d5c165d6..9b3b5ca22 100755
--- a/hack/generate.sh
+++ b/hack/generate.sh
@@ -10,10 +10,10 @@ go generate ./cmd/... ./pkg/... ./source/...
 
 rm -rf vendor/
 
-controller-gen object crd output:crd:stdout paths=./pkg/apis/... > deployment/base/nfd-crds/nfd-api-crds.yaml
+controller-gen object crd output:crd:stdout paths=./pkg/apis/... > deployment/base/nfd-crds/nodefeaturerule-crd.yaml
 
 mkdir -p deployment/helm/node-feature-discovery/crds
-cp deployment/base/nfd-crds/nfd-api-crds.yaml deployment/helm/node-feature-discovery/crds
+cp deployment/base/nfd-crds/nodefeaturerule-crd.yaml deployment/helm/node-feature-discovery/crds/
 
 rm -rf sigs.k8s.io
 
diff --git a/pkg/apis/nfd/v1alpha1/annotations_labels.go b/pkg/apis/nfd/v1alpha1/annotations_labels.go
index 978ba853c..0dc82a6a9 100644
--- a/pkg/apis/nfd/v1alpha1/annotations_labels.go
+++ b/pkg/apis/nfd/v1alpha1/annotations_labels.go
@@ -43,13 +43,4 @@ const (
 
 	// WorkerVersionAnnotation is the annotation that holds the version of nfd-worker running on the node
 	WorkerVersionAnnotation = AnnotationNs + "/worker.version"
-
-	// NodeTaintsAnnotation is the annotation that holds the taints that nfd-master set on the node
-	NodeTaintsAnnotation = AnnotationNs + "/taints"
-
-	// NodeFeatureObjNodeNameLabel is the label that specifies which node the
-	// NodeFeature object is targeting. Creators of NodeFeature objects must
-	// set this label and consumers of the objects are supposed to use the
-	// label for filtering features designated for a certain node.
-	NodeFeatureObjNodeNameLabel = "nfd.node.kubernetes.io/node-name"
 )
diff --git a/pkg/apis/nfd/v1alpha1/register.go b/pkg/apis/nfd/v1alpha1/register.go
index 8c1d41f5b..c87a4852a 100644
--- a/pkg/apis/nfd/v1alpha1/register.go
+++ b/pkg/apis/nfd/v1alpha1/register.go
@@ -40,7 +40,6 @@ func Resource(resource string) schema.GroupResource {
 
 func addKnownTypes(scheme *runtime.Scheme) error {
 	scheme.AddKnownTypes(SchemeGroupVersion,
-		&NodeFeature{},
 		&NodeFeatureRule{},
 	)
 	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
diff --git a/pkg/apis/nfd/v1alpha1/rule.go b/pkg/apis/nfd/v1alpha1/rule.go
index d7e3cd20c..c352b62d7 100644
--- a/pkg/apis/nfd/v1alpha1/rule.go
+++ b/pkg/apis/nfd/v1alpha1/rule.go
@@ -22,8 +22,8 @@ import (
 	"strings"
 	"text/template"
 
-	corev1 "k8s.io/api/core/v1"
 	"k8s.io/klog/v2"
+
 	"sigs.k8s.io/node-feature-discovery/pkg/utils"
 )
 
@@ -32,7 +32,6 @@ import (
 type RuleOutput struct {
 	Labels map[string]string
 	Vars   map[string]string
-	Taints []corev1.Taint
 }
 
 // Execute the rule against a set of input features.
@@ -95,8 +94,9 @@ func (r *Rule) Execute(features *Features) (RuleOutput, error) {
 		vars[k] = v
 	}
 
-	ret := RuleOutput{Labels: labels, Vars: vars, Taints: r.Taints}
+	ret := RuleOutput{Labels: labels, Vars: vars}
 	utils.KlogDump(2, fmt.Sprintf("rule %q matched with: ", r.Name), "  ", ret)
+
 	return ret, nil
 }
 
diff --git a/pkg/apis/nfd/v1alpha1/types.go b/pkg/apis/nfd/v1alpha1/types.go
index 3565db1cd..b3e4bd602 100644
--- a/pkg/apis/nfd/v1alpha1/types.go
+++ b/pkg/apis/nfd/v1alpha1/types.go
@@ -17,41 +17,9 @@ limitations under the License.
 package v1alpha1
 
 import (
-	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-// NodeFeatureList contains a list of NodeFeature objects.
-// +kubebuilder:object:root=true
-// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-type NodeFeatureList struct {
-	metav1.TypeMeta `json:",inline"`
-	metav1.ListMeta `json:"metadata"`
-
-	Items []NodeFeature `json:"items"`
-}
-
-// NodeFeature resource holds the features discovered for one node in the
-// cluster.
-// +kubebuilder:object:root=true
-// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
-// +genclient
-type NodeFeature struct {
-	metav1.TypeMeta   `json:",inline"`
-	metav1.ObjectMeta `json:"metadata,omitempty"`
-
-	Spec NodeFeatureSpec `json:"spec"`
-}
-
-// NodeFeatureSpec describes a NodeFeature object.
-type NodeFeatureSpec struct {
-	// Features is the full "raw" features data that has been discovered.
-	Features Features `json:"features"`
-	// Labels is the set of node labels that are requested to be created.
-	// +optional
-	Labels map[string]string `json:"labels"`
-}
-
 // Features is the collection of all discovered features.
 //
 // +protobuf=true
@@ -152,10 +120,6 @@ type Rule struct {
 	// +optional
 	VarsTemplate string `json:"varsTemplate"`
 
-	// Taints to create if the rule matches.
-	// +optional
-	Taints []corev1.Taint `json:"taints,omitempty"`
-
 	// MatchFeatures specifies a set of matcher terms all of which must match.
 	// +optional
 	MatchFeatures FeatureMatcher `json:"matchFeatures"`
diff --git a/pkg/apis/nfd/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/nfd/v1alpha1/zz_generated.deepcopy.go
index 07073afac..1196b4139 100644
--- a/pkg/apis/nfd/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/nfd/v1alpha1/zz_generated.deepcopy.go
@@ -6,7 +6,6 @@
 package v1alpha1
 
 import (
-	"k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
@@ -342,64 +341,6 @@ func (in *Nil) DeepCopy() *Nil {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NodeFeature) DeepCopyInto(out *NodeFeature) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	in.Spec.DeepCopyInto(&out.Spec)
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeFeature.
-func (in *NodeFeature) DeepCopy() *NodeFeature {
-	if in == nil {
-		return nil
-	}
-	out := new(NodeFeature)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *NodeFeature) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NodeFeatureList) DeepCopyInto(out *NodeFeatureList) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	in.ListMeta.DeepCopyInto(&out.ListMeta)
-	if in.Items != nil {
-		in, out := &in.Items, &out.Items
-		*out = make([]NodeFeature, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeFeatureList.
-func (in *NodeFeatureList) DeepCopy() *NodeFeatureList {
-	if in == nil {
-		return nil
-	}
-	out := new(NodeFeatureList)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *NodeFeatureList) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *NodeFeatureRule) DeepCopyInto(out *NodeFeatureRule) {
 	*out = *in
@@ -480,29 +421,6 @@ func (in *NodeFeatureRuleSpec) DeepCopy() *NodeFeatureRuleSpec {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *NodeFeatureSpec) DeepCopyInto(out *NodeFeatureSpec) {
-	*out = *in
-	in.Features.DeepCopyInto(&out.Features)
-	if in.Labels != nil {
-		in, out := &in.Labels, &out.Labels
-		*out = make(map[string]string, len(*in))
-		for key, val := range *in {
-			(*out)[key] = val
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeFeatureSpec.
-func (in *NodeFeatureSpec) DeepCopy() *NodeFeatureSpec {
-	if in == nil {
-		return nil
-	}
-	out := new(NodeFeatureSpec)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Rule) DeepCopyInto(out *Rule) {
 	*out = *in
@@ -520,13 +438,6 @@ func (in *Rule) DeepCopyInto(out *Rule) {
 			(*out)[key] = val
 		}
 	}
-	if in.Taints != nil {
-		in, out := &in.Taints, &out.Taints
-		*out = make([]v1.Taint, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
 	if in.MatchFeatures != nil {
 		in, out := &in.MatchFeatures, &out.MatchFeatures
 		*out = make(FeatureMatcher, len(*in))
diff --git a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go
index 4022cd369..713326833 100644
--- a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go
+++ b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nfd_client.go
@@ -28,10 +28,6 @@ type FakeNfdV1alpha1 struct {
 	*testing.Fake
 }
 
-func (c *FakeNfdV1alpha1) NodeFeatures(namespace string) v1alpha1.NodeFeatureInterface {
-	return &FakeNodeFeatures{c, namespace}
-}
-
 func (c *FakeNfdV1alpha1) NodeFeatureRules() v1alpha1.NodeFeatureRuleInterface {
 	return &FakeNodeFeatureRules{c}
 }
diff --git a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go
deleted file mode 100644
index 1986bf618..000000000
--- a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/fake/fake_nodefeature.go
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-Copyright 2022 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package fake
-
-import (
-	"context"
-
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	labels "k8s.io/apimachinery/pkg/labels"
-	schema "k8s.io/apimachinery/pkg/runtime/schema"
-	types "k8s.io/apimachinery/pkg/types"
-	watch "k8s.io/apimachinery/pkg/watch"
-	testing "k8s.io/client-go/testing"
-	v1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
-)
-
-// FakeNodeFeatures implements NodeFeatureInterface
-type FakeNodeFeatures struct {
-	Fake *FakeNfdV1alpha1
-	ns   string
-}
-
-var nodefeaturesResource = schema.GroupVersionResource{Group: "nfd.k8s-sigs.io", Version: "v1alpha1", Resource: "nodefeatures"}
-
-var nodefeaturesKind = schema.GroupVersionKind{Group: "nfd.k8s-sigs.io", Version: "v1alpha1", Kind: "NodeFeature"}
-
-// Get takes name of the nodeFeature, and returns the corresponding nodeFeature object, and an error if there is any.
-func (c *FakeNodeFeatures) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeature, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewGetAction(nodefeaturesResource, c.ns, name), &v1alpha1.NodeFeature{})
-
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.NodeFeature), err
-}
-
-// List takes label and field selectors, and returns the list of NodeFeatures that match those selectors.
-func (c *FakeNodeFeatures) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureList, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewListAction(nodefeaturesResource, nodefeaturesKind, c.ns, opts), &v1alpha1.NodeFeatureList{})
-
-	if obj == nil {
-		return nil, err
-	}
-
-	label, _, _ := testing.ExtractFromListOptions(opts)
-	if label == nil {
-		label = labels.Everything()
-	}
-	list := &v1alpha1.NodeFeatureList{ListMeta: obj.(*v1alpha1.NodeFeatureList).ListMeta}
-	for _, item := range obj.(*v1alpha1.NodeFeatureList).Items {
-		if label.Matches(labels.Set(item.Labels)) {
-			list.Items = append(list.Items, item)
-		}
-	}
-	return list, err
-}
-
-// Watch returns a watch.Interface that watches the requested nodeFeatures.
-func (c *FakeNodeFeatures) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
-	return c.Fake.
-		InvokesWatch(testing.NewWatchAction(nodefeaturesResource, c.ns, opts))
-
-}
-
-// Create takes the representation of a nodeFeature and creates it.  Returns the server's representation of the nodeFeature, and an error, if there is any.
-func (c *FakeNodeFeatures) Create(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.CreateOptions) (result *v1alpha1.NodeFeature, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewCreateAction(nodefeaturesResource, c.ns, nodeFeature), &v1alpha1.NodeFeature{})
-
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.NodeFeature), err
-}
-
-// Update takes the representation of a nodeFeature and updates it. Returns the server's representation of the nodeFeature, and an error, if there is any.
-func (c *FakeNodeFeatures) Update(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (result *v1alpha1.NodeFeature, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewUpdateAction(nodefeaturesResource, c.ns, nodeFeature), &v1alpha1.NodeFeature{})
-
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.NodeFeature), err
-}
-
-// Delete takes name of the nodeFeature and deletes it. Returns an error if one occurs.
-func (c *FakeNodeFeatures) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
-	_, err := c.Fake.
-		Invokes(testing.NewDeleteActionWithOptions(nodefeaturesResource, c.ns, name, opts), &v1alpha1.NodeFeature{})
-
-	return err
-}
-
-// DeleteCollection deletes a collection of objects.
-func (c *FakeNodeFeatures) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
-	action := testing.NewDeleteCollectionAction(nodefeaturesResource, c.ns, listOpts)
-
-	_, err := c.Fake.Invokes(action, &v1alpha1.NodeFeatureList{})
-	return err
-}
-
-// Patch applies the patch and returns the patched nodeFeature.
-func (c *FakeNodeFeatures) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeature, err error) {
-	obj, err := c.Fake.
-		Invokes(testing.NewPatchSubresourceAction(nodefeaturesResource, c.ns, name, pt, data, subresources...), &v1alpha1.NodeFeature{})
-
-	if obj == nil {
-		return nil, err
-	}
-	return obj.(*v1alpha1.NodeFeature), err
-}
diff --git a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go
index cf392dd10..8807cd64d 100644
--- a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go
+++ b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/generated_expansion.go
@@ -18,6 +18,4 @@ limitations under the License.
 
 package v1alpha1
 
-type NodeFeatureExpansion interface{}
-
 type NodeFeatureRuleExpansion interface{}
diff --git a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go
index 8ecaf1998..034d5cbe7 100644
--- a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go
+++ b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/nfd_client.go
@@ -28,7 +28,6 @@ import (
 
 type NfdV1alpha1Interface interface {
 	RESTClient() rest.Interface
-	NodeFeaturesGetter
 	NodeFeatureRulesGetter
 }
 
@@ -37,10 +36,6 @@ type NfdV1alpha1Client struct {
 	restClient rest.Interface
 }
 
-func (c *NfdV1alpha1Client) NodeFeatures(namespace string) NodeFeatureInterface {
-	return newNodeFeatures(c, namespace)
-}
-
 func (c *NfdV1alpha1Client) NodeFeatureRules() NodeFeatureRuleInterface {
 	return newNodeFeatureRules(c)
 }
diff --git a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeature.go b/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeature.go
deleted file mode 100644
index bf6d9b175..000000000
--- a/pkg/generated/clientset/versioned/typed/nfd/v1alpha1/nodefeature.go
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
-Copyright 2022 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by client-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	"context"
-	"time"
-
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	types "k8s.io/apimachinery/pkg/types"
-	watch "k8s.io/apimachinery/pkg/watch"
-	rest "k8s.io/client-go/rest"
-	v1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
-	scheme "sigs.k8s.io/node-feature-discovery/pkg/generated/clientset/versioned/scheme"
-)
-
-// NodeFeaturesGetter has a method to return a NodeFeatureInterface.
-// A group's client should implement this interface.
-type NodeFeaturesGetter interface {
-	NodeFeatures(namespace string) NodeFeatureInterface
-}
-
-// NodeFeatureInterface has methods to work with NodeFeature resources.
-type NodeFeatureInterface interface {
-	Create(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.CreateOptions) (*v1alpha1.NodeFeature, error)
-	Update(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (*v1alpha1.NodeFeature, error)
-	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
-	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
-	Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeFeature, error)
-	List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeFeatureList, error)
-	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
-	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeature, err error)
-	NodeFeatureExpansion
-}
-
-// nodeFeatures implements NodeFeatureInterface
-type nodeFeatures struct {
-	client rest.Interface
-	ns     string
-}
-
-// newNodeFeatures returns a NodeFeatures
-func newNodeFeatures(c *NfdV1alpha1Client, namespace string) *nodeFeatures {
-	return &nodeFeatures{
-		client: c.RESTClient(),
-		ns:     namespace,
-	}
-}
-
-// Get takes name of the nodeFeature, and returns the corresponding nodeFeature object, and an error if there is any.
-func (c *nodeFeatures) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeFeature, err error) {
-	result = &v1alpha1.NodeFeature{}
-	err = c.client.Get().
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		Name(name).
-		VersionedParams(&options, scheme.ParameterCodec).
-		Do(ctx).
-		Into(result)
-	return
-}
-
-// List takes label and field selectors, and returns the list of NodeFeatures that match those selectors.
-func (c *nodeFeatures) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeFeatureList, err error) {
-	var timeout time.Duration
-	if opts.TimeoutSeconds != nil {
-		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
-	}
-	result = &v1alpha1.NodeFeatureList{}
-	err = c.client.Get().
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		VersionedParams(&opts, scheme.ParameterCodec).
-		Timeout(timeout).
-		Do(ctx).
-		Into(result)
-	return
-}
-
-// Watch returns a watch.Interface that watches the requested nodeFeatures.
-func (c *nodeFeatures) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
-	var timeout time.Duration
-	if opts.TimeoutSeconds != nil {
-		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
-	}
-	opts.Watch = true
-	return c.client.Get().
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		VersionedParams(&opts, scheme.ParameterCodec).
-		Timeout(timeout).
-		Watch(ctx)
-}
-
-// Create takes the representation of a nodeFeature and creates it.  Returns the server's representation of the nodeFeature, and an error, if there is any.
-func (c *nodeFeatures) Create(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.CreateOptions) (result *v1alpha1.NodeFeature, err error) {
-	result = &v1alpha1.NodeFeature{}
-	err = c.client.Post().
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		VersionedParams(&opts, scheme.ParameterCodec).
-		Body(nodeFeature).
-		Do(ctx).
-		Into(result)
-	return
-}
-
-// Update takes the representation of a nodeFeature and updates it. Returns the server's representation of the nodeFeature, and an error, if there is any.
-func (c *nodeFeatures) Update(ctx context.Context, nodeFeature *v1alpha1.NodeFeature, opts v1.UpdateOptions) (result *v1alpha1.NodeFeature, err error) {
-	result = &v1alpha1.NodeFeature{}
-	err = c.client.Put().
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		Name(nodeFeature.Name).
-		VersionedParams(&opts, scheme.ParameterCodec).
-		Body(nodeFeature).
-		Do(ctx).
-		Into(result)
-	return
-}
-
-// Delete takes name of the nodeFeature and deletes it. Returns an error if one occurs.
-func (c *nodeFeatures) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
-	return c.client.Delete().
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		Name(name).
-		Body(&opts).
-		Do(ctx).
-		Error()
-}
-
-// DeleteCollection deletes a collection of objects.
-func (c *nodeFeatures) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
-	var timeout time.Duration
-	if listOpts.TimeoutSeconds != nil {
-		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
-	}
-	return c.client.Delete().
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		VersionedParams(&listOpts, scheme.ParameterCodec).
-		Timeout(timeout).
-		Body(&opts).
-		Do(ctx).
-		Error()
-}
-
-// Patch applies the patch and returns the patched nodeFeature.
-func (c *nodeFeatures) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeFeature, err error) {
-	result = &v1alpha1.NodeFeature{}
-	err = c.client.Patch(pt).
-		Namespace(c.ns).
-		Resource("nodefeatures").
-		Name(name).
-		SubResource(subresources...).
-		VersionedParams(&opts, scheme.ParameterCodec).
-		Body(data).
-		Do(ctx).
-		Into(result)
-	return
-}
diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go
index 5c2b9eda3..453de7f15 100644
--- a/pkg/generated/informers/externalversions/generic.go
+++ b/pkg/generated/informers/externalversions/generic.go
@@ -53,8 +53,6 @@ func (f *genericInformer) Lister() cache.GenericLister {
 func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
 	switch resource {
 	// Group=nfd.k8s-sigs.io, Version=v1alpha1
-	case v1alpha1.SchemeGroupVersion.WithResource("nodefeatures"):
-		return &genericInformer{resource: resource.GroupResource(), informer: f.Nfd().V1alpha1().NodeFeatures().Informer()}, nil
 	case v1alpha1.SchemeGroupVersion.WithResource("nodefeaturerules"):
 		return &genericInformer{resource: resource.GroupResource(), informer: f.Nfd().V1alpha1().NodeFeatureRules().Informer()}, nil
 
diff --git a/pkg/generated/informers/externalversions/nfd/v1alpha1/interface.go b/pkg/generated/informers/externalversions/nfd/v1alpha1/interface.go
index 1cae0cfc2..5f476d887 100644
--- a/pkg/generated/informers/externalversions/nfd/v1alpha1/interface.go
+++ b/pkg/generated/informers/externalversions/nfd/v1alpha1/interface.go
@@ -24,8 +24,6 @@ import (
 
 // Interface provides access to all the informers in this group version.
 type Interface interface {
-	// NodeFeatures returns a NodeFeatureInformer.
-	NodeFeatures() NodeFeatureInformer
 	// NodeFeatureRules returns a NodeFeatureRuleInformer.
 	NodeFeatureRules() NodeFeatureRuleInformer
 }
@@ -41,11 +39,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
 	return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
 }
 
-// NodeFeatures returns a NodeFeatureInformer.
-func (v *version) NodeFeatures() NodeFeatureInformer {
-	return &nodeFeatureInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
-}
-
 // NodeFeatureRules returns a NodeFeatureRuleInformer.
 func (v *version) NodeFeatureRules() NodeFeatureRuleInformer {
 	return &nodeFeatureRuleInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
diff --git a/pkg/generated/informers/externalversions/nfd/v1alpha1/nodefeature.go b/pkg/generated/informers/externalversions/nfd/v1alpha1/nodefeature.go
deleted file mode 100644
index 20ea65f56..000000000
--- a/pkg/generated/informers/externalversions/nfd/v1alpha1/nodefeature.go
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Copyright 2022 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by informer-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	"context"
-	time "time"
-
-	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	runtime "k8s.io/apimachinery/pkg/runtime"
-	watch "k8s.io/apimachinery/pkg/watch"
-	cache "k8s.io/client-go/tools/cache"
-	nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
-	versioned "sigs.k8s.io/node-feature-discovery/pkg/generated/clientset/versioned"
-	internalinterfaces "sigs.k8s.io/node-feature-discovery/pkg/generated/informers/externalversions/internalinterfaces"
-	v1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/generated/listers/nfd/v1alpha1"
-)
-
-// NodeFeatureInformer provides access to a shared informer and lister for
-// NodeFeatures.
-type NodeFeatureInformer interface {
-	Informer() cache.SharedIndexInformer
-	Lister() v1alpha1.NodeFeatureLister
-}
-
-type nodeFeatureInformer struct {
-	factory          internalinterfaces.SharedInformerFactory
-	tweakListOptions internalinterfaces.TweakListOptionsFunc
-	namespace        string
-}
-
-// NewNodeFeatureInformer constructs a new informer for NodeFeature type.
-// Always prefer using an informer factory to get a shared informer instead of getting an independent
-// one. This reduces memory footprint and number of connections to the server.
-func NewNodeFeatureInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
-	return NewFilteredNodeFeatureInformer(client, namespace, resyncPeriod, indexers, nil)
-}
-
-// NewFilteredNodeFeatureInformer constructs a new informer for NodeFeature type.
-// Always prefer using an informer factory to get a shared informer instead of getting an independent
-// one. This reduces memory footprint and number of connections to the server.
-func NewFilteredNodeFeatureInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
-	return cache.NewSharedIndexInformer(
-		&cache.ListWatch{
-			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
-				if tweakListOptions != nil {
-					tweakListOptions(&options)
-				}
-				return client.NfdV1alpha1().NodeFeatures(namespace).List(context.TODO(), options)
-			},
-			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
-				if tweakListOptions != nil {
-					tweakListOptions(&options)
-				}
-				return client.NfdV1alpha1().NodeFeatures(namespace).Watch(context.TODO(), options)
-			},
-		},
-		&nfdv1alpha1.NodeFeature{},
-		resyncPeriod,
-		indexers,
-	)
-}
-
-func (f *nodeFeatureInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
-	return NewFilteredNodeFeatureInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
-}
-
-func (f *nodeFeatureInformer) Informer() cache.SharedIndexInformer {
-	return f.factory.InformerFor(&nfdv1alpha1.NodeFeature{}, f.defaultInformer)
-}
-
-func (f *nodeFeatureInformer) Lister() v1alpha1.NodeFeatureLister {
-	return v1alpha1.NewNodeFeatureLister(f.Informer().GetIndexer())
-}
diff --git a/pkg/generated/listers/nfd/v1alpha1/expansion_generated.go b/pkg/generated/listers/nfd/v1alpha1/expansion_generated.go
index 5e6fc01e4..a072a4f4a 100644
--- a/pkg/generated/listers/nfd/v1alpha1/expansion_generated.go
+++ b/pkg/generated/listers/nfd/v1alpha1/expansion_generated.go
@@ -18,14 +18,6 @@ limitations under the License.
 
 package v1alpha1
 
-// NodeFeatureListerExpansion allows custom methods to be added to
-// NodeFeatureLister.
-type NodeFeatureListerExpansion interface{}
-
-// NodeFeatureNamespaceListerExpansion allows custom methods to be added to
-// NodeFeatureNamespaceLister.
-type NodeFeatureNamespaceListerExpansion interface{}
-
 // NodeFeatureRuleListerExpansion allows custom methods to be added to
 // NodeFeatureRuleLister.
 type NodeFeatureRuleListerExpansion interface{}
diff --git a/pkg/generated/listers/nfd/v1alpha1/nodefeature.go b/pkg/generated/listers/nfd/v1alpha1/nodefeature.go
deleted file mode 100644
index 011dffd55..000000000
--- a/pkg/generated/listers/nfd/v1alpha1/nodefeature.go
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-Copyright 2022 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-// Code generated by lister-gen. DO NOT EDIT.
-
-package v1alpha1
-
-import (
-	"k8s.io/apimachinery/pkg/api/errors"
-	"k8s.io/apimachinery/pkg/labels"
-	"k8s.io/client-go/tools/cache"
-	v1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
-)
-
-// NodeFeatureLister helps list NodeFeatures.
-// All objects returned here must be treated as read-only.
-type NodeFeatureLister interface {
-	// List lists all NodeFeatures in the indexer.
-	// Objects returned here must be treated as read-only.
-	List(selector labels.Selector) (ret []*v1alpha1.NodeFeature, err error)
-	// NodeFeatures returns an object that can list and get NodeFeatures.
-	NodeFeatures(namespace string) NodeFeatureNamespaceLister
-	NodeFeatureListerExpansion
-}
-
-// nodeFeatureLister implements the NodeFeatureLister interface.
-type nodeFeatureLister struct {
-	indexer cache.Indexer
-}
-
-// NewNodeFeatureLister returns a new NodeFeatureLister.
-func NewNodeFeatureLister(indexer cache.Indexer) NodeFeatureLister {
-	return &nodeFeatureLister{indexer: indexer}
-}
-
-// List lists all NodeFeatures in the indexer.
-func (s *nodeFeatureLister) List(selector labels.Selector) (ret []*v1alpha1.NodeFeature, err error) {
-	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
-		ret = append(ret, m.(*v1alpha1.NodeFeature))
-	})
-	return ret, err
-}
-
-// NodeFeatures returns an object that can list and get NodeFeatures.
-func (s *nodeFeatureLister) NodeFeatures(namespace string) NodeFeatureNamespaceLister {
-	return nodeFeatureNamespaceLister{indexer: s.indexer, namespace: namespace}
-}
-
-// NodeFeatureNamespaceLister helps list and get NodeFeatures.
-// All objects returned here must be treated as read-only.
-type NodeFeatureNamespaceLister interface {
-	// List lists all NodeFeatures in the indexer for a given namespace.
-	// Objects returned here must be treated as read-only.
-	List(selector labels.Selector) (ret []*v1alpha1.NodeFeature, err error)
-	// Get retrieves the NodeFeature from the indexer for a given namespace and name.
-	// Objects returned here must be treated as read-only.
-	Get(name string) (*v1alpha1.NodeFeature, error)
-	NodeFeatureNamespaceListerExpansion
-}
-
-// nodeFeatureNamespaceLister implements the NodeFeatureNamespaceLister
-// interface.
-type nodeFeatureNamespaceLister struct {
-	indexer   cache.Indexer
-	namespace string
-}
-
-// List lists all NodeFeatures in the indexer for a given namespace.
-func (s nodeFeatureNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.NodeFeature, err error) {
-	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
-		ret = append(ret, m.(*v1alpha1.NodeFeature))
-	})
-	return ret, err
-}
-
-// Get retrieves the NodeFeature from the indexer for a given namespace and name.
-func (s nodeFeatureNamespaceLister) Get(name string) (*v1alpha1.NodeFeature, error) {
-	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
-	if err != nil {
-		return nil, err
-	}
-	if !exists {
-		return nil, errors.NewNotFound(v1alpha1.Resource("nodefeature"), name)
-	}
-	return obj.(*v1alpha1.NodeFeature), nil
-}
diff --git a/pkg/nfd-client/base.go b/pkg/nfd-client/base.go
index c96553542..fa5e0b01a 100644
--- a/pkg/nfd-client/base.go
+++ b/pkg/nfd-client/base.go
@@ -49,7 +49,6 @@ type Args struct {
 	CaFile             string
 	CertFile           string
 	KeyFile            string
-	Kubeconfig         string
 	Server             string
 	ServerNameOverride string
 
diff --git a/pkg/nfd-client/topology-updater/nfd-topology-updater.go b/pkg/nfd-client/topology-updater/nfd-topology-updater.go
index 7ada9cb3b..1853536e2 100644
--- a/pkg/nfd-client/topology-updater/nfd-topology-updater.go
+++ b/pkg/nfd-client/topology-updater/nfd-topology-updater.go
@@ -22,16 +22,16 @@ import (
 	"path/filepath"
 	"time"
 
-	"k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/klog/v2"
 
 	v1alpha1 "github.com/k8stopologyawareschedwg/noderesourcetopology-api/pkg/apis/topology/v1alpha1"
 	"golang.org/x/net/context"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
+	nfdclient "sigs.k8s.io/node-feature-discovery/pkg/nfd-client"
 	"sigs.k8s.io/node-feature-discovery/pkg/podres"
 	"sigs.k8s.io/node-feature-discovery/pkg/resourcemonitor"
+	pb "sigs.k8s.io/node-feature-discovery/pkg/topologyupdater"
 	"sigs.k8s.io/node-feature-discovery/pkg/utils"
 	"sigs.k8s.io/node-feature-discovery/pkg/version"
 	"sigs.k8s.io/yaml"
@@ -39,12 +39,11 @@ import (
 
 // Args are the command line arguments
 type Args struct {
+	nfdclient.Args
 	NoPublish      bool
 	Oneshot        bool
 	KubeConfigFile string
 	ConfigFile     string
-
-	Klog map[string]*utils.KlogFlagVal
 }
 
 // NFDConfig contains the configuration settings of NFDTopologyUpdater.
@@ -53,32 +52,38 @@ type NFDConfig struct {
 }
 
 type NfdTopologyUpdater interface {
-	Run() error
-	Stop()
+	nfdclient.NfdClient
+	Update(v1alpha1.ZoneList) error
 }
 
 type staticNodeInfo struct {
-	nodeName string
 	tmPolicy string
 }
 
 type nfdTopologyUpdater struct {
+	nfdclient.NfdBaseClient
 	nodeInfo            *staticNodeInfo
 	args                Args
-	apihelper           apihelper.APIHelpers
 	resourcemonitorArgs resourcemonitor.Args
+	certWatch           *utils.FsWatcher
+	client              pb.NodeTopologyClient
 	stop                chan struct{} // channel for signaling stop
 	configFilePath      string
 	config              *NFDConfig
 }
 
 // NewTopologyUpdater creates a new NfdTopologyUpdater instance.
-func NewTopologyUpdater(args Args, resourcemonitorArgs resourcemonitor.Args, policy string) NfdTopologyUpdater {
+func NewTopologyUpdater(args Args, resourcemonitorArgs resourcemonitor.Args, policy string) (NfdTopologyUpdater, error) {
+	base, err := nfdclient.NewNfdBaseClient(&args.Args)
+	if err != nil {
+		return nil, err
+	}
+
 	nfd := &nfdTopologyUpdater{
+		NfdBaseClient:       base,
 		args:                args,
 		resourcemonitorArgs: resourcemonitorArgs,
 		nodeInfo: &staticNodeInfo{
-			nodeName: os.Getenv("NODE_NAME"),
 			tmPolicy: policy,
 		},
 		stop:   make(chan struct{}, 1),
@@ -87,26 +92,27 @@ func NewTopologyUpdater(args Args, resourcemonitorArgs resourcemonitor.Args, pol
 	if args.ConfigFile != "" {
 		nfd.configFilePath = filepath.Clean(args.ConfigFile)
 	}
-	return nfd
+	return nfd, nil
 }
 
-// Run nfdTopologyUpdater. Returns if a fatal error is encountered, or, after
+// Run nfdTopologyUpdater client. Returns if a fatal error is encountered, or, after
 // one request if OneShot is set to 'true' in the updater args.
 func (w *nfdTopologyUpdater) Run() error {
 	klog.Infof("Node Feature Discovery Topology Updater %s", version.Get())
-	klog.Infof("NodeName: '%s'", w.nodeInfo.nodeName)
+	klog.Infof("NodeName: '%s'", nfdclient.NodeName())
 
 	podResClient, err := podres.GetPodResClient(w.resourcemonitorArgs.PodResourceSocketPath)
 	if err != nil {
 		return fmt.Errorf("failed to get PodResource Client: %w", err)
 	}
 
+	var kubeApihelper apihelper.K8sHelpers
 	if !w.args.NoPublish {
 		kubeconfig, err := apihelper.GetKubeconfig(w.args.KubeConfigFile)
 		if err != nil {
 			return err
 		}
-		w.apihelper = apihelper.K8sHelpers{Kubeconfig: kubeconfig}
+		kubeApihelper = apihelper.K8sHelpers{Kubeconfig: kubeconfig}
 	}
 	if err := w.configure(); err != nil {
 		return fmt.Errorf("faild to configure Node Feature Discovery Topology Updater: %w", err)
@@ -114,7 +120,7 @@ func (w *nfdTopologyUpdater) Run() error {
 
 	var resScan resourcemonitor.ResourcesScanner
 
-	resScan, err = resourcemonitor.NewPodResourcesScanner(w.resourcemonitorArgs.Namespace, podResClient, w.apihelper)
+	resScan, err = resourcemonitor.NewPodResourcesScanner(w.resourcemonitorArgs.Namespace, podResClient, kubeApihelper)
 	if err != nil {
 		return fmt.Errorf("failed to initialize ResourceMonitor instance: %w", err)
 	}
@@ -125,7 +131,7 @@ func (w *nfdTopologyUpdater) Run() error {
 	// zonesChannel := make(chan v1alpha1.ZoneList)
 	var zones v1alpha1.ZoneList
 
-	excludeList := resourcemonitor.NewExcludeResourceList(w.config.ExcludeList, w.nodeInfo.nodeName)
+	excludeList := resourcemonitor.NewExcludeResourceList(w.config.ExcludeList, nfdclient.NodeName())
 	resAggr, err := resourcemonitor.NewResourcesAggregator(podResClient, excludeList)
 	if err != nil {
 		return fmt.Errorf("failed to obtain node resource information: %w", err)
@@ -133,6 +139,12 @@ func (w *nfdTopologyUpdater) Run() error {
 
 	klog.V(2).Infof("resAggr is: %v\n", resAggr)
 
+	// Create watcher for TLS certificates
+	w.certWatch, err = utils.CreateFsWatcher(time.Second, w.args.CaFile, w.args.CertFile, w.args.KeyFile)
+	if err != nil {
+		return err
+	}
+
 	crTrigger := time.NewTicker(w.resourcemonitorArgs.SleepInterval)
 	for {
 		select {
@@ -146,24 +158,49 @@ func (w *nfdTopologyUpdater) Run() error {
 			}
 			zones = resAggr.Aggregate(podResources)
 			utils.KlogDump(1, "After aggregating resources identified zones are", "  ", zones)
-			if !w.args.NoPublish {
-				if err = w.updateNodeResourceTopology(zones); err != nil {
-					return err
-				}
+			if err = w.Update(zones); err != nil {
+				return err
 			}
 
 			if w.args.Oneshot {
 				return nil
 			}
 
+		case <-w.certWatch.Events:
+			klog.Infof("TLS certificate update, renewing connection to nfd-master")
+			w.Disconnect()
+			if err := w.Connect(); err != nil {
+				return err
+			}
+
 		case <-w.stop:
 			klog.Infof("shutting down nfd-topology-updater")
+			w.certWatch.Close()
 			return nil
 		}
 	}
 
 }
 
+func (w *nfdTopologyUpdater) Update(zones v1alpha1.ZoneList) error {
+	// Connect to NFD master
+	err := w.Connect()
+	if err != nil {
+		return fmt.Errorf("failed to connect: %w", err)
+	}
+	defer w.Disconnect()
+
+	if w.client == nil {
+		return nil
+	}
+
+	err = advertiseNodeTopology(w.client, zones, w.nodeInfo.tmPolicy, nfdclient.NodeName())
+	if err != nil {
+		return fmt.Errorf("failed to advertise node topology: %w", err)
+	}
+	return nil
+}
+
 // Stop NFD Topology Updater
 func (w *nfdTopologyUpdater) Stop() {
 	select {
@@ -172,39 +209,59 @@ func (w *nfdTopologyUpdater) Stop() {
 	}
 }
 
-func (w *nfdTopologyUpdater) updateNodeResourceTopology(zoneInfo v1alpha1.ZoneList) error {
-	cli, err := w.apihelper.GetTopologyClient()
-	if err != nil {
+// connect creates a client connection to the NFD master
+func (w *nfdTopologyUpdater) Connect() error {
+	// Return a dummy connection in case of dry-run
+	if w.args.NoPublish {
+		return nil
+	}
+
+	if err := w.NfdBaseClient.Connect(); err != nil {
 		return err
 	}
+	w.client = pb.NewNodeTopologyClient(w.ClientConn())
 
-	nrt, err := cli.TopologyV1alpha1().NodeResourceTopologies().Get(context.TODO(), w.nodeInfo.nodeName, metav1.GetOptions{})
-	if errors.IsNotFound(err) {
-		nrtNew := v1alpha1.NodeResourceTopology{
-			ObjectMeta: metav1.ObjectMeta{
-				Name: w.nodeInfo.nodeName,
-			},
-			Zones:            zoneInfo,
-			TopologyPolicies: []string{w.nodeInfo.tmPolicy},
-		}
+	return nil
+}
 
-		_, err := cli.TopologyV1alpha1().NodeResourceTopologies().Create(context.TODO(), &nrtNew, metav1.CreateOptions{})
-		if err != nil {
-			return fmt.Errorf("failed to create NodeResourceTopology: %w", err)
+// disconnect closes the connection to NFD master
+func (w *nfdTopologyUpdater) Disconnect() {
+	w.NfdBaseClient.Disconnect()
+	w.client = nil
+}
+
+// advertiseNodeTopology advertises the topology CR to a Kubernetes node
+// via the NFD server.
+func advertiseNodeTopology(client pb.NodeTopologyClient, zoneInfo v1alpha1.ZoneList, tmPolicy string, nodeName string) error {
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+	defer cancel()
+	zones := make([]*v1alpha1.Zone, len(zoneInfo))
+	// TODO: Avoid copying of data to allow returning the zone info
+	// directly in a compatible data type (i.e. []*v1alpha1.Zone).
+	for i, zone := range zoneInfo {
+		zones[i] = &v1alpha1.Zone{
+			Name:      zone.Name,
+			Type:      zone.Type,
+			Parent:    zone.Parent,
+			Resources: zone.Resources,
+			Costs:     zone.Costs,
 		}
-		return nil
-	} else if err != nil {
-		return err
 	}
 
-	nrtMutated := nrt.DeepCopy()
-	nrtMutated.Zones = zoneInfo
+	topologyReq := &pb.NodeTopologyRequest{
+		Zones:            zones,
+		NfdVersion:       version.Get(),
+		NodeName:         nodeName,
+		TopologyPolicies: []string{tmPolicy},
+	}
+
+	utils.KlogDump(1, "Sending NodeTopologyRequest to nfd-master:", "  ", topologyReq)
 
-	nrtUpdated, err := cli.TopologyV1alpha1().NodeResourceTopologies().Update(context.TODO(), nrtMutated, metav1.UpdateOptions{})
+	_, err := client.UpdateNodeTopology(ctx, topologyReq)
 	if err != nil {
-		return fmt.Errorf("failed to update NodeResourceTopology: %w", err)
+		return err
 	}
-	utils.KlogDump(4, "CR instance updated resTopo:", "  ", nrtUpdated)
+
 	return nil
 }
 
diff --git a/pkg/nfd-client/worker/nfd-worker.go b/pkg/nfd-client/worker/nfd-worker.go
index abc0fdb4a..e7a6df73a 100644
--- a/pkg/nfd-client/worker/nfd-worker.go
+++ b/pkg/nfd-client/worker/nfd-worker.go
@@ -27,16 +27,10 @@ import (
 	"time"
 
 	"golang.org/x/net/context"
-	"k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/util/validation"
 	"k8s.io/klog/v2"
 	"sigs.k8s.io/yaml"
 
-	apiequality "k8s.io/apimachinery/pkg/api/equality"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
-	nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
-	nfdclient "sigs.k8s.io/node-feature-discovery/pkg/generated/clientset/versioned"
 	pb "sigs.k8s.io/node-feature-discovery/pkg/labeler"
 	clientcommon "sigs.k8s.io/node-feature-discovery/pkg/nfd-client"
 	"sigs.k8s.io/node-feature-discovery/pkg/utils"
@@ -82,10 +76,9 @@ type Labels map[string]string
 type Args struct {
 	clientcommon.Args
 
-	ConfigFile           string
-	EnableNodeFeatureApi bool
-	Oneshot              bool
-	Options              string
+	ConfigFile string
+	Oneshot    bool
+	Options    string
 
 	Klog      map[string]*utils.KlogFlagVal
 	Overrides ConfigOverrideArgs
@@ -102,16 +95,14 @@ type ConfigOverrideArgs struct {
 type nfdWorker struct {
 	clientcommon.NfdBaseClient
 
-	args                Args
-	certWatch           *utils.FsWatcher
-	configFilePath      string
-	config              *NFDConfig
-	kubernetesNamespace string
-	grpcClient          pb.LabelerClient
-	nfdClient           *nfdclient.Clientset
-	stop                chan struct{} // channel for signaling stop
-	featureSources      []source.FeatureSource
-	labelSources        []source.LabelSource
+	args           Args
+	certWatch      *utils.FsWatcher
+	configFilePath string
+	config         *NFDConfig
+	grpcClient     pb.LabelerClient
+	stop           chan struct{} // channel for signaling stop
+	featureSources []source.FeatureSource
+	labelSources   []source.LabelSource
 }
 
 type duration struct {
@@ -128,10 +119,9 @@ func NewNfdWorker(args *Args) (clientcommon.NfdClient, error) {
 	nfd := &nfdWorker{
 		NfdBaseClient: base,
 
-		args:                *args,
-		config:              &NFDConfig{},
-		kubernetesNamespace: utils.GetKubernetesNamespace(),
-		stop:                make(chan struct{}, 1),
+		args:   *args,
+		config: &NFDConfig{},
+		stop:   make(chan struct{}, 1),
 	}
 
 	if args.ConfigFile != "" {
@@ -158,7 +148,6 @@ func newDefaultConfig() *NFDConfig {
 func (w *nfdWorker) Run() error {
 	klog.Infof("Node Feature Discovery Worker %s", version.Get())
 	klog.Infof("NodeName: '%s'", clientcommon.NodeName())
-	klog.Infof("Kubernetes namespace: '%s'", w.kubernetesNamespace)
 
 	// Create watcher for config file and read initial configuration
 	configWatch, err := utils.CreateFsWatcher(time.Second, w.configFilePath)
@@ -194,8 +183,9 @@ func (w *nfdWorker) Run() error {
 
 			// Update the node with the feature labels.
 			if !w.config.Core.NoPublish {
-				if err := w.advertiseFeatures(labels); err != nil {
-					return err
+				err := w.advertiseFeatureLabels(labels)
+				if err != nil {
+					return fmt.Errorf("failed to advertise labels: %s", err.Error())
 				}
 			}
 
@@ -213,7 +203,7 @@ func (w *nfdWorker) Run() error {
 				return err
 			}
 			// Manage connection to master
-			if w.config.Core.NoPublish || !w.args.EnableNodeFeatureApi {
+			if w.config.Core.NoPublish {
 				w.GrpcDisconnect()
 			}
 
@@ -532,22 +522,6 @@ func getFeatureLabels(source source.LabelSource, labelWhiteList regexp.Regexp) (
 	return labels, nil
 }
 
-// advertiseFeatures advertises the features of a Kubernetes node
-func (w *nfdWorker) advertiseFeatures(labels Labels) error {
-	if w.args.EnableNodeFeatureApi {
-		// Create/update NodeFeature CR object
-		if err := w.updateNodeFeatureObject(labels); err != nil {
-			return fmt.Errorf("failed to advertise features (via CRD API): %w", err)
-		}
-	} else {
-		// Create/update feature labels through gRPC connection to nfd-master
-		if err := w.advertiseFeatureLabels(labels); err != nil {
-			return fmt.Errorf("failed to advertise features (via gRPC): %w", err)
-		}
-	}
-	return nil
-}
-
 // advertiseFeatureLabels advertises the feature labels to a Kubernetes node
 // via the NFD server.
 func (w *nfdWorker) advertiseFeatureLabels(labels Labels) error {
@@ -575,85 +549,6 @@ func (w *nfdWorker) advertiseFeatureLabels(labels Labels) error {
 	return nil
 }
 
-// updateNodeFeatureObject creates/updates the node-specific NodeFeature custom resource.
-func (m *nfdWorker) updateNodeFeatureObject(labels Labels) error {
-	cli, err := m.getNfdClient()
-	if err != nil {
-		return err
-	}
-	nodename := clientcommon.NodeName()
-	namespace := m.kubernetesNamespace
-
-	features := source.GetAllFeatures()
-
-	// TODO: we could implement some simple caching of the object, only get it
-	// every 10 minutes or so because nobody else should really be modifying it
-	if nfr, err := cli.NfdV1alpha1().NodeFeatures(namespace).Get(context.TODO(), nodename, metav1.GetOptions{}); errors.IsNotFound(err) {
-		klog.Infof("creating NodeFeature object %q", nodename)
-		nfr = &nfdv1alpha1.NodeFeature{
-			ObjectMeta: metav1.ObjectMeta{
-				Name:        nodename,
-				Annotations: map[string]string{nfdv1alpha1.WorkerVersionAnnotation: version.Get()},
-				Labels:      map[string]string{nfdv1alpha1.NodeFeatureObjNodeNameLabel: nodename},
-			},
-			Spec: nfdv1alpha1.NodeFeatureSpec{
-				Features: *features,
-				Labels:   labels,
-			},
-		}
-
-		nfrCreated, err := cli.NfdV1alpha1().NodeFeatures(namespace).Create(context.TODO(), nfr, metav1.CreateOptions{})
-		if err != nil {
-			return fmt.Errorf("failed to create NodeFeature object %q: %w", nfr.Name, err)
-		}
-
-		utils.KlogDump(4, "NodeFeature object created:", "  ", nfrCreated)
-	} else if err != nil {
-		return fmt.Errorf("failed to get NodeFeature object: %w", err)
-	} else {
-
-		nfrUpdated := nfr.DeepCopy()
-		nfrUpdated.Annotations = map[string]string{nfdv1alpha1.WorkerVersionAnnotation: version.Get()}
-		nfrUpdated.Labels = map[string]string{nfdv1alpha1.NodeFeatureObjNodeNameLabel: nodename}
-		nfrUpdated.Spec = nfdv1alpha1.NodeFeatureSpec{
-			Features: *features,
-			Labels:   labels,
-		}
-
-		if !apiequality.Semantic.DeepEqual(nfr, nfrUpdated) {
-			klog.Infof("updating NodeFeature object %q", nodename)
-			nfrUpdated, err = cli.NfdV1alpha1().NodeFeatures(namespace).Update(context.TODO(), nfrUpdated, metav1.UpdateOptions{})
-			if err != nil {
-				return fmt.Errorf("failed to update NodeFeature object %q: %w", nfr.Name, err)
-			}
-			utils.KlogDump(4, "NodeFeature object updated:", "  ", nfrUpdated)
-		} else {
-			klog.V(1).Info("no changes in NodeFeature object, not updating")
-		}
-	}
-	return nil
-}
-
-// getNfdClient returns the clientset for using the nfd CRD api
-func (m *nfdWorker) getNfdClient() (*nfdclient.Clientset, error) {
-	if m.nfdClient != nil {
-		return m.nfdClient, nil
-	}
-
-	kubeconfig, err := apihelper.GetKubeconfig(m.args.Kubeconfig)
-	if err != nil {
-		return nil, err
-	}
-
-	c, err := nfdclient.NewForConfig(kubeconfig)
-	if err != nil {
-		return nil, err
-	}
-
-	m.nfdClient = c
-	return c, nil
-}
-
 // UnmarshalJSON implements the Unmarshaler interface from "encoding/json"
 func (d *duration) UnmarshalJSON(data []byte) error {
 	var v interface{}
diff --git a/pkg/nfd-master/nfd-api-controller.go b/pkg/nfd-master/nfd-api-controller.go
index 84fd7d524..04212b137 100644
--- a/pkg/nfd-master/nfd-api-controller.go
+++ b/pkg/nfd-master/nfd-api-controller.go
@@ -32,89 +32,41 @@ import (
 )
 
 type nfdController struct {
-	featureLister nfdlisters.NodeFeatureLister
-	ruleLister    nfdlisters.NodeFeatureRuleLister
+	ruleLister nfdlisters.NodeFeatureRuleLister
 
 	stopChan chan struct{}
-
-	updateAllNodesChan chan struct{}
-	updateOneNodeChan  chan string
 }
 
-func newNfdController(config *restclient.Config, disableNodeFeature bool) (*nfdController, error) {
+func newNfdController(config *restclient.Config) *nfdController {
 	c := &nfdController{
-		stopChan:           make(chan struct{}, 1),
-		updateAllNodesChan: make(chan struct{}, 1),
-		updateOneNodeChan:  make(chan string),
+		stopChan: make(chan struct{}, 1),
 	}
 
 	nfdClient := nfdclientset.NewForConfigOrDie(config)
 
 	informerFactory := nfdinformers.NewSharedInformerFactory(nfdClient, 5*time.Minute)
-
-	// Add informer for NodeFeature objects
-	if !disableNodeFeature {
-		featureInformer := informerFactory.Nfd().V1alpha1().NodeFeatures()
-		if _, err := featureInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
-			AddFunc: func(obj interface{}) {
-				key, _ := cache.MetaNamespaceKeyFunc(obj)
-				klog.V(2).Infof("NodeFeature %v added", key)
-				c.updateOneNode(obj)
-			},
-			UpdateFunc: func(oldObj, newObj interface{}) {
-				key, _ := cache.MetaNamespaceKeyFunc(newObj)
-				klog.V(2).Infof("NodeFeature %v updated", key)
-				c.updateOneNode(newObj)
-			},
-			DeleteFunc: func(obj interface{}) {
-				key, _ := cache.MetaNamespaceKeyFunc(obj)
-				klog.V(2).Infof("NodeFeature %v deleted", key)
-				c.updateOneNode(obj)
-			},
-		}); err != nil {
-			return nil, err
-		}
-		c.featureLister = featureInformer.Lister()
-	}
-
-	// Add informer for NodeFeatureRule objects
 	ruleInformer := informerFactory.Nfd().V1alpha1().NodeFeatureRules()
-	if _, err := ruleInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
+	ruleInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 		AddFunc: func(object interface{}) {
 			key, _ := cache.MetaNamespaceKeyFunc(object)
 			klog.V(2).Infof("NodeFeatureRule %v added", key)
-			if !disableNodeFeature {
-				c.updateAllNodes()
-			}
-			// else: rules will be processed only when gRPC requests are received
 		},
 		UpdateFunc: func(oldObject, newObject interface{}) {
 			key, _ := cache.MetaNamespaceKeyFunc(newObject)
 			klog.V(2).Infof("NodeFeatureRule %v updated", key)
-			if !disableNodeFeature {
-				c.updateAllNodes()
-			}
-			// else: rules will be processed only when gRPC requests are received
 		},
 		DeleteFunc: func(object interface{}) {
 			key, _ := cache.MetaNamespaceKeyFunc(object)
 			klog.V(2).Infof("NodeFeatureRule %v deleted", key)
-			if !disableNodeFeature {
-				c.updateAllNodes()
-			}
-			// else: rules will be processed only when gRPC requests are received
 		},
-	}); err != nil {
-		return nil, err
-	}
-	c.ruleLister = ruleInformer.Lister()
-
-	// Start informers
+	})
 	informerFactory.Start(c.stopChan)
 
 	utilruntime.Must(nfdv1alpha1.AddToScheme(nfdscheme.Scheme))
 
-	return c, nil
+	c.ruleLister = ruleInformer.Lister()
+
+	return c
 }
 
 func (c *nfdController) stop() {
@@ -123,32 +75,3 @@ func (c *nfdController) stop() {
 	default:
 	}
 }
-
-func (c *nfdController) updateOneNode(obj interface{}) {
-	o, ok := obj.(*nfdv1alpha1.NodeFeature)
-	if !ok {
-		klog.Errorf("not a NodeFeature object (but of type %T): %v", obj, obj)
-		return
-	}
-
-	nodeName, ok := o.Labels[nfdv1alpha1.NodeFeatureObjNodeNameLabel]
-	if !ok {
-		klog.Errorf("no node name for NodeFeature object %s/%s: %q label is missing",
-			o.Namespace, o.Name, nfdv1alpha1.NodeFeatureObjNodeNameLabel)
-		return
-	}
-	if nodeName == "" {
-		klog.Errorf("no node name for NodeFeature object %s/%s: %q label is empty",
-			o.Namespace, o.Name, nfdv1alpha1.NodeFeatureObjNodeNameLabel)
-		return
-	}
-
-	c.updateOneNodeChan <- nodeName
-}
-
-func (c *nfdController) updateAllNodes() {
-	select {
-	case c.updateAllNodesChan <- struct{}{}:
-	default:
-	}
-}
diff --git a/pkg/nfd-master/nfd-master.go b/pkg/nfd-master/nfd-master.go
index 75da6bd62..5111d5773 100644
--- a/pkg/nfd-master/nfd-master.go
+++ b/pkg/nfd-master/nfd-master.go
@@ -29,6 +29,7 @@ import (
 	"strings"
 	"time"
 
+	"github.com/k8stopologyawareschedwg/noderesourcetopology-api/pkg/apis/topology/v1alpha1"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials"
@@ -36,17 +37,17 @@ import (
 	"google.golang.org/grpc/health/grpc_health_v1"
 	"google.golang.org/grpc/peer"
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
-	label "k8s.io/apimachinery/pkg/labels"
 	"k8s.io/client-go/kubernetes"
 	restclient "k8s.io/client-go/rest"
 	"k8s.io/klog/v2"
-	controller "k8s.io/kubernetes/pkg/controller"
-	taintutils "k8s.io/kubernetes/pkg/util/taints"
 
 	"sigs.k8s.io/node-feature-discovery/pkg/apihelper"
 	nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/pkg/apis/nfd/v1alpha1"
 	pb "sigs.k8s.io/node-feature-discovery/pkg/labeler"
+	topologypb "sigs.k8s.io/node-feature-discovery/pkg/topologyupdater"
 	"sigs.k8s.io/node-feature-discovery/pkg/utils"
 	"sigs.k8s.io/node-feature-discovery/pkg/version"
 )
@@ -62,21 +63,19 @@ type Annotations map[string]string
 
 // Args holds command line arguments
 type Args struct {
-	CaFile               string
-	CertFile             string
-	ExtraLabelNs         utils.StringSetVal
-	Instance             string
-	KeyFile              string
-	Kubeconfig           string
-	LabelWhiteList       utils.RegexpVal
-	CrdController        bool
-	EnableNodeFeatureApi bool
-	NoPublish            bool
-	EnableTaints         bool
-	Port                 int
-	Prune                bool
-	VerifyNodeName       bool
-	ResourceLabels       utils.StringSetVal
+	CaFile                 string
+	CertFile               string
+	ExtraLabelNs           utils.StringSetVal
+	Instance               string
+	KeyFile                string
+	Kubeconfig             string
+	LabelWhiteList         utils.RegexpVal
+	FeatureRulesController bool
+	NoPublish              bool
+	Port                   int
+	Prune                  bool
+	VerifyNodeName         bool
+	ResourceLabels         utils.StringSetVal
 }
 
 type NfdMaster interface {
@@ -89,7 +88,6 @@ type nfdMaster struct {
 	*nfdController
 
 	args       Args
-	namespace  string
 	nodeName   string
 	server     *grpc.Server
 	stop       chan struct{}
@@ -101,10 +99,9 @@ type nfdMaster struct {
 // NewNfdMaster creates a new NfdMaster server instance.
 func NewNfdMaster(args *Args) (NfdMaster, error) {
 	nfd := &nfdMaster{args: *args,
-		nodeName:  os.Getenv("NODE_NAME"),
-		namespace: utils.GetKubernetesNamespace(),
-		ready:     make(chan bool, 1),
-		stop:      make(chan struct{}, 1),
+		nodeName: os.Getenv("NODE_NAME"),
+		ready:    make(chan bool, 1),
+		stop:     make(chan struct{}, 1),
 	}
 
 	if args.Instance != "" {
@@ -148,22 +145,18 @@ func (m *nfdMaster) Run() error {
 		klog.Infof("Master instance: %q", m.args.Instance)
 	}
 	klog.Infof("NodeName: %q", m.nodeName)
-	klog.Infof("Kubernetes namespace: %q", m.namespace)
 
 	if m.args.Prune {
 		return m.prune()
 	}
 
-	if m.args.CrdController {
+	if m.args.FeatureRulesController {
 		kubeconfig, err := m.getKubeconfig()
 		if err != nil {
 			return err
 		}
 		klog.Info("starting nfd api controller")
-		m.nfdController, err = newNfdController(kubeconfig, !m.args.EnableNodeFeatureApi)
-		if err != nil {
-			return fmt.Errorf("failed to initialize CRD controller: %w", err)
-		}
+		m.nfdController = newNfdController(kubeconfig)
 	}
 
 	if !m.args.NoPublish {
@@ -175,14 +168,7 @@ func (m *nfdMaster) Run() error {
 
 	// Run gRPC server
 	grpcErr := make(chan error, 1)
-	if !m.args.EnableNodeFeatureApi {
-		go m.runGrpcServer(grpcErr)
-	}
-
-	// Run updater that handles events from the nfd CRD API.
-	if m.nfdController != nil {
-		go m.nfdAPIUpdateHandler()
-	}
+	go m.runGrpcServer(grpcErr)
 
 	// Notify that we're ready to accept connections
 	m.ready <- true
@@ -231,6 +217,7 @@ func (m *nfdMaster) runGrpcServer(errChan chan<- error) {
 	m.server = grpc.NewServer(serverOpts...)
 	pb.RegisterLabelerServer(m.server, m)
 	grpc_health_v1.RegisterHealthServer(m.server, health.NewServer())
+	topologypb.RegisterNodeTopologyServer(m.server, m)
 	klog.Infof("gRPC server serving on port: %d", m.args.Port)
 
 	// Run gRPC server
@@ -257,40 +244,6 @@ func (m *nfdMaster) runGrpcServer(errChan chan<- error) {
 	}
 }
 
-// nfdAPIUpdateHandler handles events from the nfd API controller.
-func (m *nfdMaster) nfdAPIUpdateHandler() {
-	updateAll := false
-	updateNodes := make(map[string]struct{})
-	rateLimit := time.After(time.Second)
-	for {
-		select {
-		case <-m.nfdController.updateAllNodesChan:
-			updateAll = true
-		case nodeName := <-m.nfdController.updateOneNodeChan:
-			updateNodes[nodeName] = struct{}{}
-		case <-rateLimit:
-			// Check what we need to do
-			// TODO: we might want to update multiple nodes in parallel
-			if updateAll {
-				if err := m.nfdAPIUpdateAllNodes(); err != nil {
-					klog.Error(err)
-				}
-			} else {
-				for nodeName := range updateNodes {
-					if err := m.nfdAPIUpdateOneNode(nodeName); err != nil {
-						klog.Error(err)
-					}
-				}
-			}
-
-			// Reset "work queue" and timer
-			updateAll = false
-			updateNodes = make(map[string]struct{})
-			rateLimit = time.After(time.Second)
-		}
-	}
-}
-
 // Stop NfdMaster
 func (m *nfdMaster) Stop() {
 	m.server.GracefulStop()
@@ -336,9 +289,9 @@ func (m *nfdMaster) prune() error {
 		klog.Infof("pruning node %q...", node.Name)
 
 		// Prune labels and extended resources
-		err := m.updateNodeObject(cli, node.Name, Labels{}, Annotations{}, ExtendedResources{}, []corev1.Taint{})
+		err := m.updateNodeFeatures(cli, node.Name, Labels{}, Annotations{}, ExtendedResources{})
 		if err != nil {
-			return fmt.Errorf("failed to prune node %q: %v", node.Name, err)
+			return fmt.Errorf("failed to prune labels from node %q: %v", node.Name, err)
 		}
 
 		// Prune annotations
@@ -439,13 +392,14 @@ func verifyNodeName(cert *x509.Certificate, nodeName string) error {
 
 	err := cert.VerifyHostname(nodeName)
 	if err != nil {
-		return fmt.Errorf("certificate %q not valid for node %q: %v", cert.Subject.CommonName, nodeName, err)
+		return fmt.Errorf("Certificate %q not valid for node %q: %v", cert.Subject.CommonName, nodeName, err)
 	}
 	return nil
 }
 
 // SetLabels implements LabelerServer
 func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.SetLabelsReply, error) {
+
 	err := authorizeClient(c, m.args.VerifyNodeName, r.NodeName)
 	if err != nil {
 		return &pb.SetLabelsReply{}, err
@@ -460,6 +414,18 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se
 		klog.Infof("received labeling request for node %q", r.NodeName)
 	}
 
+	// Mix in CR-originated labels
+	rawLabels := make(map[string]string)
+	if r.Labels != nil {
+		// NOTE: we effectively mangle the request struct by not creating a deep copy of the map
+		rawLabels = r.Labels
+	}
+	for k, v := range m.crLabels(r) {
+		rawLabels[k] = v
+	}
+
+	labels, extendedResources := filterFeatureLabels(rawLabels, m.args.ExtraLabelNs, m.args.LabelWhiteList.Regexp, m.args.ResourceLabels)
+
 	if !m.args.NoPublish {
 		cli, err := m.apihelper.GetClient()
 		if err != nil {
@@ -469,203 +435,15 @@ func (m *nfdMaster) SetLabels(c context.Context, r *pb.SetLabelsRequest) (*pb.Se
 		// Advertise NFD worker version as an annotation
 		annotations := Annotations{m.instanceAnnotation(nfdv1alpha1.WorkerVersionAnnotation): r.NfdVersion}
 
-		// Create labels et al
-		if err := m.refreshNodeFeatures(cli, r.NodeName, annotations, r.GetLabels(), r.GetFeatures()); err != nil {
+		err = m.updateNodeFeatures(cli, r.NodeName, labels, annotations, extendedResources)
+		if err != nil {
+			klog.Errorf("failed to advertise labels: %v", err)
 			return &pb.SetLabelsReply{}, err
 		}
 	}
 	return &pb.SetLabelsReply{}, nil
 }
 
-func (m *nfdMaster) nfdAPIUpdateAllNodes() error {
-	klog.Info("will process all nodes in the cluster")
-
-	cli, err := m.apihelper.GetClient()
-	if err != nil {
-		return err
-	}
-
-	nodes, err := m.apihelper.GetNodes(cli)
-	if err != nil {
-		return err
-	}
-
-	for _, node := range nodes.Items {
-		if err := m.nfdAPIUpdateOneNode(node.Name); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (m *nfdMaster) nfdAPIUpdateOneNode(nodeName string) error {
-	sel := labels.SelectorFromSet(labels.Set{nfdv1alpha1.NodeFeatureObjNodeNameLabel: nodeName})
-	objs, err := m.nfdController.featureLister.List(sel)
-	if len(objs) == 0 {
-		klog.Infof("no NodeFeature object exists for node %q, skipping...", nodeName)
-		return nil
-	} else if err != nil {
-		return fmt.Errorf("failed to get NodeFeature resources for node %q: %w", nodeName, err)
-	}
-
-	// Sort our objects
-	sort.Slice(objs, func(i, j int) bool {
-		// Objects in our nfd namespace gets into the beginning of the list
-		if objs[i].Namespace == m.namespace && objs[j].Namespace != m.namespace {
-			return true
-		}
-		if objs[i].Namespace != m.namespace && objs[j].Namespace == m.namespace {
-			return false
-		}
-		// After the nfd namespace, sort objects by their name
-		if objs[i].Name != objs[j].Name {
-			return objs[i].Name < objs[j].Name
-		}
-		// Objects with the same name are sorted by their namespace
-		return objs[i].Namespace < objs[j].Namespace
-	})
-
-	if m.args.NoPublish {
-		return nil
-	}
-
-	klog.V(1).Infof("processing node %q, initiated by NodeFeature API", nodeName)
-
-	// Merge in features
-	//
-	// TODO: support multiple NodeFeature objects. There are two obvious options to implement this:
-	// 1. Merge features of all objects into one joint object
-	// 2. Change the rule api to support handle multiple objects
-	// Of these #2 would probably perform better with lot less data to copy. We
-	// could probably even get rid of the DeepCopy in this scenario.
-	features := objs[0].DeepCopy()
-
-	annotations := Annotations{}
-	if objs[0].Namespace == m.namespace && objs[0].Name == nodeName {
-		// This is the one created by nfd-worker
-		if v := objs[0].Annotations[nfdv1alpha1.WorkerVersionAnnotation]; v != "" {
-			annotations[nfdv1alpha1.WorkerVersionAnnotation] = v
-		}
-	}
-
-	// Create labels et al
-	cli, err := m.apihelper.GetClient()
-	if err != nil {
-		return err
-	}
-	if err := m.refreshNodeFeatures(cli, nodeName, annotations, features.Spec.Labels, &features.Spec.Features); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (m *nfdMaster) refreshNodeFeatures(cli *kubernetes.Clientset, nodeName string, annotations, labels map[string]string, features *nfdv1alpha1.Features) error {
-	if labels == nil {
-		labels = make(map[string]string)
-	}
-
-	crLabels, crTaints := m.processNodeFeatureRule(features)
-
-	// Mix in CR-originated labels
-	for k, v := range crLabels {
-		labels[k] = v
-	}
-
-	labels, extendedResources := filterFeatureLabels(labels, m.args.ExtraLabelNs, m.args.LabelWhiteList.Regexp, m.args.ResourceLabels)
-
-	var taints []corev1.Taint
-	if m.args.EnableTaints {
-		taints = crTaints
-	}
-
-	err := m.updateNodeObject(cli, nodeName, labels, annotations, extendedResources, taints)
-	if err != nil {
-		klog.Errorf("failed to update node %q: %v", nodeName, err)
-		return err
-	}
-
-	return nil
-}
-
-// setTaints sets node taints and annotations based on the taints passed via
-// nodeFeatureRule custom resorce. If empty list of taints is passed, currently
-// NFD owned taints and annotations are removed from the node.
-func (m *nfdMaster) setTaints(cli *kubernetes.Clientset, taints []corev1.Taint, nodeName string) error {
-	// Fetch the node object.
-	node, err := m.apihelper.GetNode(cli, nodeName)
-	if err != nil {
-		return err
-	}
-
-	// De-serialize the taints annotation into corev1.Taint type for comparision below.
-	oldTaints := []corev1.Taint{}
-	if val, ok := node.Annotations[nfdv1alpha1.NodeTaintsAnnotation]; ok {
-		sts := strings.Split(val, ",")
-		oldTaints, _, err = taintutils.ParseTaints(sts)
-		if err != nil {
-			return err
-		}
-	}
-
-	// Delete old nfd-managed taints that are not found in the set of new taints.
-	taintsUpdated := false
-	newNode := node.DeepCopy()
-	for _, taintToRemove := range oldTaints {
-		if taintutils.TaintExists(taints, &taintToRemove) {
-			continue
-		}
-
-		newTaints, removed := taintutils.DeleteTaint(newNode.Spec.Taints, &taintToRemove)
-		if !removed {
-			klog.V(1).Infof("taint %q already deleted from node", taintToRemove.ToString())
-		}
-		taintsUpdated = taintsUpdated || removed
-		newNode.Spec.Taints = newTaints
-	}
-
-	// Add new taints found in the set of new taints.
-	for _, taint := range taints {
-		var updated bool
-		newNode, updated, err = taintutils.AddOrUpdateTaint(newNode, &taint)
-		if err != nil {
-			return fmt.Errorf("failed to add %q taint on node %v", taint, node.Name)
-		}
-		taintsUpdated = taintsUpdated || updated
-	}
-
-	if taintsUpdated {
-		err = controller.PatchNodeTaints(context.TODO(), cli, nodeName, node, newNode)
-		if err != nil {
-			return fmt.Errorf("failed to patch the node %v", node.Name)
-		}
-		klog.Infof("updated node %q taints", nodeName)
-	}
-
-	// Update node annotation that holds the taints managed by us
-	newAnnotations := map[string]string{}
-	if len(taints) > 0 {
-		// Serialize the new taints into string and update the annotation
-		// with that string.
-		taintStrs := make([]string, 0, len(taints))
-		for _, taint := range taints {
-			taintStrs = append(taintStrs, taint.ToString())
-		}
-		newAnnotations[nfdv1alpha1.NodeTaintsAnnotation] = strings.Join(taintStrs, ",")
-	}
-
-	patches := createPatches([]string{nfdv1alpha1.NodeTaintsAnnotation}, node.Annotations, newAnnotations, "/metadata/annotations")
-	if len(patches) > 0 {
-		err = m.apihelper.PatchNode(cli, node.Name, patches)
-		if err != nil {
-			return fmt.Errorf("error while patching node object: %v", err)
-		}
-		klog.V(1).Infof("patched node %q annotations for taints", nodeName)
-	}
-	return nil
-}
-
 func authorizeClient(c context.Context, checkNodeName bool, nodeName string) error {
 	if checkNodeName {
 		// Client authorization.
@@ -694,23 +472,46 @@ func authorizeClient(c context.Context, checkNodeName bool, nodeName string) err
 	return nil
 }
 
-func (m *nfdMaster) processNodeFeatureRule(features *nfdv1alpha1.Features) (map[string]string, []corev1.Taint) {
+func (m *nfdMaster) UpdateNodeTopology(c context.Context, r *topologypb.NodeTopologyRequest) (*topologypb.NodeTopologyResponse, error) {
+	err := authorizeClient(c, m.args.VerifyNodeName, r.NodeName)
+	if err != nil {
+		return &topologypb.NodeTopologyResponse{}, err
+	}
+	if klog.V(1).Enabled() {
+		klog.Infof("REQUEST Node: %s NFD-version: %s Topology Policy: %s", r.NodeName, r.NfdVersion, r.TopologyPolicies)
+		utils.KlogDump(1, "Zones received:", "  ", r.Zones)
+	} else {
+		klog.Infof("received CR updation request for node %q", r.NodeName)
+	}
+	if !m.args.NoPublish {
+		err := m.updateCR(r.NodeName, r.TopologyPolicies, r.Zones)
+		if err != nil {
+			klog.Errorf("failed to advertise NodeResourceTopology: %v", err)
+			return &topologypb.NodeTopologyResponse{}, err
+		}
+	}
+	return &topologypb.NodeTopologyResponse{}, nil
+}
+
+func (m *nfdMaster) crLabels(r *pb.SetLabelsRequest) map[string]string {
 	if m.nfdController == nil {
-		return nil, nil
+		return nil
 	}
 
-	labels := make(map[string]string)
-	var taints []corev1.Taint
-	ruleSpecs, err := m.nfdController.ruleLister.List(label.Everything())
+	l := make(map[string]string)
+	ruleSpecs, err := m.nfdController.ruleLister.List(labels.Everything())
 	sort.Slice(ruleSpecs, func(i, j int) bool {
 		return ruleSpecs[i].Name < ruleSpecs[j].Name
 	})
 
 	if err != nil {
 		klog.Errorf("failed to list NodeFeatureRule resources: %v", err)
-		return nil, nil
+		return nil
 	}
 
+	// Helper struct for rule processing
+	features := r.GetFeatures()
+
 	// Process all rule CRs
 	for _, spec := range ruleSpecs {
 		switch {
@@ -726,9 +527,9 @@ func (m *nfdMaster) processNodeFeatureRule(features *nfdv1alpha1.Features) (map[
 				klog.Errorf("failed to process Rule %q: %v", rule.Name, err)
 				continue
 			}
-			taints = append(taints, ruleOut.Taints...)
+
 			for k, v := range ruleOut.Labels {
-				labels[k] = v
+				l[k] = v
 			}
 
 			// Feed back rule output to features map for subsequent rules to match
@@ -737,13 +538,13 @@ func (m *nfdMaster) processNodeFeatureRule(features *nfdv1alpha1.Features) (map[
 		}
 	}
 
-	return labels, taints
+	return l
 }
 
-// updateNodeObject ensures the Kubernetes node object is up to date,
+// updateNodeFeatures ensures the Kubernetes node object is up to date,
 // creating new labels and extended resources where necessary and removing
 // outdated ones. Also updates the corresponding annotations.
-func (m *nfdMaster) updateNodeObject(cli *kubernetes.Clientset, nodeName string, labels Labels, annotations Annotations, extendedResources ExtendedResources, taints []corev1.Taint) error {
+func (m *nfdMaster) updateNodeFeatures(cli *kubernetes.Clientset, nodeName string, labels Labels, annotations Annotations, extendedResources ExtendedResources) error {
 	if cli == nil {
 		return fmt.Errorf("no client is passed, client:  %v", cli)
 	}
@@ -796,12 +597,6 @@ func (m *nfdMaster) updateNodeObject(cli *kubernetes.Clientset, nodeName string,
 		klog.V(1).Infof("no updates to node %q", nodeName)
 	}
 
-	// Set taints
-	err = m.setTaints(cli, taints, node.Name)
-	if err != nil {
-		return err
-	}
-
 	return err
 }
 
@@ -908,6 +703,60 @@ func stringToNsNames(cslist, ns string) []string {
 	return names
 }
 
+func modifyCR(topoUpdaterZones []*v1alpha1.Zone) []v1alpha1.Zone {
+	zones := make([]v1alpha1.Zone, len(topoUpdaterZones))
+	// TODO: Avoid copying of data to allow returning the zone info
+	// directly in a compatible data type (i.e. []*v1alpha1.Zone).
+	for i, zone := range topoUpdaterZones {
+		zones[i] = v1alpha1.Zone{
+			Name:      zone.Name,
+			Type:      zone.Type,
+			Parent:    zone.Parent,
+			Costs:     zone.Costs,
+			Resources: zone.Resources,
+		}
+	}
+	return zones
+}
+
+func (m *nfdMaster) updateCR(hostname string, tmpolicy []string, topoUpdaterZones []*v1alpha1.Zone) error {
+	cli, err := m.apihelper.GetTopologyClient()
+	if err != nil {
+		return err
+	}
+
+	zones := modifyCR(topoUpdaterZones)
+
+	nrt, err := cli.TopologyV1alpha1().NodeResourceTopologies().Get(context.TODO(), hostname, metav1.GetOptions{})
+	if errors.IsNotFound(err) {
+		nrtNew := v1alpha1.NodeResourceTopology{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: hostname,
+			},
+			Zones:            zones,
+			TopologyPolicies: tmpolicy,
+		}
+
+		_, err := cli.TopologyV1alpha1().NodeResourceTopologies().Create(context.TODO(), &nrtNew, metav1.CreateOptions{})
+		if err != nil {
+			return fmt.Errorf("failed to create v1alpha1.NodeResourceTopology!:%w", err)
+		}
+		return nil
+	} else if err != nil {
+		return err
+	}
+
+	nrtMutated := nrt.DeepCopy()
+	nrtMutated.Zones = zones
+
+	nrtUpdated, err := cli.TopologyV1alpha1().NodeResourceTopologies().Update(context.TODO(), nrtMutated, metav1.UpdateOptions{})
+	if err != nil {
+		return fmt.Errorf("failed to update v1alpha1.NodeResourceTopology!:%w", err)
+	}
+	utils.KlogDump(2, "CR instance updated resTopo:", "  ", nrtUpdated)
+	return nil
+}
+
 func (m *nfdMaster) instanceAnnotation(name string) string {
 	if m.args.Instance == "" {
 		return name
diff --git a/pkg/resourcemonitor/excludelist.go b/pkg/resourcemonitor/excludelist.go
index 590d0bb8a..444042f46 100644
--- a/pkg/resourcemonitor/excludelist.go
+++ b/pkg/resourcemonitor/excludelist.go
@@ -8,13 +8,12 @@ import (
 
 // ExcludeResourceList contains a list of resources to ignore during resources scan
 type ExcludeResourceList struct {
-	excludeList sets.Set[string]
+	excludeList sets.String
 }
 
 // NewExcludeResourceList returns new ExcludeList with values with set.String types
 func NewExcludeResourceList(resMap map[string][]string, nodeName string) ExcludeResourceList {
-	excludeList := make(sets.Set[string])
-
+	excludeList := make(sets.String)
 	for k, v := range resMap {
 		if k == nodeName || k == "*" {
 			excludeList.Insert(v...)
diff --git a/pkg/topologyupdater/doc.go b/pkg/topologyupdater/doc.go
new file mode 100644
index 000000000..b95359c68
--- /dev/null
+++ b/pkg/topologyupdater/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package topologyupdater
+
+//go:generate protoc --go_opt=paths=source_relative --go_out=plugins=grpc:. -I . -I ../../vendor/ topology-updater.proto
+//go:generate mockery --name=NodeTopologyClient --inpackage
diff --git a/pkg/topologyupdater/mock_NodeTopologyClient.go b/pkg/topologyupdater/mock_NodeTopologyClient.go
new file mode 100644
index 000000000..3ee715c27
--- /dev/null
+++ b/pkg/topologyupdater/mock_NodeTopologyClient.go
@@ -0,0 +1,61 @@
+// Code generated by mockery v2.13.0. DO NOT EDIT.
+
+package topologyupdater
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MockNodeTopologyClient is an autogenerated mock type for the NodeTopologyClient type
+type MockNodeTopologyClient struct {
+	mock.Mock
+}
+
+// UpdateNodeTopology provides a mock function with given fields: ctx, in, opts
+func (_m *MockNodeTopologyClient) UpdateNodeTopology(ctx context.Context, in *NodeTopologyRequest, opts ...grpc.CallOption) (*NodeTopologyResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *NodeTopologyResponse
+	if rf, ok := ret.Get(0).(func(context.Context, *NodeTopologyRequest, ...grpc.CallOption) *NodeTopologyResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*NodeTopologyResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *NodeTopologyRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+type NewMockNodeTopologyClientT interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockNodeTopologyClient creates a new instance of MockNodeTopologyClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockNodeTopologyClient(t NewMockNodeTopologyClientT) *MockNodeTopologyClient {
+	mock := &MockNodeTopologyClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/pkg/topologyupdater/topology-updater.pb.go b/pkg/topologyupdater/topology-updater.pb.go
new file mode 100644
index 000000000..41d45d54f
--- /dev/null
+++ b/pkg/topologyupdater/topology-updater.pb.go
@@ -0,0 +1,353 @@
+//
+//Copyright 2021 The Kubernetes Authors.
+//
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.23.0
+// 	protoc        v3.17.3
+// source: topology-updater.proto
+
+package topologyupdater
+
+import (
+	context "context"
+	proto "github.com/golang/protobuf/proto"
+	v1alpha1 "github.com/k8stopologyawareschedwg/noderesourcetopology-api/pkg/apis/topology/v1alpha1"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// This is a compile-time assertion that a sufficiently up-to-date version
+// of the legacy proto package is being used.
+const _ = proto.ProtoPackageIsVersion4
+
+type NodeTopologyRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	NfdVersion       string           `protobuf:"bytes,1,opt,name=nfd_version,json=nfdVersion,proto3" json:"nfd_version,omitempty"`
+	NodeName         string           `protobuf:"bytes,2,opt,name=node_name,json=nodeName,proto3" json:"node_name,omitempty"`
+	TopologyPolicies []string         `protobuf:"bytes,3,rep,name=topology_policies,json=topologyPolicies,proto3" json:"topology_policies,omitempty"`
+	Zones            []*v1alpha1.Zone `protobuf:"bytes,4,rep,name=zones,proto3" json:"zones,omitempty"`
+}
+
+func (x *NodeTopologyRequest) Reset() {
+	*x = NodeTopologyRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_topology_updater_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *NodeTopologyRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NodeTopologyRequest) ProtoMessage() {}
+
+func (x *NodeTopologyRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_topology_updater_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use NodeTopologyRequest.ProtoReflect.Descriptor instead.
+func (*NodeTopologyRequest) Descriptor() ([]byte, []int) {
+	return file_topology_updater_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *NodeTopologyRequest) GetNfdVersion() string {
+	if x != nil {
+		return x.NfdVersion
+	}
+	return ""
+}
+
+func (x *NodeTopologyRequest) GetNodeName() string {
+	if x != nil {
+		return x.NodeName
+	}
+	return ""
+}
+
+func (x *NodeTopologyRequest) GetTopologyPolicies() []string {
+	if x != nil {
+		return x.TopologyPolicies
+	}
+	return nil
+}
+
+func (x *NodeTopologyRequest) GetZones() []*v1alpha1.Zone {
+	if x != nil {
+		return x.Zones
+	}
+	return nil
+}
+
+type NodeTopologyResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *NodeTopologyResponse) Reset() {
+	*x = NodeTopologyResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_topology_updater_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *NodeTopologyResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NodeTopologyResponse) ProtoMessage() {}
+
+func (x *NodeTopologyResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_topology_updater_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use NodeTopologyResponse.ProtoReflect.Descriptor instead.
+func (*NodeTopologyResponse) Descriptor() ([]byte, []int) {
+	return file_topology_updater_proto_rawDescGZIP(), []int{1}
+}
+
+var File_topology_updater_proto protoreflect.FileDescriptor
+
+var file_topology_updater_proto_rawDesc = []byte{
+	0x0a, 0x16, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74,
+	0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f,
+	0x67, 0x79, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x72, 0x1a, 0x66, 0x67, 0x69, 0x74, 0x68, 0x75,
+	0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x38, 0x73, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67,
+	0x79, 0x61, 0x77, 0x61, 0x72, 0x65, 0x73, 0x63, 0x68, 0x65, 0x64, 0x77, 0x67, 0x2f, 0x6e, 0x6f,
+	0x64, 0x65, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f,
+	0x67, 0x79, 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
+	0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
+	0x31, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x22, 0xa6, 0x01, 0x0a, 0x13, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f,
+	0x67, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x66, 0x64,
+	0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x6e, 0x66, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f,
+	0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e,
+	0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x6f, 0x70, 0x6f, 0x6c,
+	0x6f, 0x67, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
+	0x28, 0x09, 0x52, 0x10, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x50, 0x6f, 0x6c, 0x69,
+	0x63, 0x69, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x05, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x04, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x5a,
+	0x6f, 0x6e, 0x65, 0x52, 0x05, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x4e, 0x6f,
+	0x64, 0x65, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x32, 0x71, 0x0a, 0x0c, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f,
+	0x67, 0x79, 0x12, 0x61, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
+	0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x12, 0x24, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c,
+	0x6f, 0x67, 0x79, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x72, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x54,
+	0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25,
+	0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x72,
+	0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x38, 0x5a, 0x36, 0x73, 0x69, 0x67, 0x73, 0x2e, 0x6b, 0x38,
+	0x73, 0x2e, 0x69, 0x6f, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72,
+	0x65, 0x2d, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
+	0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x72, 0x62,
+	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_topology_updater_proto_rawDescOnce sync.Once
+	file_topology_updater_proto_rawDescData = file_topology_updater_proto_rawDesc
+)
+
+func file_topology_updater_proto_rawDescGZIP() []byte {
+	file_topology_updater_proto_rawDescOnce.Do(func() {
+		file_topology_updater_proto_rawDescData = protoimpl.X.CompressGZIP(file_topology_updater_proto_rawDescData)
+	})
+	return file_topology_updater_proto_rawDescData
+}
+
+var file_topology_updater_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_topology_updater_proto_goTypes = []interface{}{
+	(*NodeTopologyRequest)(nil),  // 0: topologyupdater.NodeTopologyRequest
+	(*NodeTopologyResponse)(nil), // 1: topologyupdater.NodeTopologyResponse
+	(*v1alpha1.Zone)(nil),        // 2: v1alpha1.Zone
+}
+var file_topology_updater_proto_depIdxs = []int32{
+	2, // 0: topologyupdater.NodeTopologyRequest.zones:type_name -> v1alpha1.Zone
+	0, // 1: topologyupdater.NodeTopology.UpdateNodeTopology:input_type -> topologyupdater.NodeTopologyRequest
+	1, // 2: topologyupdater.NodeTopology.UpdateNodeTopology:output_type -> topologyupdater.NodeTopologyResponse
+	2, // [2:3] is the sub-list for method output_type
+	1, // [1:2] is the sub-list for method input_type
+	1, // [1:1] is the sub-list for extension type_name
+	1, // [1:1] is the sub-list for extension extendee
+	0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_topology_updater_proto_init() }
+func file_topology_updater_proto_init() {
+	if File_topology_updater_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_topology_updater_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*NodeTopologyRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_topology_updater_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*NodeTopologyResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_topology_updater_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   2,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_topology_updater_proto_goTypes,
+		DependencyIndexes: file_topology_updater_proto_depIdxs,
+		MessageInfos:      file_topology_updater_proto_msgTypes,
+	}.Build()
+	File_topology_updater_proto = out.File
+	file_topology_updater_proto_rawDesc = nil
+	file_topology_updater_proto_goTypes = nil
+	file_topology_updater_proto_depIdxs = nil
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConnInterface
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion6
+
+// NodeTopologyClient is the client API for NodeTopology service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type NodeTopologyClient interface {
+	UpdateNodeTopology(ctx context.Context, in *NodeTopologyRequest, opts ...grpc.CallOption) (*NodeTopologyResponse, error)
+}
+
+type nodeTopologyClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewNodeTopologyClient(cc grpc.ClientConnInterface) NodeTopologyClient {
+	return &nodeTopologyClient{cc}
+}
+
+func (c *nodeTopologyClient) UpdateNodeTopology(ctx context.Context, in *NodeTopologyRequest, opts ...grpc.CallOption) (*NodeTopologyResponse, error) {
+	out := new(NodeTopologyResponse)
+	err := c.cc.Invoke(ctx, "/topologyupdater.NodeTopology/UpdateNodeTopology", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// NodeTopologyServer is the server API for NodeTopology service.
+type NodeTopologyServer interface {
+	UpdateNodeTopology(context.Context, *NodeTopologyRequest) (*NodeTopologyResponse, error)
+}
+
+// UnimplementedNodeTopologyServer can be embedded to have forward compatible implementations.
+type UnimplementedNodeTopologyServer struct {
+}
+
+func (*UnimplementedNodeTopologyServer) UpdateNodeTopology(context.Context, *NodeTopologyRequest) (*NodeTopologyResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UpdateNodeTopology not implemented")
+}
+
+func RegisterNodeTopologyServer(s *grpc.Server, srv NodeTopologyServer) {
+	s.RegisterService(&_NodeTopology_serviceDesc, srv)
+}
+
+func _NodeTopology_UpdateNodeTopology_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(NodeTopologyRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(NodeTopologyServer).UpdateNodeTopology(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/topologyupdater.NodeTopology/UpdateNodeTopology",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(NodeTopologyServer).UpdateNodeTopology(ctx, req.(*NodeTopologyRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _NodeTopology_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "topologyupdater.NodeTopology",
+	HandlerType: (*NodeTopologyServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "UpdateNodeTopology",
+			Handler:    _NodeTopology_UpdateNodeTopology_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "topology-updater.proto",
+}
diff --git a/pkg/topologyupdater/topology-updater.proto b/pkg/topologyupdater/topology-updater.proto
new file mode 100644
index 000000000..2cbcc4497
--- /dev/null
+++ b/pkg/topologyupdater/topology-updater.proto
@@ -0,0 +1,35 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+syntax = "proto3";
+
+option go_package = "sigs.k8s.io/node-feature-discovery/pkg/topologyupdater";
+import "github.com/k8stopologyawareschedwg/noderesourcetopology-api/pkg/apis/topology/v1alpha1/generated.proto";
+
+package topologyupdater;
+
+service NodeTopology{
+    rpc UpdateNodeTopology(NodeTopologyRequest) returns (NodeTopologyResponse);
+}
+
+message NodeTopologyRequest {
+    string nfd_version = 1;
+    string node_name = 2;
+    repeated string topology_policies = 3;
+    repeated v1alpha1.Zone zones = 4;
+}
+
+message NodeTopologyResponse {
+}
diff --git a/pkg/utils/kubernetes.go b/pkg/utils/kubernetes.go
deleted file mode 100644
index 4dd6ba09f..000000000
--- a/pkg/utils/kubernetes.go
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Copyright 2022 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package utils
-
-import (
-	"os"
-	"strings"
-)
-
-// GetKubernetesNamespace returns the kubernetes namespace we're running under,
-// or an empty string if the namespace cannot be determined.
-func GetKubernetesNamespace() string {
-	const kubernetesNamespaceFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
-	if _, err := os.Stat(kubernetesNamespaceFilePath); err == nil {
-		data, err := os.ReadFile(kubernetesNamespaceFilePath)
-		if err == nil {
-			return strings.TrimSpace(string(data))
-		}
-	}
-	return os.Getenv("KUBERNETES_NAMESPACE")
-}


Test patch:
diff --git a/cmd/nfd-topology-updater/main_test.go b/cmd/nfd-topology-updater/main_test.go
index b7bdd06f3..dd2ba86e0 100644
--- a/cmd/nfd-topology-updater/main_test.go
+++ b/cmd/nfd-topology-updater/main_test.go
@@ -87,10 +87,16 @@ func TestArgsParse(t *testing.T) {
 				"-no-publish",
 				"-sleep-interval=30s",
 				"-kubelet-config-uri=file:///path/testconfig.yaml",
-				"-podresources-socket=/path/testkubelet.sock")
+				"-podresources-socket=/path/testkubelet.sock",
+				"-ca-file=ca",
+				"-cert-file=crt",
+				"-key-file=key")
 
 			Convey("-no-publish is set and args.sources is set to appropriate values", func() {
 				So(args.NoPublish, ShouldBeTrue)
+				So(args.CaFile, ShouldEqual, "ca")
+				So(args.CertFile, ShouldEqual, "crt")
+				So(args.KeyFile, ShouldEqual, "key")
 				So(finderArgs.SleepInterval, ShouldEqual, 30*time.Second)
 				So(finderArgs.KubeletConfigURI, ShouldEqual, "file:///path/testconfig.yaml")
 				So(finderArgs.PodResourceSocketPath, ShouldEqual, "/path/testkubelet.sock")
diff --git a/pkg/nfd-client/topology-updater/nfd-topology-updater_test.go b/pkg/nfd-client/topology-updater/nfd-topology-updater_test.go
new file mode 100644
index 000000000..9f8434b99
--- /dev/null
+++ b/pkg/nfd-client/topology-updater/nfd-topology-updater_test.go
@@ -0,0 +1,169 @@
+/*
+Copyright 2021 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package topologyupdater_test
+
+import (
+	"fmt"
+	"os"
+	"testing"
+	"time"
+
+	v1alpha1 "github.com/k8stopologyawareschedwg/noderesourcetopology-api/pkg/apis/topology/v1alpha1"
+	. "github.com/smartystreets/goconvey/convey"
+	"k8s.io/apimachinery/pkg/api/resource"
+	nfdclient "sigs.k8s.io/node-feature-discovery/pkg/nfd-client"
+	u "sigs.k8s.io/node-feature-discovery/pkg/nfd-client/topology-updater"
+	nfdmaster "sigs.k8s.io/node-feature-discovery/pkg/nfd-master"
+	"sigs.k8s.io/node-feature-discovery/pkg/resourcemonitor"
+	"sigs.k8s.io/node-feature-discovery/test/data"
+)
+
+type testContext struct {
+	master nfdmaster.NfdMaster
+	errs   chan error
+}
+
+func setupTest(args *nfdmaster.Args) testContext {
+	// Fixed port and no-publish, for convenience
+	args.NoPublish = true
+	args.Port = 8192
+	m, err := nfdmaster.NewNfdMaster(args)
+	if err != nil {
+		fmt.Printf("Test setup failed: %v\n", err)
+		os.Exit(1)
+	}
+	ctx := testContext{master: m, errs: make(chan error)}
+
+	// Run nfd-master instance, intended to be used as the server counterpart
+	go func() {
+		ctx.errs <- ctx.master.Run()
+		close(ctx.errs)
+	}()
+	ready := ctx.master.WaitForReady(5 * time.Second)
+	if !ready {
+		fmt.Println("Test setup failed: timeout while waiting for nfd-master")
+		os.Exit(1)
+	}
+
+	return ctx
+}
+
+func teardownTest(ctx testContext) {
+	ctx.master.Stop()
+	for e := range ctx.errs {
+		if e != nil {
+			fmt.Printf("Error in test context: %v\n", e)
+			os.Exit(1)
+		}
+	}
+}
+
+func TestNewTopologyUpdater(t *testing.T) {
+	Convey("When initializing new NfdTopologyUpdater instance", t, func() {
+		Convey("When one of -cert-file, -key-file or -ca-file is missing", func() {
+			tmPolicy := "fake-topology-manager-policy"
+			_, err := u.NewTopologyUpdater(u.Args{Args: nfdclient.Args{CertFile: "crt", KeyFile: "key"}}, resourcemonitor.Args{}, tmPolicy)
+			_, err2 := u.NewTopologyUpdater(u.Args{Args: nfdclient.Args{KeyFile: "key", CaFile: "ca"}}, resourcemonitor.Args{}, tmPolicy)
+			_, err3 := u.NewTopologyUpdater(u.Args{Args: nfdclient.Args{CertFile: "crt", CaFile: "ca"}}, resourcemonitor.Args{}, tmPolicy)
+			Convey("An error should be returned", func() {
+				So(err, ShouldNotBeNil)
+				So(err2, ShouldNotBeNil)
+				So(err3, ShouldNotBeNil)
+			})
+		})
+	})
+}
+
+func TestUpdate(t *testing.T) {
+	ctx := setupTest(&nfdmaster.Args{})
+	resourceInfo := v1alpha1.ResourceInfoList{
+		v1alpha1.ResourceInfo{
+			Name:        "cpu",
+			Available:   resource.MustParse("2"),
+			Allocatable: resource.MustParse("4"),
+			Capacity:    resource.MustParse("4"),
+		},
+	}
+	zones := v1alpha1.ZoneList{
+		v1alpha1.Zone{
+			Name:      "node-0",
+			Type:      "Node",
+			Resources: resourceInfo,
+		},
+	}
+	defer teardownTest(ctx)
+	Convey("When running nfd-topology-updater against nfd-master", t, func() {
+		Convey("When running as a Oneshot job with Zones", func() {
+			args := u.Args{
+				Oneshot: true,
+				Args: nfdclient.Args{
+					Server: "localhost:8192"},
+			}
+			updater, _ := u.NewTopologyUpdater(args, resourcemonitor.Args{}, "fake-topology-manager-policy")
+			err := updater.Update(zones)
+			Convey("No error should be returned", func() {
+				So(err, ShouldBeNil)
+			})
+		})
+	})
+}
+
+func TestRunTls(t *testing.T) {
+	masterArgs := &nfdmaster.Args{
+		CaFile:         data.FilePath("ca.crt"),
+		CertFile:       data.FilePath("nfd-test-master.crt"),
+		KeyFile:        data.FilePath("nfd-test-master.key"),
+		VerifyNodeName: false,
+	}
+	ctx := setupTest(masterArgs)
+	defer teardownTest(ctx)
+	Convey("When running nfd-worker against nfd-master with mutual TLS auth enabled", t, func() {
+		Convey("When publishing CRs obtained from Zones", func() {
+			resourceInfo := v1alpha1.ResourceInfoList{
+				v1alpha1.ResourceInfo{
+					Name:        "cpu",
+					Available:   resource.MustParse("2"),
+					Allocatable: resource.MustParse("4"),
+					Capacity:    resource.MustParse("4"),
+				},
+			}
+			zones := v1alpha1.ZoneList{
+				v1alpha1.Zone{
+					Name:      "node-0",
+					Type:      "Node",
+					Resources: resourceInfo,
+				},
+			}
+			updaterArgs := u.Args{
+				Args: nfdclient.Args{
+					CaFile:             data.FilePath("ca.crt"),
+					CertFile:           data.FilePath("nfd-test-topology-updater.crt"),
+					KeyFile:            data.FilePath("nfd-test-topology-updater.key"),
+					Server:             "localhost:8192",
+					ServerNameOverride: "nfd-test-master",
+				},
+				Oneshot: true,
+			}
+
+			updater, _ := u.NewTopologyUpdater(updaterArgs, resourcemonitor.Args{}, "fake-topology-manager-policy")
+			err := updater.Update(zones)
+			Convey("No error should be returned", func() {
+				So(err, ShouldBeNil)
+			})
+		})
+	})
+}
diff --git a/pkg/nfd-master/nfd-master-internal_test.go b/pkg/nfd-master/nfd-master-internal_test.go
index cf50e4906..fc522daec 100644
--- a/pkg/nfd-master/nfd-master-internal_test.go
+++ b/pkg/nfd-master/nfd-master-internal_test.go
@@ -61,7 +61,7 @@ func newMockMaster(apihelper apihelper.APIHelpers) *nfdMaster {
 	}
 }
 
-func TestUpdateNodeObject(t *testing.T) {
+func TestUpdateNodeFeatures(t *testing.T) {
 	Convey("When I update the node using fake client", t, func() {
 		fakeFeatureLabels := map[string]string{
 			nfdv1alpha1.FeatureLabelNs + "/source-feature.1": "1",
@@ -112,10 +112,10 @@ func TestUpdateNodeObject(t *testing.T) {
 			}
 
 			mockAPIHelper.On("GetClient").Return(mockClient, nil)
-			mockAPIHelper.On("GetNode", mockClient, mockNodeName).Return(mockNode, nil).Twice()
+			mockAPIHelper.On("GetNode", mockClient, mockNodeName).Return(mockNode, nil).Once()
 			mockAPIHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(metadataPatches))).Return(nil)
 			mockAPIHelper.On("PatchNodeStatus", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(statusPatches))).Return(nil)
-			err := mockMaster.updateNodeObject(mockClient, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources, nil)
+			err := mockMaster.updateNodeFeatures(mockClient, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources)
 
 			Convey("Error is nil", func() {
 				So(err, ShouldBeNil)
@@ -125,7 +125,7 @@ func TestUpdateNodeObject(t *testing.T) {
 		Convey("When I fail to update the node with feature labels", func() {
 			expectedError := fmt.Errorf("no client is passed, client:  <nil>")
 			mockAPIHelper.On("GetClient").Return(nil, expectedError)
-			err := mockMaster.updateNodeObject(nil, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources, nil)
+			err := mockMaster.updateNodeFeatures(nil, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources)
 
 			Convey("Error is produced", func() {
 				So(err, ShouldResemble, expectedError)
@@ -135,7 +135,7 @@ func TestUpdateNodeObject(t *testing.T) {
 		Convey("When I fail to get a mock client while updating feature labels", func() {
 			expectedError := fmt.Errorf("no client is passed, client:  <nil>")
 			mockAPIHelper.On("GetClient").Return(nil, expectedError)
-			err := mockMaster.updateNodeObject(nil, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources, nil)
+			err := mockMaster.updateNodeFeatures(nil, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources)
 
 			Convey("Error is produced", func() {
 				So(err, ShouldResemble, expectedError)
@@ -145,8 +145,8 @@ func TestUpdateNodeObject(t *testing.T) {
 		Convey("When I fail to get a mock node while updating feature labels", func() {
 			expectedError := errors.New("fake error")
 			mockAPIHelper.On("GetClient").Return(mockClient, nil)
-			mockAPIHelper.On("GetNode", mockClient, mockNodeName).Return(nil, expectedError).Twice()
-			err := mockMaster.updateNodeObject(mockClient, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources, nil)
+			mockAPIHelper.On("GetNode", mockClient, mockNodeName).Return(nil, expectedError).Once()
+			err := mockMaster.updateNodeFeatures(mockClient, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources)
 
 			Convey("Error is produced", func() {
 				So(err, ShouldEqual, expectedError)
@@ -156,9 +156,9 @@ func TestUpdateNodeObject(t *testing.T) {
 		Convey("When I fail to update a mock node while updating feature labels", func() {
 			expectedError := errors.New("fake error")
 			mockAPIHelper.On("GetClient").Return(mockClient, nil)
-			mockAPIHelper.On("GetNode", mockClient, mockNodeName).Return(mockNode, nil).Twice()
-			mockAPIHelper.On("PatchNode", mockClient, mockNodeName, mock.Anything).Return(expectedError).Twice()
-			err := mockMaster.updateNodeObject(mockClient, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources, nil)
+			mockAPIHelper.On("GetNode", mockClient, mockNodeName).Return(mockNode, nil).Once()
+			mockAPIHelper.On("PatchNode", mockClient, mockNodeName, mock.Anything).Return(expectedError).Once()
+			err := mockMaster.updateNodeFeatures(mockClient, mockNodeName, fakeFeatureLabels, fakeAnnotations, fakeExtResources)
 
 			Convey("Error is produced", func() {
 				So(err.Error(), ShouldEndWith, expectedError.Error())
@@ -294,7 +294,7 @@ func TestRemovingExtResources(t *testing.T) {
 
 func TestSetLabels(t *testing.T) {
 	Convey("When servicing SetLabels request", t, func() {
-		const workerName = mockNodeName
+		const workerName = "mock-worker"
 		const workerVer = "0.1-test"
 		mockHelper := &apihelper.MockAPIHelpers{}
 		mockMaster := newMockMaster(mockHelper)
@@ -324,7 +324,7 @@ func TestSetLabels(t *testing.T) {
 			}
 
 			mockHelper.On("GetClient").Return(mockClient, nil)
-			mockHelper.On("GetNode", mockClient, workerName).Return(mockNode, nil).Twice()
+			mockHelper.On("GetNode", mockClient, workerName).Return(mockNode, nil)
 			mockHelper.On("PatchNode", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedPatches))).Return(nil)
 			mockHelper.On("PatchNodeStatus", mockClient, mockNodeName, mock.MatchedBy(jsonPatchMatcher(expectedStatusPatches))).Return(nil)
 			_, err := mockMaster.SetLabels(mockCtx, mockReq)
diff --git a/test/e2e/node_feature_discovery.go b/test/e2e/node_feature_discovery.go
index e19144916..a11a1f0e5 100644
--- a/test/e2e/node_feature_discovery.go
+++ b/test/e2e/node_feature_discovery.go
@@ -34,7 +34,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	clientset "k8s.io/client-go/kubernetes"
 	"k8s.io/kubernetes/test/e2e/framework"
-	e2elog "k8s.io/kubernetes/test/e2e/framework"
+	e2elog "k8s.io/kubernetes/test/e2e/framework/log"
 	e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
 	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
 
@@ -115,7 +115,7 @@ var _ = SIGDescribe("Node Feature Discovery", func() {
 			// Launch nfd-master
 			By("Creating nfd master pod and nfd-master service")
 			imageOpt := testpod.SpecWithContainerImage(fmt.Sprintf("%s:%s", *dockerRepo, *dockerTag))
-			masterPod = e2epod.NewPodClient(f).CreateSync(testpod.NFDMaster(imageOpt))
+			masterPod = f.PodClient().CreateSync(testpod.NFDMaster(imageOpt))
 
 			// Create nfd-master service
 			nfdSvc, err := testutils.CreateService(f.ClientSet, f.Namespace.Name)
@@ -390,7 +390,7 @@ var _ = SIGDescribe("Node Feature Discovery", func() {
 		Context("and nfd-worker and NodeFeatureRules objects deployed", func() {
 			var extClient *extclient.Clientset
 			var nfdClient *nfdclient.Clientset
-			var crds []*apiextensionsv1.CustomResourceDefinition
+			var crd *apiextensionsv1.CustomResourceDefinition
 
 			BeforeEach(func() {
 				// Create clients for apiextensions and our CRD api
@@ -398,17 +398,15 @@ var _ = SIGDescribe("Node Feature Discovery", func() {
 				nfdClient = nfdclient.NewForConfigOrDie(f.ClientConfig())
 
 				// Create CRDs
-				By("Creating NFD CRDs")
+				By("Creating NodeFeatureRule CRD")
 				var err error
-				crds, err = testutils.CreateNfdCRDs(extClient)
+				crd, err = testutils.CreateNodeFeatureRulesCRD(extClient)
 				Expect(err).NotTo(HaveOccurred())
 			})
 
 			AfterEach(func() {
-				for _, crd := range crds {
-					err := extClient.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{})
-					Expect(err).NotTo(HaveOccurred())
-				}
+				err := extClient.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{})
+				Expect(err).NotTo(HaveOccurred())
 			})
 
 			It("custom labels from the NodeFeatureRule rules should be created", func() {
@@ -440,13 +438,13 @@ core:
 					"feature.node.kubernetes.io/e2e-instance-test-1":  "true"}
 
 				By("Creating NodeFeatureRules #1")
-				Expect(testutils.CreateNodeFeatureRulesFromFile(nfdClient, "nodefeaturerule-1.yaml")).NotTo(HaveOccurred())
+				Expect(testutils.CreateNodeFeatureRuleFromFile(nfdClient, "nodefeaturerule-1.yaml")).NotTo(HaveOccurred())
 
 				By("Verifying node labels from NodeFeatureRules #1")
 				Expect(waitForNfdNodeLabels(f.ClientSet, expected)).NotTo(HaveOccurred())
 
 				By("Creating NodeFeatureRules #2")
-				Expect(testutils.CreateNodeFeatureRulesFromFile(nfdClient, "nodefeaturerule-2.yaml")).NotTo(HaveOccurred())
+				Expect(testutils.CreateNodeFeatureRuleFromFile(nfdClient, "nodefeaturerule-2.yaml")).NotTo(HaveOccurred())
 
 				// Add features from NodeFeatureRule #2
 				expected["feature.node.kubernetes.io/e2e-matchany-test-1"] = "true"
diff --git a/test/e2e/topology_updater.go b/test/e2e/topology_updater.go
index af6991994..05e2b65f2 100644
--- a/test/e2e/topology_updater.go
+++ b/test/e2e/topology_updater.go
@@ -19,11 +19,9 @@ package e2e
 import (
 	"context"
 	"fmt"
-	"time"
-
 	"k8s.io/apimachinery/pkg/api/resource"
+	"time"
 
-	"github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 
@@ -38,9 +36,9 @@ import (
 	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
 	"k8s.io/kubernetes/test/e2e/framework"
 	"k8s.io/kubernetes/test/e2e/framework/kubelet"
+	e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
 	admissionapi "k8s.io/pod-security-admission/api"
 
-	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
 	testutils "sigs.k8s.io/node-feature-discovery/test/e2e/utils"
 	testds "sigs.k8s.io/node-feature-discovery/test/e2e/utils/daemonset"
 	testpod "sigs.k8s.io/node-feature-discovery/test/e2e/utils/pod"
@@ -74,9 +72,18 @@ var _ = SIGDescribe("Node Feature Discovery topology updater", func() {
 		By("Creating the node resource topologies CRD")
 		Expect(testutils.CreateNodeResourceTopologies(extClient)).ToNot(BeNil())
 
-		By("Configuring RBAC")
 		Expect(testutils.ConfigureRBAC(f.ClientSet, f.Namespace.Name)).NotTo(HaveOccurred())
 
+		imageOpt := testpod.SpecWithContainerImage(fmt.Sprintf("%s:%s", *dockerRepo, *dockerTag))
+		f.PodClient().CreateSync(testpod.NFDMaster(imageOpt))
+
+		// Create nfd-master service
+		masterService, err := testutils.CreateService(f.ClientSet, f.Namespace.Name)
+		Expect(err).NotTo(HaveOccurred())
+
+		By("Waiting for the nfd-master service to be up")
+		Expect(e2enetwork.WaitForService(f.ClientSet, f.Namespace.Name, masterService.Name, true, time.Second, 10*time.Second)).NotTo(HaveOccurred())
+
 		By("Creating nfd-topology-updater daemonset")
 		topologyUpdaterDaemonSet, err = f.ClientSet.AppsV1().DaemonSets(f.Namespace.Name).Create(context.TODO(), topologyUpdaterDaemonSet, metav1.CreateOptions{})
 		Expect(err).NotTo(HaveOccurred())
@@ -99,16 +106,16 @@ var _ = SIGDescribe("Node Feature Discovery topology updater", func() {
 		Expect(err).NotTo(HaveOccurred())
 	})
 
-	ginkgo.AfterEach(func() {
-		framework.Logf("Node Feature Discovery topology updater CRD and RBAC removal")
+	// TODO: replace with regular AfterEach once we have https://github.com/kubernetes/kubernetes/pull/111998 in
+	f.AddAfterEach("Node Feature Discovery topology updater CRD and RBAC removal", func(f *framework.Framework, failed bool) {
 		err := testutils.DeconfigureRBAC(f.ClientSet, f.Namespace.Name)
 		if err != nil {
-			framework.Failf("AfterEach: Failed to delete RBAC resources: %v", err)
+			framework.Logf("failed to delete RBAC resources: %v", err)
 		}
 	})
 
-	Context("with topology-updater daemonset running", func() {
-		ginkgo.BeforeEach(func() {
+	Context("with single nfd-master pod", func() {
+		BeforeEach(func() {
 			cfg, err := testutils.GetConfig()
 			Expect(err).ToNot(HaveOccurred())
 
@@ -132,7 +139,7 @@ var _ = SIGDescribe("Node Feature Discovery topology updater", func() {
 			sleeperPod := testpod.BestEffortSleeper()
 
 			podMap := make(map[string]*corev1.Pod)
-			pod := e2epod.NewPodClient(f).CreateSync(sleeperPod)
+			pod := f.PodClient().CreateSync(sleeperPod)
 			podMap[pod.Name] = pod
 			defer testpod.DeleteAsync(f, podMap)
 
@@ -177,7 +184,7 @@ var _ = SIGDescribe("Node Feature Discovery topology updater", func() {
 				}))
 
 			podMap := make(map[string]*corev1.Pod)
-			pod := e2epod.NewPodClient(f).CreateSync(sleeperPod)
+			pod := f.PodClient().CreateSync(sleeperPod)
 			podMap[pod.Name] = pod
 			defer testpod.DeleteAsync(f, podMap)
 
@@ -232,7 +239,7 @@ var _ = SIGDescribe("Node Feature Discovery topology updater", func() {
 			sleeperPod.Spec.NodeName = topologyUpdaterNode.Name
 
 			podMap := make(map[string]*corev1.Pod)
-			pod := e2epod.NewPodClient(f).CreateSync(sleeperPod)
+			pod := f.PodClient().CreateSync(sleeperPod)
 			podMap[pod.Name] = pod
 			defer testpod.DeleteAsync(f, podMap)
 
diff --git a/test/e2e/utils/config.go b/test/e2e/utils/config.go
index 2620fdac7..ab8b3dbfc 100644
--- a/test/e2e/utils/config.go
+++ b/test/e2e/utils/config.go
@@ -21,7 +21,7 @@ import (
 	"os"
 	"regexp"
 
-	e2elog "k8s.io/kubernetes/test/e2e/framework"
+	e2elog "k8s.io/kubernetes/test/e2e/framework/log"
 
 	"sigs.k8s.io/yaml"
 )
diff --git a/test/e2e/utils/crd.go b/test/e2e/utils/crd.go
index 76ea53c00..5a45e642d 100644
--- a/test/e2e/utils/crd.go
+++ b/test/e2e/utils/crd.go
@@ -17,7 +17,6 @@ limitations under the License.
 package utils
 
 import (
-	"bytes"
 	"context"
 	"fmt"
 	"os"
@@ -37,104 +36,69 @@ import (
 
 var packagePath string
 
-// CreateNfdCRDs creates the NodeFeatureRule CRD in the API server.
-func CreateNfdCRDs(cli extclient.Interface) ([]*apiextensionsv1.CustomResourceDefinition, error) {
-	crds, err := crdsFromFile(filepath.Join(packagePath, "..", "..", "..", "deployment", "base", "nfd-crds", "nfd-api-crds.yaml"))
+// CreateNodeFeatureRulesCRD creates the NodeFeatureRule CRD in the API server.
+func CreateNodeFeatureRulesCRD(cli extclient.Interface) (*apiextensionsv1.CustomResourceDefinition, error) {
+	crd, err := crdFromFile(filepath.Join(packagePath, "..", "..", "..", "deployment", "base", "nfd-crds", "nodefeaturerule-crd.yaml"))
 	if err != nil {
 		return nil, err
 	}
 
-	newCRDs := make([]*apiextensionsv1.CustomResourceDefinition, len(crds))
-	for i, crd := range crds {
-		// Delete existing CRD (if any) with this we also get rid of stale objects
-		err = cli.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{})
-		if err != nil && !errors.IsNotFound(err) {
-			return nil, fmt.Errorf("failed to delete NodeFeatureRule CRD: %w", err)
-		}
-		newCRDs[i], err = cli.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), crd, metav1.CreateOptions{})
-		if err != nil {
-			return nil, err
-		}
+	// Delete existing CRD (if any) with this we also get rid of stale objects
+	err = cli.ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.Name, metav1.DeleteOptions{})
+	if err != nil && !errors.IsNotFound(err) {
+		return nil, fmt.Errorf("failed to delete NodeFeatureRule CRD: %w", err)
 	}
-	return newCRDs, nil
+
+	return cli.ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), crd, metav1.CreateOptions{})
 }
 
 // CreateNodeFeatureRuleFromFile creates a NodeFeatureRule object from a given file located under test data directory.
-func CreateNodeFeatureRulesFromFile(cli nfdclientset.Interface, filename string) error {
-	objs, err := nodeFeatureRulesFromFile(filepath.Join(packagePath, "..", "data", filename))
+func CreateNodeFeatureRuleFromFile(cli nfdclientset.Interface, filename string) error {
+	obj, err := nodeFeatureRuleFromFile(filepath.Join(packagePath, "..", "data", filename))
 	if err != nil {
 		return err
 	}
-
-	for _, obj := range objs {
-		if _, err = cli.NfdV1alpha1().NodeFeatureRules().Create(context.TODO(), obj, metav1.CreateOptions{}); err != nil {
-			return err
-		}
-	}
-	return nil
+	_, err = cli.NfdV1alpha1().NodeFeatureRules().Create(context.TODO(), obj, metav1.CreateOptions{})
+	return err
 }
 
-func apiObjsFromFile(path string, decoder apiruntime.Decoder) ([]apiruntime.Object, error) {
+func apiObjFromFile(path string, decoder apiruntime.Decoder) (apiruntime.Object, error) {
 	data, err := os.ReadFile(path)
 	if err != nil {
 		return nil, err
 	}
 
-	// TODO: find out a nicer way to decode multiple api objects from a single
-	// file (K8s must have that somewhere)
-	split := bytes.Split(data, []byte("---"))
-	objs := []apiruntime.Object{}
-
-	for _, slice := range split {
-		if len(slice) == 0 {
-			continue
-		}
-		obj, _, err := decoder.Decode(slice, nil, nil)
-		if err != nil {
-			return nil, err
-		}
-		objs = append(objs, obj)
-	}
-	return objs, err
+	obj, _, err := decoder.Decode(data, nil, nil)
+	return obj, err
 }
 
-// crdsFromFile creates a CustomResourceDefinition API object from a file.
-func crdsFromFile(path string) ([]*apiextensionsv1.CustomResourceDefinition, error) {
-	objs, err := apiObjsFromFile(path, scheme.Codecs.UniversalDeserializer())
+// crdFromFile creates a CustomResourceDefinition API object from a file.
+func crdFromFile(path string) (*apiextensionsv1.CustomResourceDefinition, error) {
+	obj, err := apiObjFromFile(path, scheme.Codecs.UniversalDeserializer())
 	if err != nil {
 		return nil, err
 	}
 
-	crds := make([]*apiextensionsv1.CustomResourceDefinition, len(objs))
-
-	for i, obj := range objs {
-		var ok bool
-		crds[i], ok = obj.(*apiextensionsv1.CustomResourceDefinition)
-		if !ok {
-			return nil, fmt.Errorf("unexpected type %T when reading %q", obj, path)
-		}
+	crd, ok := obj.(*apiextensionsv1.CustomResourceDefinition)
+	if !ok {
+		return nil, fmt.Errorf("unexpected type %t when reading %q", obj, path)
 	}
 
-	return crds, nil
+	return crd, nil
 }
 
-func nodeFeatureRulesFromFile(path string) ([]*nfdv1alpha1.NodeFeatureRule, error) {
-	objs, err := apiObjsFromFile(path, nfdscheme.Codecs.UniversalDeserializer())
+func nodeFeatureRuleFromFile(path string) (*nfdv1alpha1.NodeFeatureRule, error) {
+	obj, err := apiObjFromFile(path, nfdscheme.Codecs.UniversalDeserializer())
 	if err != nil {
 		return nil, err
 	}
 
-	crs := make([]*nfdv1alpha1.NodeFeatureRule, len(objs))
-
-	for i, obj := range objs {
-		var ok bool
-		crs[i], ok = obj.(*nfdv1alpha1.NodeFeatureRule)
-		if !ok {
-			return nil, fmt.Errorf("unexpected type %t when reading %q", obj, path)
-		}
+	crd, ok := obj.(*nfdv1alpha1.NodeFeatureRule)
+	if !ok {
+		return nil, fmt.Errorf("unexpected type %t when reading %q", obj, path)
 	}
 
-	return crs, nil
+	return crd, nil
 }
 
 func init() {
diff --git a/test/e2e/utils/pod/pod.go b/test/e2e/utils/pod/pod.go
index 674f38e6c..82485569c 100644
--- a/test/e2e/utils/pod/pod.go
+++ b/test/e2e/utils/pod/pod.go
@@ -31,9 +31,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/wait"
 	clientset "k8s.io/client-go/kubernetes"
 	"k8s.io/kubectl/pkg/util/podutils"
-
 	"k8s.io/kubernetes/test/e2e/framework"
-	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
 	"k8s.io/utils/pointer"
 
 	"sigs.k8s.io/node-feature-discovery/test/e2e/utils"
@@ -113,7 +111,7 @@ func DeleteSyncByName(f *framework.Framework, podName string) {
 	delOpts := metav1.DeleteOptions{
 		GracePeriodSeconds: &gp,
 	}
-	e2epod.NewPodClient(f).DeleteSync(podName, delOpts, e2epod.DefaultPodDeletionTimeout)
+	f.PodClient().DeleteSync(podName, delOpts, framework.DefaultPodDeletionTimeout)
 }
 
 type SpecOption func(spec *corev1.PodSpec)
@@ -369,7 +367,8 @@ func NFDTopologyUpdaterSpec(kc utils.KubeletConfig, opts ...SpecOption) *corev1.
 					"--kubelet-config-uri=file:///podresources/config.yaml",
 					"--podresources-socket=unix:///podresources/kubelet.sock",
 					"--sleep-interval=3s",
-					"--watch-namespace=rte"},
+					"--watch-namespace=rte",
+					"--server=nfd-master-e2e:8080"},
 				Env: []corev1.EnvVar{
 					{
 						Name: "NODE_NAME",
@@ -384,9 +383,9 @@ func NFDTopologyUpdaterSpec(kc utils.KubeletConfig, opts ...SpecOption) *corev1.
 					Capabilities: &corev1.Capabilities{
 						Drop: []corev1.Capability{"ALL"},
 					},
-					RunAsUser:                pointer.Int64(0),
-					ReadOnlyRootFilesystem:   pointer.Bool(true),
-					AllowPrivilegeEscalation: pointer.Bool(false),
+					RunAsUser:                pointer.Int64Ptr(0),
+					ReadOnlyRootFilesystem:   pointer.BoolPtr(true),
+					AllowPrivilegeEscalation: pointer.BoolPtr(false),
 				},
 				VolumeMounts: []corev1.VolumeMount{
 					{
diff --git a/test/e2e/utils/rbac.go b/test/e2e/utils/rbac.go
index 9d851576b..14add8009 100644
--- a/test/e2e/utils/rbac.go
+++ b/test/e2e/utils/rbac.go
@@ -133,6 +133,15 @@ func createClusterRoleMaster(cs clientset.Interface) (*rbacv1.ClusterRole, error
 				Resources: []string{"nodefeaturerules"},
 				Verbs:     []string{"get", "list", "watch"},
 			},
+			{
+				APIGroups: []string{"topology.node.k8s.io"},
+				Resources: []string{"noderesourcetopologies"},
+				Verbs: []string{
+					"create",
+					"get",
+					"update",
+				},
+			},
 		},
 	}
 	if *openShift {
@@ -163,15 +172,6 @@ func createClusterRoleTopologyUpdater(cs clientset.Interface) (*rbacv1.ClusterRo
 				Resources: []string{"pods"},
 				Verbs:     []string{"get", "list", "watch"},
 			},
-			{
-				APIGroups: []string{"topology.node.k8s.io"},
-				Resources: []string{"noderesourcetopologies"},
-				Verbs: []string{
-					"create",
-					"get",
-					"update",
-				},
-			},
 		},
 	}
 	if *openShift {