From 6c544d0c84776b034661f205a5fb65cea29505951b8976a470b0b82618e15333 Mon Sep 17 00:00:00 2001 From: Vasily Ulyanov Date: Wed, 16 Aug 2023 15:02:36 +0000 Subject: [PATCH 1/2] Accepting request 1104204 from home:vulyanov:branches:Virtualization - Bump client-go (fix possible panic in discovery) 0011-Fix-Aggregated-Discovery.patch - Wait for new hotplug attachment pod to be ready 0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch - Adapt the storage tests to the new populators flow 0013-Adapt-e2e-tests-to-CDI-1.57.0.patch OBS-URL: https://build.opensuse.org/request/show/1104204 OBS-URL: https://build.opensuse.org/package/show/Virtualization/kubevirt?expand=0&rev=130 --- 0011-Fix-Aggregated-Discovery.patch | 751 ++++++++++++++++++ ...w-hotplug-attachment-pod-to-be-ready.patch | 382 +++++++++ 0013-Adapt-e2e-tests-to-CDI-1.57.0.patch | 194 +++++ kubevirt.changes | 10 + kubevirt.spec | 3 + 5 files changed, 1340 insertions(+) create mode 100644 0011-Fix-Aggregated-Discovery.patch create mode 100644 0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch create mode 100644 0013-Adapt-e2e-tests-to-CDI-1.57.0.patch diff --git a/0011-Fix-Aggregated-Discovery.patch b/0011-Fix-Aggregated-Discovery.patch new file mode 100644 index 0000000..2ce9464 --- /dev/null +++ b/0011-Fix-Aggregated-Discovery.patch @@ -0,0 +1,751 @@ +From 22a734153b37c3706069cb7a0a8eb92167040b9e Mon Sep 17 00:00:00 2001 +From: Luboslav Pivarc +Date: Wed, 9 Aug 2023 11:51:10 +0200 +Subject: [PATCH] Fix Aggregated Discovery + +Bump client-go dependency to update bug +with Aggregated Discovery + +Signed-off-by: Luboslav Pivarc +--- + go.mod | 52 +++---- + go.sum | 32 ++--- + staging/src/kubevirt.io/client-go/go.mod | 50 +++---- + staging/src/kubevirt.io/client-go/go.sum | 24 ++-- + .../discovery/aggregated_discovery.go | 58 +++++--- + .../client-go/tools/cache/controller.go | 22 +-- + .../client-go/tools/cache/delta_fifo.go | 135 ++++++++++++------ + .../client-go/tools/cache/shared_informer.go | 8 +- + vendor/modules.txt | 60 ++++---- + 9 files changed, 241 insertions(+), 200 deletions(-) + +diff --git a/go.mod b/go.mod +index 64a39278f..8bc66a1c5 100644 +--- a/go.mod ++++ b/go.mod +@@ -65,11 +65,11 @@ require ( + gopkg.in/cheggaaa/pb.v1 v1.0.28 + gopkg.in/yaml.v2 v2.4.0 + k8s.io/api v0.27.1 +- k8s.io/apiextensions-apiserver v0.26.3 ++ k8s.io/apiextensions-apiserver v0.26.4 + k8s.io/apimachinery v0.27.1 + k8s.io/client-go v12.0.0+incompatible + k8s.io/klog/v2 v2.90.1 +- k8s.io/kube-aggregator v0.26.3 ++ k8s.io/kube-aggregator v0.26.4 + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f + k8s.io/kubectl v0.0.0-00010101000000-000000000000 + k8s.io/utils v0.0.0-20230505201702-9f6742963106 +@@ -165,32 +165,32 @@ replace ( + github.com/openshift/client-go => github.com/openshift/client-go v0.0.0-20210112165513-ebc401615f47 + github.com/operator-framework/operator-lifecycle-manager => github.com/operator-framework/operator-lifecycle-manager v0.0.0-20190128024246-5eb7ae5bdb7a + +- k8s.io/api => k8s.io/api v0.26.3 +- k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.3 +- k8s.io/apimachinery => k8s.io/apimachinery v0.26.3 +- k8s.io/apiserver => k8s.io/apiserver v0.26.3 +- k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.3 +- k8s.io/client-go => k8s.io/client-go v0.26.3 +- k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.3 +- k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.3 +- k8s.io/code-generator => k8s.io/code-generator v0.26.3 +- k8s.io/component-base => k8s.io/component-base v0.26.3 +- k8s.io/cri-api => k8s.io/cri-api v0.26.3 +- k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.3 ++ k8s.io/api => k8s.io/api v0.26.4 ++ k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.4 ++ k8s.io/apimachinery => k8s.io/apimachinery v0.26.4 ++ k8s.io/apiserver => k8s.io/apiserver v0.26.4 ++ k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.4 ++ k8s.io/client-go => k8s.io/client-go v0.26.4 ++ k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.4 ++ k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.4 ++ k8s.io/code-generator => k8s.io/code-generator v0.26.4 ++ k8s.io/component-base => k8s.io/component-base v0.26.4 ++ k8s.io/cri-api => k8s.io/cri-api v0.26.4 ++ k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.4 + k8s.io/klog => k8s.io/klog v0.4.0 +- k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.3 +- k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.3 ++ k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.4 ++ k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.4 + k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 +- k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.3 +- k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.3 +- k8s.io/kubectl => k8s.io/kubectl v0.26.3 +- k8s.io/kubelet => k8s.io/kubelet v0.26.3 +- k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.3 +- k8s.io/metrics => k8s.io/metrics v0.26.3 +- k8s.io/node-api => k8s.io/node-api v0.26.3 +- k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.3 +- k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.26.3 +- k8s.io/sample-controller => k8s.io/sample-controller v0.26.3 ++ k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.4 ++ k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.4 ++ k8s.io/kubectl => k8s.io/kubectl v0.26.4 ++ k8s.io/kubelet => k8s.io/kubelet v0.26.4 ++ k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.4 ++ k8s.io/metrics => k8s.io/metrics v0.26.4 ++ k8s.io/node-api => k8s.io/node-api v0.26.4 ++ k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.4 ++ k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.26.4 ++ k8s.io/sample-controller => k8s.io/sample-controller v0.26.4 + + kubevirt.io/api => ./staging/src/kubevirt.io/api + kubevirt.io/client-go => ./staging/src/kubevirt.io/client-go +diff --git a/go.sum b/go.sum +index fdd556ec6..3f7fe3ce3 100644 +--- a/go.sum ++++ b/go.sum +@@ -1927,17 +1927,17 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt + honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= + honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= + howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +-k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= +-k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= +-k8s.io/apiextensions-apiserver v0.26.3 h1:5PGMm3oEzdB1W/FTMgGIDmm100vn7IaUP5er36dB+YE= +-k8s.io/apiextensions-apiserver v0.26.3/go.mod h1:jdA5MdjNWGP+njw1EKMZc64xAT5fIhN6VJrElV3sfpQ= +-k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= +-k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +-k8s.io/apiserver v0.26.3/go.mod h1:CJe/VoQNcXdhm67EvaVjYXxR3QyfwpceKPuPaeLibTA= +-k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= +-k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ= +-k8s.io/code-generator v0.26.3/go.mod h1:ryaiIKwfxEJEaywEzx3dhWOydpVctKYbqLajJf0O8dI= +-k8s.io/component-base v0.26.3/go.mod h1:5kj1kZYwSC6ZstHJN7oHBqcJC6yyn41eR+Sqa/mQc8E= ++k8s.io/api v0.26.4 h1:qSG2PmtcD23BkYiWfoYAcak870eF/hE7NNYBYavTT94= ++k8s.io/api v0.26.4/go.mod h1:WwKEXU3R1rgCZ77AYa7DFksd9/BAIKyOmRlbVxgvjCk= ++k8s.io/apiextensions-apiserver v0.26.4 h1:9D2RTxYGxrG5uYg6D7QZRcykXvavBvcA59j5kTaedQI= ++k8s.io/apiextensions-apiserver v0.26.4/go.mod h1:cd4uGFGIgzEqUghWpRsr9KE8j2KNTjY8Ji8pnMMazyw= ++k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs= ++k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= ++k8s.io/apiserver v0.26.4/go.mod h1:yAY3O1vBM4/0OIGAGeWcdfzQvgdwJ188VirLcuSAVnw= ++k8s.io/client-go v0.26.4 h1:/7P/IbGBuT73A+G97trf44NTPSNqvuBREpOfdLbHvD4= ++k8s.io/client-go v0.26.4/go.mod h1:6qOItWm3EwxJdl/8p5t7FWtWUOwyMdA8N9ekbW4idpI= ++k8s.io/code-generator v0.26.4/go.mod h1:ryaiIKwfxEJEaywEzx3dhWOydpVctKYbqLajJf0O8dI= ++k8s.io/component-base v0.26.4/go.mod h1:lTuWL1Xz/a4e80gmIC3YZG2JCO4xNwtKWHJWeJmsq20= + k8s.io/gengo v0.0.0-20181113154421-fd15ee9cc2f7/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= + k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= + k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +@@ -1949,13 +1949,13 @@ k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= + k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= + k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= + k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +-k8s.io/kms v0.26.3/go.mod h1:69qGnf1NsFOQP07fBYqNLZklqEHSJF024JqYCaeVxHg= +-k8s.io/kube-aggregator v0.26.3 h1:nc4H5ymGkWPU3c9U9UM468JcmNENY/s/mDYVW3t3uRo= +-k8s.io/kube-aggregator v0.26.3/go.mod h1:SgBESB/+PfZAyceTPIanfQ7GtX9G/+mjfUbTHg3Twbo= ++k8s.io/kms v0.26.4/go.mod h1:69qGnf1NsFOQP07fBYqNLZklqEHSJF024JqYCaeVxHg= ++k8s.io/kube-aggregator v0.26.4 h1:iGljhq5exQkbuc3bnkwUx95RPCBDExg7DkX9XaYhg6w= ++k8s.io/kube-aggregator v0.26.4/go.mod h1:eWfg4tU0+l57ebWiS5THOANIJUrKRxudSVDJ+63bqvQ= + 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/kubectl v0.26.3 h1:bZ5SgFyeEXw6XTc1Qji0iNdtqAC76lmeIIQULg2wNXM= +-k8s.io/kubectl v0.26.3/go.mod h1:02+gv7Qn4dupzN3fi/9OvqqdW+uG/4Zi56vc4Zmsp1g= ++k8s.io/kubectl v0.26.4 h1:A0Oa0u/po4KxXnXsNCOwLojAe9cQR3TJNJabEIf7U1w= ++k8s.io/kubectl v0.26.4/go.mod h1:cWtp/+I4p+h5En3s2zO1zCry9v3/6h37EQ2tF3jNRnM= + k8s.io/kubernetes v1.11.8-beta.0.0.20190124204751-3a10094374f2/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= + k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= + k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +diff --git a/staging/src/kubevirt.io/client-go/go.mod b/staging/src/kubevirt.io/client-go/go.mod +index b8b0074df..2c8edf077 100644 +--- a/staging/src/kubevirt.io/client-go/go.mod ++++ b/staging/src/kubevirt.io/client-go/go.mod +@@ -16,7 +16,7 @@ require ( + github.com/openshift/client-go v0.0.0-20210112165513-ebc401615f47 + github.com/spf13/pflag v1.0.5 + k8s.io/api v0.27.1 +- k8s.io/apiextensions-apiserver v0.26.3 ++ k8s.io/apiextensions-apiserver v0.26.4 + k8s.io/apimachinery v0.27.1 + k8s.io/client-go v12.0.0+incompatible + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f +@@ -71,32 +71,32 @@ require ( + replace ( + github.com/openshift/api => github.com/openshift/api v0.0.0-20210105115604-44119421ec6b + +- k8s.io/api => k8s.io/api v0.26.3 +- k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.3 +- k8s.io/apimachinery => k8s.io/apimachinery v0.26.3 +- k8s.io/apiserver => k8s.io/apiserver v0.26.3 +- k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.3 +- k8s.io/client-go => k8s.io/client-go v0.26.3 +- k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.3 +- k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.3 +- k8s.io/code-generator => k8s.io/code-generator v0.26.3 +- k8s.io/component-base => k8s.io/component-base v0.26.3 +- k8s.io/cri-api => k8s.io/cri-api v0.26.3 +- k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.3 ++ k8s.io/api => k8s.io/api v0.26.4 ++ k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.4 ++ k8s.io/apimachinery => k8s.io/apimachinery v0.26.4 ++ k8s.io/apiserver => k8s.io/apiserver v0.26.4 ++ k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.4 ++ k8s.io/client-go => k8s.io/client-go v0.26.4 ++ k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.4 ++ k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.4 ++ k8s.io/code-generator => k8s.io/code-generator v0.26.4 ++ k8s.io/component-base => k8s.io/component-base v0.26.4 ++ k8s.io/cri-api => k8s.io/cri-api v0.26.4 ++ k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.4 + k8s.io/klog => k8s.io/klog v0.4.0 +- k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.3 +- k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.3 ++ k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.4 ++ k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.4 + k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 +- k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.3 +- k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.3 +- k8s.io/kubectl => k8s.io/kubectl v0.26.3 +- k8s.io/kubelet => k8s.io/kubelet v0.26.3 +- k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.3 +- k8s.io/metrics => k8s.io/metrics v0.26.3 +- k8s.io/node-api => k8s.io/node-api v0.26.3 +- k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.3 +- k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.26.3 +- k8s.io/sample-controller => k8s.io/sample-controller v0.26.3 ++ k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.4 ++ k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.4 ++ k8s.io/kubectl => k8s.io/kubectl v0.26.4 ++ k8s.io/kubelet => k8s.io/kubelet v0.26.4 ++ k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.4 ++ k8s.io/metrics => k8s.io/metrics v0.26.4 ++ k8s.io/node-api => k8s.io/node-api v0.26.4 ++ k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.4 ++ k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.26.4 ++ k8s.io/sample-controller => k8s.io/sample-controller v0.26.4 + + kubevirt.io/api => ../api + ) +diff --git a/staging/src/kubevirt.io/client-go/go.sum b/staging/src/kubevirt.io/client-go/go.sum +index 3fcf63dc1..89daf9285 100644 +--- a/staging/src/kubevirt.io/client-go/go.sum ++++ b/staging/src/kubevirt.io/client-go/go.sum +@@ -1668,17 +1668,17 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt + honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= + honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= + howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +-k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= +-k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= +-k8s.io/apiextensions-apiserver v0.26.3 h1:5PGMm3oEzdB1W/FTMgGIDmm100vn7IaUP5er36dB+YE= +-k8s.io/apiextensions-apiserver v0.26.3/go.mod h1:jdA5MdjNWGP+njw1EKMZc64xAT5fIhN6VJrElV3sfpQ= +-k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= +-k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +-k8s.io/apiserver v0.26.3/go.mod h1:CJe/VoQNcXdhm67EvaVjYXxR3QyfwpceKPuPaeLibTA= +-k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= +-k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ= +-k8s.io/code-generator v0.26.3/go.mod h1:ryaiIKwfxEJEaywEzx3dhWOydpVctKYbqLajJf0O8dI= +-k8s.io/component-base v0.26.3/go.mod h1:5kj1kZYwSC6ZstHJN7oHBqcJC6yyn41eR+Sqa/mQc8E= ++k8s.io/api v0.26.4 h1:qSG2PmtcD23BkYiWfoYAcak870eF/hE7NNYBYavTT94= ++k8s.io/api v0.26.4/go.mod h1:WwKEXU3R1rgCZ77AYa7DFksd9/BAIKyOmRlbVxgvjCk= ++k8s.io/apiextensions-apiserver v0.26.4 h1:9D2RTxYGxrG5uYg6D7QZRcykXvavBvcA59j5kTaedQI= ++k8s.io/apiextensions-apiserver v0.26.4/go.mod h1:cd4uGFGIgzEqUghWpRsr9KE8j2KNTjY8Ji8pnMMazyw= ++k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs= ++k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= ++k8s.io/apiserver v0.26.4/go.mod h1:yAY3O1vBM4/0OIGAGeWcdfzQvgdwJ188VirLcuSAVnw= ++k8s.io/client-go v0.26.4 h1:/7P/IbGBuT73A+G97trf44NTPSNqvuBREpOfdLbHvD4= ++k8s.io/client-go v0.26.4/go.mod h1:6qOItWm3EwxJdl/8p5t7FWtWUOwyMdA8N9ekbW4idpI= ++k8s.io/code-generator v0.26.4/go.mod h1:ryaiIKwfxEJEaywEzx3dhWOydpVctKYbqLajJf0O8dI= ++k8s.io/component-base v0.26.4/go.mod h1:lTuWL1Xz/a4e80gmIC3YZG2JCO4xNwtKWHJWeJmsq20= + k8s.io/gengo v0.0.0-20190907103519-ebc107f98eab/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= + k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= + k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +@@ -1692,7 +1692,7 @@ k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= + k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= + k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= + k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +-k8s.io/kms v0.26.3/go.mod h1:69qGnf1NsFOQP07fBYqNLZklqEHSJF024JqYCaeVxHg= ++k8s.io/kms v0.26.4/go.mod h1:69qGnf1NsFOQP07fBYqNLZklqEHSJF024JqYCaeVxHg= + 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/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +diff --git a/vendor/k8s.io/client-go/discovery/aggregated_discovery.go b/vendor/k8s.io/client-go/discovery/aggregated_discovery.go +index 758b0a3ac..7470259dc 100644 +--- a/vendor/k8s.io/client-go/discovery/aggregated_discovery.go ++++ b/vendor/k8s.io/client-go/discovery/aggregated_discovery.go +@@ -92,12 +92,18 @@ func convertAPIGroup(g apidiscovery.APIGroupDiscovery) ( + resourceList := &metav1.APIResourceList{} + resourceList.GroupVersion = gv.String() + for _, r := range v.Resources { +- resource := convertAPIResource(r) +- resourceList.APIResources = append(resourceList.APIResources, resource) ++ resource, err := convertAPIResource(r) ++ if err == nil { ++ resourceList.APIResources = append(resourceList.APIResources, resource) ++ } + // Subresources field in new format get transformed into full APIResources. ++ // It is possible a partial result with an error was returned to be used ++ // as the parent resource for the subresource. + for _, subresource := range r.Subresources { +- sr := convertAPISubresource(resource, subresource) +- resourceList.APIResources = append(resourceList.APIResources, sr) ++ sr, err := convertAPISubresource(resource, subresource) ++ if err == nil { ++ resourceList.APIResources = append(resourceList.APIResources, sr) ++ } + } + } + gvResources[gv] = resourceList +@@ -105,30 +111,44 @@ func convertAPIGroup(g apidiscovery.APIGroupDiscovery) ( + return group, gvResources, failedGVs + } + +-// convertAPIResource tranforms a APIResourceDiscovery to an APIResource. +-func convertAPIResource(in apidiscovery.APIResourceDiscovery) metav1.APIResource { +- return metav1.APIResource{ ++// convertAPIResource tranforms a APIResourceDiscovery to an APIResource. We are ++// resilient to missing GVK, since this resource might be the parent resource ++// for a subresource. If the parent is missing a GVK, it is not returned in ++// discovery, and the subresource MUST have the GVK. ++func convertAPIResource(in apidiscovery.APIResourceDiscovery) (metav1.APIResource, error) { ++ result := metav1.APIResource{ + Name: in.Resource, + SingularName: in.SingularResource, + Namespaced: in.Scope == apidiscovery.ScopeNamespace, +- Group: in.ResponseKind.Group, +- Version: in.ResponseKind.Version, +- Kind: in.ResponseKind.Kind, + Verbs: in.Verbs, + ShortNames: in.ShortNames, + Categories: in.Categories, + } ++ var err error ++ if in.ResponseKind != nil { ++ result.Group = in.ResponseKind.Group ++ result.Version = in.ResponseKind.Version ++ result.Kind = in.ResponseKind.Kind ++ } else { ++ err = fmt.Errorf("discovery resource %s missing GVK", in.Resource) ++ } ++ // Can return partial result with error, which can be the parent for a ++ // subresource. Do not add this result to the returned discovery resources. ++ return result, err + } + + // convertAPISubresource tranforms a APISubresourceDiscovery to an APIResource. +-func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) metav1.APIResource { +- return metav1.APIResource{ +- Name: fmt.Sprintf("%s/%s", parent.Name, in.Subresource), +- SingularName: parent.SingularName, +- Namespaced: parent.Namespaced, +- Group: in.ResponseKind.Group, +- Version: in.ResponseKind.Version, +- Kind: in.ResponseKind.Kind, +- Verbs: in.Verbs, ++func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) (metav1.APIResource, error) { ++ result := metav1.APIResource{} ++ if in.ResponseKind == nil { ++ return result, fmt.Errorf("subresource %s/%s missing GVK", parent.Name, in.Subresource) + } ++ result.Name = fmt.Sprintf("%s/%s", parent.Name, in.Subresource) ++ result.SingularName = parent.SingularName ++ result.Namespaced = parent.Namespaced ++ result.Group = in.ResponseKind.Group ++ result.Version = in.ResponseKind.Version ++ result.Kind = in.ResponseKind.Kind ++ result.Verbs = in.Verbs ++ return result, nil + } +diff --git a/vendor/k8s.io/client-go/tools/cache/controller.go b/vendor/k8s.io/client-go/tools/cache/controller.go +index 0762da3be..96005ff58 100644 +--- a/vendor/k8s.io/client-go/tools/cache/controller.go ++++ b/vendor/k8s.io/client-go/tools/cache/controller.go +@@ -353,17 +353,6 @@ func NewIndexerInformer( + return clientState, newInformer(lw, objType, resyncPeriod, h, clientState, nil) + } + +-// TransformFunc allows for transforming an object before it will be processed +-// and put into the controller cache and before the corresponding handlers will +-// be called on it. +-// TransformFunc (similarly to ResourceEventHandler functions) should be able +-// to correctly handle the tombstone of type cache.DeletedFinalStateUnknown +-// +-// The most common usage pattern is to clean-up some parts of the object to +-// reduce component memory usage if a given component doesn't care about them. +-// given controller doesn't care for them +-type TransformFunc func(interface{}) (interface{}, error) +- + // NewTransformingInformer returns a Store and a controller for populating + // the store while also providing event notifications. You should only used + // the returned Store for Get/List operations; Add/Modify/Deletes will cause +@@ -411,19 +400,11 @@ func processDeltas( + // Object which receives event notifications from the given deltas + handler ResourceEventHandler, + clientState Store, +- transformer TransformFunc, + deltas Deltas, + ) error { + // from oldest to newest + for _, d := range deltas { + obj := d.Object +- if transformer != nil { +- var err error +- obj, err = transformer(obj) +- if err != nil { +- return err +- } +- } + + switch d.Type { + case Sync, Replaced, Added, Updated: +@@ -475,6 +456,7 @@ func newInformer( + fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{ + KnownObjects: clientState, + EmitDeltaTypeReplaced: true, ++ Transformer: transformer, + }) + + cfg := &Config{ +@@ -486,7 +468,7 @@ func newInformer( + + Process: func(obj interface{}) error { + if deltas, ok := obj.(Deltas); ok { +- return processDeltas(h, clientState, transformer, deltas) ++ return processDeltas(h, clientState, deltas) + } + return errors.New("object given as Process argument is not Deltas") + }, +diff --git a/vendor/k8s.io/client-go/tools/cache/delta_fifo.go b/vendor/k8s.io/client-go/tools/cache/delta_fifo.go +index 0c13a41f0..84f3ab9ca 100644 +--- a/vendor/k8s.io/client-go/tools/cache/delta_fifo.go ++++ b/vendor/k8s.io/client-go/tools/cache/delta_fifo.go +@@ -51,6 +51,10 @@ type DeltaFIFOOptions struct { + // When true, `Replaced` events will be sent for items passed to a Replace() call. + // When false, `Sync` events will be sent instead. + EmitDeltaTypeReplaced bool ++ ++ // If set, will be called for objects before enqueueing them. Please ++ // see the comment on TransformFunc for details. ++ Transformer TransformFunc + } + + // DeltaFIFO is like FIFO, but differs in two ways. One is that the +@@ -129,8 +133,32 @@ type DeltaFIFO struct { + // emitDeltaTypeReplaced is whether to emit the Replaced or Sync + // DeltaType when Replace() is called (to preserve backwards compat). + emitDeltaTypeReplaced bool ++ ++ // Called with every object if non-nil. ++ transformer TransformFunc + } + ++// TransformFunc allows for transforming an object before it will be processed. ++// TransformFunc (similarly to ResourceEventHandler functions) should be able ++// to correctly handle the tombstone of type cache.DeletedFinalStateUnknown. ++// ++// New in v1.27: In such cases, the contained object will already have gone ++// through the transform object separately (when it was added / updated prior ++// to the delete), so the TransformFunc can likely safely ignore such objects ++// (i.e., just return the input object). ++// ++// The most common usage pattern is to clean-up some parts of the object to ++// reduce component memory usage if a given component doesn't care about them. ++// ++// New in v1.27: unless the object is a DeletedFinalStateUnknown, TransformFunc ++// sees the object before any other actor, and it is now safe to mutate the ++// object in place instead of making a copy. ++// ++// Note that TransformFunc is called while inserting objects into the ++// notification queue and is therefore extremely performance sensitive; please ++// do not do anything that will take a long time. ++type TransformFunc func(interface{}) (interface{}, error) ++ + // DeltaType is the type of a change (addition, deletion, etc) + type DeltaType string + +@@ -227,6 +255,7 @@ func NewDeltaFIFOWithOptions(opts DeltaFIFOOptions) *DeltaFIFO { + knownObjects: opts.KnownObjects, + + emitDeltaTypeReplaced: opts.EmitDeltaTypeReplaced, ++ transformer: opts.Transformer, + } + f.cond.L = &f.lock + return f +@@ -411,6 +440,21 @@ func (f *DeltaFIFO) queueActionLocked(actionType DeltaType, obj interface{}) err + if err != nil { + return KeyError{obj, err} + } ++ ++ // Every object comes through this code path once, so this is a good ++ // place to call the transform func. If obj is a ++ // DeletedFinalStateUnknown tombstone, then the containted inner object ++ // will already have gone through the transformer, but we document that ++ // this can happen. In cases involving Replace(), such an object can ++ // come through multiple times. ++ if f.transformer != nil { ++ var err error ++ obj, err = f.transformer(obj) ++ if err != nil { ++ return err ++ } ++ } ++ + oldDeltas := f.items[id] + newDeltas := append(oldDeltas, Delta{actionType, obj}) + newDeltas = dedupDeltas(newDeltas) +@@ -566,12 +610,11 @@ func (f *DeltaFIFO) Pop(process PopProcessFunc) (interface{}, error) { + // using the Sync or Replace DeltaType and then (2) it does some deletions. + // In particular: for every pre-existing key K that is not the key of + // an object in `list` there is the effect of +-// `Delete(DeletedFinalStateUnknown{K, O})` where O is current object +-// of K. If `f.knownObjects == nil` then the pre-existing keys are +-// those in `f.items` and the current object of K is the `.Newest()` +-// of the Deltas associated with K. Otherwise the pre-existing keys +-// are those listed by `f.knownObjects` and the current object of K is +-// what `f.knownObjects.GetByKey(K)` returns. ++// `Delete(DeletedFinalStateUnknown{K, O})` where O is the latest known ++// object of K. The pre-existing keys are those in the union set of the keys in ++// `f.items` and `f.knownObjects` (if not nil). The last known object for key K is ++// the one present in the last delta in `f.items`. If there is no delta for K ++// in `f.items`, it is the object in `f.knownObjects` + func (f *DeltaFIFO) Replace(list []interface{}, _ string) error { + f.lock.Lock() + defer f.lock.Unlock() +@@ -595,51 +638,23 @@ func (f *DeltaFIFO) Replace(list []interface{}, _ string) error { + } + } + +- if f.knownObjects == nil { +- // Do deletion detection against our own list. +- queuedDeletions := 0 +- for k, oldItem := range f.items { +- if keys.Has(k) { +- continue +- } +- // Delete pre-existing items not in the new list. +- // This could happen if watch deletion event was missed while +- // disconnected from apiserver. +- var deletedObj interface{} +- if n := oldItem.Newest(); n != nil { +- deletedObj = n.Object +- } +- queuedDeletions++ +- if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil { +- return err +- } +- } +- +- if !f.populated { +- f.populated = true +- // While there shouldn't be any queued deletions in the initial +- // population of the queue, it's better to be on the safe side. +- f.initialPopulationCount = keys.Len() + queuedDeletions +- } +- +- return nil +- } +- +- // Detect deletions not already in the queue. +- knownKeys := f.knownObjects.ListKeys() ++ // Do deletion detection against objects in the queue + queuedDeletions := 0 +- for _, k := range knownKeys { ++ for k, oldItem := range f.items { + if keys.Has(k) { + continue + } +- +- deletedObj, exists, err := f.knownObjects.GetByKey(k) +- if err != nil { +- deletedObj = nil +- klog.Errorf("Unexpected error %v during lookup of key %v, placing DeleteFinalStateUnknown marker without object", err, k) +- } else if !exists { +- deletedObj = nil +- klog.Infof("Key %v does not exist in known objects store, placing DeleteFinalStateUnknown marker without object", k) ++ // Delete pre-existing items not in the new list. ++ // This could happen if watch deletion event was missed while ++ // disconnected from apiserver. ++ var deletedObj interface{} ++ if n := oldItem.Newest(); n != nil { ++ deletedObj = n.Object ++ ++ // if the previous object is a DeletedFinalStateUnknown, we have to extract the actual Object ++ if d, ok := deletedObj.(DeletedFinalStateUnknown); ok { ++ deletedObj = d.Obj ++ } + } + queuedDeletions++ + if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil { +@@ -647,6 +662,32 @@ func (f *DeltaFIFO) Replace(list []interface{}, _ string) error { + } + } + ++ if f.knownObjects != nil { ++ // Detect deletions for objects not present in the queue, but present in KnownObjects ++ knownKeys := f.knownObjects.ListKeys() ++ for _, k := range knownKeys { ++ if keys.Has(k) { ++ continue ++ } ++ if len(f.items[k]) > 0 { ++ continue ++ } ++ ++ deletedObj, exists, err := f.knownObjects.GetByKey(k) ++ if err != nil { ++ deletedObj = nil ++ klog.Errorf("Unexpected error %v during lookup of key %v, placing DeleteFinalStateUnknown marker without object", err, k) ++ } else if !exists { ++ deletedObj = nil ++ klog.Infof("Key %v does not exist in known objects store, placing DeleteFinalStateUnknown marker without object", k) ++ } ++ queuedDeletions++ ++ if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil { ++ return err ++ } ++ } ++ } ++ + if !f.populated { + f.populated = true + f.initialPopulationCount = keys.Len() + queuedDeletions +diff --git a/vendor/k8s.io/client-go/tools/cache/shared_informer.go b/vendor/k8s.io/client-go/tools/cache/shared_informer.go +index f5c7316a1..4979642ce 100644 +--- a/vendor/k8s.io/client-go/tools/cache/shared_informer.go ++++ b/vendor/k8s.io/client-go/tools/cache/shared_informer.go +@@ -198,10 +198,7 @@ type SharedInformer interface { + // + // Must be set before starting the informer. + // +- // Note: Since the object given to the handler may be already shared with +- // other goroutines, it is advisable to copy the object being +- // transform before mutating it at all and returning the copy to prevent +- // data races. ++ // Please see the comment on TransformFunc for more details. + SetTransform(handler TransformFunc) error + + // IsStopped reports whether the informer has already been stopped. +@@ -422,6 +419,7 @@ func (s *sharedIndexInformer) Run(stopCh <-chan struct{}) { + fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{ + KnownObjects: s.indexer, + EmitDeltaTypeReplaced: true, ++ Transformer: s.transform, + }) + + cfg := &Config{ +@@ -585,7 +583,7 @@ func (s *sharedIndexInformer) HandleDeltas(obj interface{}) error { + defer s.blockDeltas.Unlock() + + if deltas, ok := obj.(Deltas); ok { +- return processDeltas(s, s.indexer, s.transform, deltas) ++ return processDeltas(s, s.indexer, deltas) + } + return errors.New("object given as Process argument is not Deltas") + } +diff --git a/vendor/modules.txt b/vendor/modules.txt +index 2806f50a8..a863ab45f 100644 +--- a/vendor/modules.txt ++++ b/vendor/modules.txt +@@ -658,7 +658,7 @@ gopkg.in/yaml.v2 + # gopkg.in/yaml.v3 v3.0.1 + ## explicit + gopkg.in/yaml.v3 +-# k8s.io/api v0.27.1 => k8s.io/api v0.26.3 ++# k8s.io/api v0.27.1 => k8s.io/api v0.26.4 + ## explicit; go 1.19 + k8s.io/api/admission/v1 + k8s.io/api/admissionregistration/v1 +@@ -712,7 +712,7 @@ k8s.io/api/scheduling/v1beta1 + k8s.io/api/storage/v1 + k8s.io/api/storage/v1alpha1 + k8s.io/api/storage/v1beta1 +-# k8s.io/apiextensions-apiserver v0.26.3 => k8s.io/apiextensions-apiserver v0.26.3 ++# k8s.io/apiextensions-apiserver v0.26.4 => k8s.io/apiextensions-apiserver v0.26.4 + ## explicit; go 1.19 + k8s.io/apiextensions-apiserver/pkg/apis/apiextensions + k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 +@@ -724,7 +724,7 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextension + k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1/fake + k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1 + k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake +-# k8s.io/apimachinery v0.27.1 => k8s.io/apimachinery v0.26.3 ++# k8s.io/apimachinery v0.27.1 => k8s.io/apimachinery v0.26.4 + ## explicit; go 1.19 + k8s.io/apimachinery/pkg/api/equality + k8s.io/apimachinery/pkg/api/errors +@@ -777,7 +777,7 @@ k8s.io/apimachinery/pkg/watch + k8s.io/apimachinery/third_party/forked/golang/json + k8s.io/apimachinery/third_party/forked/golang/netutil + k8s.io/apimachinery/third_party/forked/golang/reflect +-# k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.26.3 ++# k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.26.4 + ## explicit; go 1.19 + k8s.io/client-go/applyconfigurations/admissionregistration/v1 + k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1 +@@ -1096,7 +1096,7 @@ k8s.io/klog/v2/internal/clock + k8s.io/klog/v2/internal/dbg + k8s.io/klog/v2/internal/serialize + k8s.io/klog/v2/internal/severity +-# k8s.io/kube-aggregator v0.26.3 => k8s.io/kube-aggregator v0.26.3 ++# k8s.io/kube-aggregator v0.26.4 => k8s.io/kube-aggregator v0.26.4 + ## explicit; go 1.19 + k8s.io/kube-aggregator/pkg/apis/apiregistration + k8s.io/kube-aggregator/pkg/apis/apiregistration/v1 +@@ -1124,7 +1124,7 @@ k8s.io/kube-openapi/pkg/util + k8s.io/kube-openapi/pkg/util/proto + k8s.io/kube-openapi/pkg/validation/errors + k8s.io/kube-openapi/pkg/validation/spec +-# k8s.io/kubectl v0.0.0-00010101000000-000000000000 => k8s.io/kubectl v0.26.3 ++# k8s.io/kubectl v0.0.0-00010101000000-000000000000 => k8s.io/kubectl v0.26.4 + ## explicit; go 1.19 + k8s.io/kubectl/pkg/cmd/util/podcmd + # k8s.io/utils v0.0.0-20230505201702-9f6742963106 +@@ -1253,32 +1253,32 @@ sigs.k8s.io/yaml + # github.com/openshift/api => github.com/openshift/api v0.0.0-20191219222812-2987a591a72c + # github.com/openshift/client-go => github.com/openshift/client-go v0.0.0-20210112165513-ebc401615f47 + # github.com/operator-framework/operator-lifecycle-manager => github.com/operator-framework/operator-lifecycle-manager v0.0.0-20190128024246-5eb7ae5bdb7a +-# k8s.io/api => k8s.io/api v0.26.3 +-# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.3 +-# k8s.io/apimachinery => k8s.io/apimachinery v0.26.3 +-# k8s.io/apiserver => k8s.io/apiserver v0.26.3 +-# k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.3 +-# k8s.io/client-go => k8s.io/client-go v0.26.3 +-# k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.3 +-# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.3 +-# k8s.io/code-generator => k8s.io/code-generator v0.26.3 +-# k8s.io/component-base => k8s.io/component-base v0.26.3 +-# k8s.io/cri-api => k8s.io/cri-api v0.26.3 +-# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.3 ++# k8s.io/api => k8s.io/api v0.26.4 ++# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.4 ++# k8s.io/apimachinery => k8s.io/apimachinery v0.26.4 ++# k8s.io/apiserver => k8s.io/apiserver v0.26.4 ++# k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.4 ++# k8s.io/client-go => k8s.io/client-go v0.26.4 ++# k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.4 ++# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.4 ++# k8s.io/code-generator => k8s.io/code-generator v0.26.4 ++# k8s.io/component-base => k8s.io/component-base v0.26.4 ++# k8s.io/cri-api => k8s.io/cri-api v0.26.4 ++# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.4 + # k8s.io/klog => k8s.io/klog v0.4.0 +-# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.3 +-# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.3 ++# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.4 ++# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.4 + # k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 +-# k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.3 +-# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.3 +-# k8s.io/kubectl => k8s.io/kubectl v0.26.3 +-# k8s.io/kubelet => k8s.io/kubelet v0.26.3 +-# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.3 +-# k8s.io/metrics => k8s.io/metrics v0.26.3 +-# k8s.io/node-api => k8s.io/node-api v0.26.3 +-# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.3 +-# k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.26.3 +-# k8s.io/sample-controller => k8s.io/sample-controller v0.26.3 ++# k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.4 ++# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.4 ++# k8s.io/kubectl => k8s.io/kubectl v0.26.4 ++# k8s.io/kubelet => k8s.io/kubelet v0.26.4 ++# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.4 ++# k8s.io/metrics => k8s.io/metrics v0.26.4 ++# k8s.io/node-api => k8s.io/node-api v0.26.4 ++# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.4 ++# k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.26.4 ++# k8s.io/sample-controller => k8s.io/sample-controller v0.26.4 + # kubevirt.io/api => ./staging/src/kubevirt.io/api + # kubevirt.io/client-go => ./staging/src/kubevirt.io/client-go + # sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.6.2 +-- +2.41.0 + diff --git a/0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch b/0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch new file mode 100644 index 0000000..004b83e --- /dev/null +++ b/0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch @@ -0,0 +1,382 @@ +From ee3463ae990a1776908483b182ad79c79637cd5d Mon Sep 17 00:00:00 2001 +From: Alexander Wels +Date: Fri, 11 Aug 2023 07:56:29 -0500 +Subject: [PATCH 1/4] Wait for new attachemnt pod + +Before deleting old attachment pod, wait for new attachment +pod to be ready, so k8s should not detach the volume from the +node since there will always be a pod using the volume from +its perspective. + +Fixed issue where when adding or removing a volume the existing +volumes would still have the UID of the old attachment pod in +the VMI status which caused errors to appear in the virt-handler +logs about not being able to find the device or image. + +Fixed issue where the cleanup would attempt to remove a volume +that was already gone causing errors to appear in the virt-handler +log. + +Signed-off-by: Alexander Wels +--- + pkg/virt-controller/watch/vmi.go | 60 +++++++++++++++----------- + pkg/virt-controller/watch/vmi_test.go | 52 ++++++++++++++++++++++ + pkg/virt-handler/hotplug-disk/mount.go | 7 ++- + tests/storage/hotplug.go | 10 +++++ + 4 files changed, 103 insertions(+), 26 deletions(-) + +diff --git a/pkg/virt-controller/watch/vmi.go b/pkg/virt-controller/watch/vmi.go +index 9afaee4f0..99af8b8cb 100644 +--- a/pkg/virt-controller/watch/vmi.go ++++ b/pkg/virt-controller/watch/vmi.go +@@ -516,11 +516,7 @@ func (c *VMIController) hasOwnerVM(vmi *virtv1.VirtualMachineInstance) bool { + } + + ownerVM := obj.(*virtv1.VirtualMachine) +- if controllerRef.UID == ownerVM.UID { +- return true +- } +- +- return false ++ return controllerRef.UID == ownerVM.UID + } + + func (c *VMIController) updateStatus(vmi *virtv1.VirtualMachineInstance, pod *k8sv1.Pod, dataVolumes []*cdiv1.DataVolume, syncErr syncError) error { +@@ -1816,15 +1812,29 @@ func (c *VMIController) waitForFirstConsumerTemporaryPods(vmi *virtv1.VirtualMac + } + + func (c *VMIController) needsHandleHotplug(hotplugVolumes []*virtv1.Volume, hotplugAttachmentPods []*k8sv1.Pod) bool { ++ if len(hotplugAttachmentPods) > 1 { ++ return true ++ } + // Determine if the ready volumes have changed compared to the current pod + for _, attachmentPod := range hotplugAttachmentPods { + if c.podVolumesMatchesReadyVolumes(attachmentPod, hotplugVolumes) { +- log.DefaultLogger().Infof("Don't need to handle as we have a matching attachment pod") + return false + } +- return true + } +- return len(hotplugVolumes) > 0 ++ return len(hotplugVolumes) > 0 || len(hotplugAttachmentPods) > 0 ++} ++ ++func (c *VMIController) getActiveAndOldAttachmentPods(readyHotplugVolumes []*virtv1.Volume, hotplugAttachmentPods []*k8sv1.Pod) (*k8sv1.Pod, []*k8sv1.Pod) { ++ var currentPod *k8sv1.Pod ++ oldPods := make([]*k8sv1.Pod, 0) ++ for _, attachmentPod := range hotplugAttachmentPods { ++ if !c.podVolumesMatchesReadyVolumes(attachmentPod, readyHotplugVolumes) { ++ oldPods = append(oldPods, attachmentPod) ++ } else { ++ currentPod = attachmentPod ++ } ++ } ++ return currentPod, oldPods + } + + func (c *VMIController) handleHotplugVolumes(hotplugVolumes []*virtv1.Volume, hotplugAttachmentPods []*k8sv1.Pod, vmi *virtv1.VirtualMachineInstance, virtLauncherPod *k8sv1.Pod, dataVolumes []*cdiv1.DataVolume) syncError { +@@ -1855,29 +1865,25 @@ func (c *VMIController) handleHotplugVolumes(hotplugVolumes []*virtv1.Volume, ho + readyHotplugVolumes = append(readyHotplugVolumes, volume) + } + // Determine if the ready volumes have changed compared to the current pod +- currentPod := make([]*k8sv1.Pod, 0) +- oldPods := make([]*k8sv1.Pod, 0) +- for _, attachmentPod := range hotplugAttachmentPods { +- if !c.podVolumesMatchesReadyVolumes(attachmentPod, readyHotplugVolumes) { +- oldPods = append(oldPods, attachmentPod) +- } else { +- currentPod = append(currentPod, attachmentPod) +- } +- } ++ currentPod, oldPods := c.getActiveAndOldAttachmentPods(readyHotplugVolumes, hotplugAttachmentPods) + +- if len(currentPod) == 0 && len(readyHotplugVolumes) > 0 { ++ if currentPod == nil && len(readyHotplugVolumes) > 0 { + // ready volumes have changed + // Create new attachment pod that holds all the ready volumes + if err := c.createAttachmentPod(vmi, virtLauncherPod, readyHotplugVolumes); err != nil { + return err + } + } +- // Delete old attachment pod +- for _, attachmentPod := range oldPods { +- if err := c.deleteAttachmentPodForVolume(vmi, attachmentPod); err != nil { +- return &syncErrorImpl{fmt.Errorf("Error deleting attachment pod %v", err), FailedDeletePodReason} ++ ++ if len(readyHotplugVolumes) == 0 || (currentPod != nil && currentPod.Status.Phase == k8sv1.PodRunning) { ++ // Delete old attachment pod ++ for _, attachmentPod := range oldPods { ++ if err := c.deleteAttachmentPodForVolume(vmi, attachmentPod); err != nil { ++ return &syncErrorImpl{fmt.Errorf("Error deleting attachment pod %v", err), FailedDeletePodReason} ++ } + } + } ++ + return nil + } + +@@ -2121,6 +2127,9 @@ func (c *VMIController) updateVolumeStatus(vmi *virtv1.VirtualMachineInstance, v + if err != nil { + return err + } ++ ++ attachmentPod, _ := c.getActiveAndOldAttachmentPods(hotplugVolumes, attachmentPods) ++ + newStatus := make([]virtv1.VolumeStatus, 0) + for i, volume := range vmi.Spec.Volumes { + status := virtv1.VolumeStatus{} +@@ -2142,7 +2151,6 @@ func (c *VMIController) updateVolumeStatus(vmi *virtv1.VirtualMachineInstance, v + ClaimName: volume.Name, + } + } +- attachmentPod := c.findAttachmentPodByVolumeName(volume.Name, attachmentPods) + if attachmentPod == nil { + if !c.volumeReady(status.Phase) { + status.HotplugVolume.AttachPodUID = "" +@@ -2156,6 +2164,9 @@ func (c *VMIController) updateVolumeStatus(vmi *virtv1.VirtualMachineInstance, v + status.HotplugVolume.AttachPodName = attachmentPod.Name + if len(attachmentPod.Status.ContainerStatuses) == 1 && attachmentPod.Status.ContainerStatuses[0].Ready { + status.HotplugVolume.AttachPodUID = attachmentPod.UID ++ } else { ++ // Remove UID of old pod if a new one is available, but not yet ready ++ status.HotplugVolume.AttachPodUID = "" + } + if c.canMoveToAttachedPhase(status.Phase) { + status.Phase = virtv1.HotplugVolumeAttachedToNode +@@ -2244,8 +2255,7 @@ func (c *VMIController) getFilesystemOverhead(pvc *k8sv1.PersistentVolumeClaim) + } + + func (c *VMIController) canMoveToAttachedPhase(currentPhase virtv1.VolumePhase) bool { +- return (currentPhase == "" || currentPhase == virtv1.VolumeBound || currentPhase == virtv1.VolumePending || +- currentPhase == virtv1.HotplugVolumeAttachedToNode) ++ return (currentPhase == "" || currentPhase == virtv1.VolumeBound || currentPhase == virtv1.VolumePending) + } + + func (c *VMIController) findAttachmentPodByVolumeName(volumeName string, attachmentPods []*k8sv1.Pod) *k8sv1.Pod { +diff --git a/pkg/virt-controller/watch/vmi_test.go b/pkg/virt-controller/watch/vmi_test.go +index a9b173232..932326432 100644 +--- a/pkg/virt-controller/watch/vmi_test.go ++++ b/pkg/virt-controller/watch/vmi_test.go +@@ -2700,6 +2700,58 @@ var _ = Describe("VirtualMachineInstance watcher", func() { + []string{SuccessfulCreatePodReason}), + ) + ++ DescribeTable("Should properly calculate if it needs to handle hotplug volumes", func(hotplugVolumes []*virtv1.Volume, attachmentPods []*k8sv1.Pod, match gomegaTypes.GomegaMatcher) { ++ Expect(controller.needsHandleHotplug(hotplugVolumes, attachmentPods)).To(match) ++ }, ++ Entry("nil volumes, nil attachmentPods", nil, nil, BeFalse()), ++ Entry("empty volumes, empty attachmentPods", []*virtv1.Volume{}, []*k8sv1.Pod{}, BeFalse()), ++ Entry("single volume, empty attachmentPods", []*virtv1.Volume{ ++ { ++ Name: "test", ++ }, ++ }, []*k8sv1.Pod{}, BeTrue()), ++ Entry("no volume, single attachmentPod", []*virtv1.Volume{}, makePods(0), BeTrue()), ++ Entry("matching volume, single attachmentPod", []*virtv1.Volume{ ++ { ++ Name: "volume0", ++ }, ++ }, makePods(0), BeFalse()), ++ Entry("mismatched volume, single attachmentPod", []*virtv1.Volume{ ++ { ++ Name: "invalid", ++ }, ++ }, makePods(0), BeTrue()), ++ Entry("matching volume, multiple attachmentPods", []*virtv1.Volume{ ++ { ++ Name: "volume0", ++ }, ++ }, []*k8sv1.Pod{makePods(0)[0], makePods(1)[0]}, BeTrue()), ++ ) ++ ++ DescribeTable("Should find active and old pods", func(hotplugVolumes []*virtv1.Volume, attachmentPods []*k8sv1.Pod, expectedActive *k8sv1.Pod, expectedOld []*k8sv1.Pod) { ++ active, old := controller.getActiveAndOldAttachmentPods(hotplugVolumes, attachmentPods) ++ Expect(active).To(Equal(expectedActive)) ++ Expect(old).To(ContainElements(expectedOld)) ++ }, ++ Entry("nil volumes, nil attachmentPods", nil, nil, nil, nil), ++ Entry("empty volumes, empty attachmentPods", []*virtv1.Volume{}, []*k8sv1.Pod{}, nil, []*k8sv1.Pod{}), ++ Entry("matching volume, single attachmentPod", []*virtv1.Volume{ ++ { ++ Name: "volume0", ++ }, ++ }, makePods(0), makePods(0)[0], []*k8sv1.Pod{}), ++ Entry("matching volume, multiple attachmentPods, first pod matches", []*virtv1.Volume{ ++ { ++ Name: "volume0", ++ }, ++ }, []*k8sv1.Pod{makePods(0)[0], makePods(1)[0]}, makePods(0)[0], makePods(1)), ++ Entry("matching volume, multiple attachmentPods, second pod matches", []*virtv1.Volume{ ++ { ++ Name: "volume1", ++ }, ++ }, []*k8sv1.Pod{makePods(0)[0], makePods(1)[0]}, makePods(1)[0], makePods(0)), ++ ) ++ + It("Should get default filesystem overhead if there are multiple CDI instances", func() { + cdi := cdiv1.CDI{ + ObjectMeta: metav1.ObjectMeta{ +diff --git a/pkg/virt-handler/hotplug-disk/mount.go b/pkg/virt-handler/hotplug-disk/mount.go +index 942301815..43504d48d 100644 +--- a/pkg/virt-handler/hotplug-disk/mount.go ++++ b/pkg/virt-handler/hotplug-disk/mount.go +@@ -508,9 +508,10 @@ func (m *volumeMounter) updateBlockMajorMinor(dev uint64, allow bool, manager cg + func (m *volumeMounter) createBlockDeviceFile(basePath *safepath.Path, deviceName string, dev uint64, blockDevicePermissions os.FileMode) error { + if _, err := safepath.JoinNoFollow(basePath, deviceName); errors.Is(err, os.ErrNotExist) { + return mknodCommand(basePath, deviceName, dev, blockDevicePermissions) +- } else { ++ } else if err != nil { + return err + } ++ return nil + } + + func (m *volumeMounter) mountFileSystemHotplugVolume(vmi *v1.VirtualMachineInstance, volume string, sourceUID types.UID, record *vmiMountTargetRecord, mountDirectory bool) error { +@@ -667,6 +668,10 @@ func (m *volumeMounter) Unmount(vmi *v1.VirtualMachineInstance) error { + var err error + if m.isBlockVolume(&vmi.Status, volumeStatus.Name) { + path, err = safepath.JoinNoFollow(basePath, volumeStatus.Name) ++ if errors.Is(err, os.ErrNotExist) { ++ // already unmounted or never mounted ++ continue ++ } + } else if m.isDirectoryMounted(&vmi.Status, volumeStatus.Name) { + path, err = m.hotplugDiskManager.GetFileSystemDirectoryTargetPathFromHostView(virtlauncherUID, volumeStatus.Name, false) + if os.IsExist(err) { +diff --git a/tests/storage/hotplug.go b/tests/storage/hotplug.go +index a85976484..ba9c69100 100644 +--- a/tests/storage/hotplug.go ++++ b/tests/storage/hotplug.go +@@ -724,6 +724,16 @@ var _ = SIGDescribe("Hotplug", func() { + for i := range testVolumes { + verifyVolumeNolongerAccessible(vmi, targets[i]) + } ++ By("Verifying there are no sync errors") ++ events, err := virtClient.CoreV1().Events(vmi.Namespace).List(context.Background(), metav1.ListOptions{}) ++ Expect(err).ToNot(HaveOccurred()) ++ for _, event := range events.Items { ++ if event.InvolvedObject.Kind == "VirtualMachineInstance" && event.InvolvedObject.UID == vmi.UID { ++ if event.Reason == string(v1.SyncFailed) { ++ Fail(fmt.Sprintf("Found sync failed event %v", event)) ++ } ++ } ++ } + }, + Entry("with VMs", addDVVolumeVM, removeVolumeVM, corev1.PersistentVolumeFilesystem, false), + Entry("with VMIs", addDVVolumeVMI, removeVolumeVMI, corev1.PersistentVolumeFilesystem, true), +-- +2.41.0 + + +From b02ab03f39e7e888c27949d24c0e9b38963d9b6c Mon Sep 17 00:00:00 2001 +From: Alexander Wels +Date: Fri, 11 Aug 2023 15:00:59 -0500 +Subject: [PATCH 2/4] Don't generate SynFail caused by a race condition. + +Signed-off-by: Alexander Wels +--- + pkg/virt-handler/hotplug-disk/mount.go | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/pkg/virt-handler/hotplug-disk/mount.go b/pkg/virt-handler/hotplug-disk/mount.go +index 43504d48d..9a5d24747 100644 +--- a/pkg/virt-handler/hotplug-disk/mount.go ++++ b/pkg/virt-handler/hotplug-disk/mount.go +@@ -313,12 +313,16 @@ func (m *volumeMounter) mountHotplugVolume(vmi *v1.VirtualMachineInstance, volum + if m.isBlockVolume(&vmi.Status, volumeName) { + logger.V(4).Infof("Mounting block volume: %s", volumeName) + if err := m.mountBlockHotplugVolume(vmi, volumeName, sourceUID, record); err != nil { +- return fmt.Errorf("failed to mount block hotplug volume %s: %v", volumeName, err) ++ if !errors.Is(err, os.ErrNotExist) { ++ return fmt.Errorf("failed to mount block hotplug volume %s: %v", volumeName, err) ++ } + } + } else { + logger.V(4).Infof("Mounting file system volume: %s", volumeName) + if err := m.mountFileSystemHotplugVolume(vmi, volumeName, sourceUID, record, mountDirectory); err != nil { +- return fmt.Errorf("failed to mount filesystem hotplug volume %s: %v", volumeName, err) ++ if !errors.Is(err, os.ErrNotExist) { ++ return fmt.Errorf("failed to mount filesystem hotplug volume %s: %v", volumeName, err) ++ } + } + } + } +-- +2.41.0 + + +From 5012469d5179f01f5da9ae7c701949a57fb9d439 Mon Sep 17 00:00:00 2001 +From: Alexander Wels +Date: Fri, 11 Aug 2023 18:04:28 -0500 +Subject: [PATCH 3/4] Address code review comments + +Signed-off-by: Alexander Wels +--- + pkg/virt-controller/watch/vmi.go | 6 ++---- + pkg/virt-handler/hotplug-disk/mount.go | 3 +-- + 2 files changed, 3 insertions(+), 6 deletions(-) + +diff --git a/pkg/virt-controller/watch/vmi.go b/pkg/virt-controller/watch/vmi.go +index 99af8b8cb..e031c35a8 100644 +--- a/pkg/virt-controller/watch/vmi.go ++++ b/pkg/virt-controller/watch/vmi.go +@@ -1816,10 +1816,8 @@ func (c *VMIController) needsHandleHotplug(hotplugVolumes []*virtv1.Volume, hotp + return true + } + // Determine if the ready volumes have changed compared to the current pod +- for _, attachmentPod := range hotplugAttachmentPods { +- if c.podVolumesMatchesReadyVolumes(attachmentPod, hotplugVolumes) { +- return false +- } ++ if len(hotplugAttachmentPods) == 1 && c.podVolumesMatchesReadyVolumes(hotplugAttachmentPods[0], hotplugVolumes) { ++ return false + } + return len(hotplugVolumes) > 0 || len(hotplugAttachmentPods) > 0 + } +diff --git a/pkg/virt-handler/hotplug-disk/mount.go b/pkg/virt-handler/hotplug-disk/mount.go +index 9a5d24747..c0b55046c 100644 +--- a/pkg/virt-handler/hotplug-disk/mount.go ++++ b/pkg/virt-handler/hotplug-disk/mount.go +@@ -512,10 +512,9 @@ func (m *volumeMounter) updateBlockMajorMinor(dev uint64, allow bool, manager cg + func (m *volumeMounter) createBlockDeviceFile(basePath *safepath.Path, deviceName string, dev uint64, blockDevicePermissions os.FileMode) error { + if _, err := safepath.JoinNoFollow(basePath, deviceName); errors.Is(err, os.ErrNotExist) { + return mknodCommand(basePath, deviceName, dev, blockDevicePermissions) +- } else if err != nil { ++ } else { + return err + } +- return nil + } + + func (m *volumeMounter) mountFileSystemHotplugVolume(vmi *v1.VirtualMachineInstance, volume string, sourceUID types.UID, record *vmiMountTargetRecord, mountDirectory bool) error { +-- +2.41.0 + + +From 5abf17fef7ab5433ec7dd155a82b1575660b86d3 Mon Sep 17 00:00:00 2001 +From: Alexander Wels +Date: Mon, 14 Aug 2023 07:58:16 -0500 +Subject: [PATCH 4/4] Update pkg/virt-handler/hotplug-disk/mount.go + +Co-authored-by: Vasiliy Ulyanov +Signed-off-by: Alexander Wels +--- + pkg/virt-handler/hotplug-disk/mount.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkg/virt-handler/hotplug-disk/mount.go b/pkg/virt-handler/hotplug-disk/mount.go +index c0b55046c..b1a11d93f 100644 +--- a/pkg/virt-handler/hotplug-disk/mount.go ++++ b/pkg/virt-handler/hotplug-disk/mount.go +@@ -677,7 +677,7 @@ func (m *volumeMounter) Unmount(vmi *v1.VirtualMachineInstance) error { + } + } else if m.isDirectoryMounted(&vmi.Status, volumeStatus.Name) { + path, err = m.hotplugDiskManager.GetFileSystemDirectoryTargetPathFromHostView(virtlauncherUID, volumeStatus.Name, false) +- if os.IsExist(err) { ++ if errors.Is(err, os.ErrNotExist) { + // already unmounted or never mounted + continue + } +-- +2.41.0 + diff --git a/0013-Adapt-e2e-tests-to-CDI-1.57.0.patch b/0013-Adapt-e2e-tests-to-CDI-1.57.0.patch new file mode 100644 index 0000000..146db99 --- /dev/null +++ b/0013-Adapt-e2e-tests-to-CDI-1.57.0.patch @@ -0,0 +1,194 @@ +From 61ca1e96363afe403465ed195b8cc808a4a04f06 Mon Sep 17 00:00:00 2001 +From: Alex Kalenyuk +Date: Wed, 12 Jul 2023 19:52:04 +0300 +Subject: [PATCH 1/2] Don't wait for populator target PVC to be bound + +Populator PVCs only achieve bound phase once the population is done, +as opposed to CDI population which was working on the target PVC directly. + +Signed-off-by: Alex Kalenyuk +--- + tests/storage/export.go | 70 ++--------------------------------------- + 1 file changed, 3 insertions(+), 67 deletions(-) + +diff --git a/tests/storage/export.go b/tests/storage/export.go +index d456e2fb1..4fab2aec1 100644 +--- a/tests/storage/export.go ++++ b/tests/storage/export.go +@@ -48,7 +48,6 @@ import ( + + k8sv1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" +- storagev1 "k8s.io/api/storage/v1" + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" +@@ -230,68 +229,6 @@ var _ = SIGDescribe("Export", func() { + return tests.RunPod(pod) + } + +- createTriggerPodForPvc := func(pvc *k8sv1.PersistentVolumeClaim) *k8sv1.Pod { +- volumeName := pvc.GetName() +- podName := fmt.Sprintf("bind-%s", volumeName) +- pod := tests.RenderPod(podName, []string{"/bin/sh", "-c", "sleep 1"}, []string{}) +- pod.Spec.Volumes = append(pod.Spec.Volumes, k8sv1.Volume{ +- Name: volumeName, +- VolumeSource: k8sv1.VolumeSource{ +- PersistentVolumeClaim: &k8sv1.PersistentVolumeClaimVolumeSource{ +- ClaimName: pvc.GetName(), +- }, +- }, +- }) +- +- volumeMode := pvc.Spec.VolumeMode +- if volumeMode != nil && *volumeMode == k8sv1.PersistentVolumeBlock { +- addBlockVolume(pod, volumeName) +- } else { +- addFilesystemVolume(pod, volumeName) +- } +- return tests.RunPodAndExpectCompletion(pod) +- } +- +- isWaitForFirstConsumer := func(storageClassName string) bool { +- sc, err := virtClient.StorageV1().StorageClasses().Get(context.Background(), storageClassName, metav1.GetOptions{}) +- Expect(err).ToNot(HaveOccurred()) +- return sc.VolumeBindingMode != nil && *sc.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer +- } +- +- ensurePVCBound := func(pvc *k8sv1.PersistentVolumeClaim) { +- namespace := pvc.Namespace +- if !isWaitForFirstConsumer(*pvc.Spec.StorageClassName) { +- By("Checking for bound claim on non-WFFC storage") +- // Not WFFC, pvc will be bound +- Eventually(func() k8sv1.PersistentVolumeClaimPhase { +- pvc, err := virtClient.CoreV1().PersistentVolumeClaims(namespace).Get(context.Background(), pvc.Name, metav1.GetOptions{}) +- Expect(err).ToNot(HaveOccurred()) +- return pvc.Status.Phase +- }, 30*time.Second, 1*time.Second).Should(Equal(k8sv1.ClaimBound)) +- return +- } +- By("Checking the PVC is pending for WFFC storage") +- Eventually(func() k8sv1.PersistentVolumeClaimPhase { +- pvc, err := virtClient.CoreV1().PersistentVolumeClaims(namespace).Get(context.Background(), pvc.Name, metav1.GetOptions{}) +- Expect(err).ToNot(HaveOccurred()) +- return pvc.Status.Phase +- }, 15*time.Second, 1*time.Second).Should(Equal(k8sv1.ClaimPending)) +- +- By("Creating trigger pod to bind WFFC storage") +- triggerPod := createTriggerPodForPvc(pvc) +- By("Checking the PVC was bound") +- Eventually(func() k8sv1.PersistentVolumeClaimPhase { +- pvc, err := virtClient.CoreV1().PersistentVolumeClaims(namespace).Get(context.Background(), pvc.Name, metav1.GetOptions{}) +- Expect(err).ToNot(HaveOccurred()) +- return pvc.Status.Phase +- }, 30*time.Second, 1*time.Second).Should(Equal(k8sv1.ClaimBound)) +- By("Deleting the trigger pod") +- immediate := int64(0) +- Expect(virtClient.CoreV1().Pods(triggerPod.Namespace).Delete(context.Background(), triggerPod.Name, metav1.DeleteOptions{ +- GracePeriodSeconds: &immediate, +- })).To(Succeed()) +- } +- + createExportTokenSecret := func(name, namespace string) *k8sv1.Secret { + var err error + secret := &k8sv1.Secret{ +@@ -352,6 +289,7 @@ var _ = SIGDescribe("Export", func() { + dv := libdv.NewDataVolume( + libdv.WithRegistryURLSourceAndPullMethod(cd.DataVolumeImportUrlForContainerDisk(cd.ContainerDiskCirros), cdiv1.RegistryPullNode), + libdv.WithPVC(libdv.PVCWithStorageClass(sc), libdv.PVCWithVolumeMode(volumeMode)), ++ libdv.WithForceBindAnnotation(), + ) + + dv, err = virtClient.CdiClient().CdiV1beta1().DataVolumes(testsuite.GetTestNamespace(nil)).Create(context.Background(), dv, metav1.CreateOptions{}) +@@ -362,7 +300,6 @@ var _ = SIGDescribe("Export", func() { + pvc, err = virtClient.CoreV1().PersistentVolumeClaims(testsuite.GetTestNamespace(dv)).Get(context.Background(), dv.Name, metav1.GetOptions{}) + return err + }, 60*time.Second, 1*time.Second).Should(BeNil(), "persistent volume associated with DV should be created") +- ensurePVCBound(pvc) + + By("Making sure the DV is successful") + libstorage.EventuallyDV(dv, 90, HaveSucceeded()) +@@ -847,6 +784,7 @@ var _ = SIGDescribe("Export", func() { + dv := libdv.NewDataVolume( + libdv.WithRegistryURLSourceAndPullMethod(cd.DataVolumeImportUrlForContainerDisk(cd.ContainerDiskCirros), cdiv1.RegistryPullNode), + libdv.WithPVC(libdv.PVCWithStorageClass(sc)), ++ libdv.WithForceBindAnnotation(), + ) + + name := dv.Name +@@ -869,12 +807,10 @@ var _ = SIGDescribe("Export", func() { + }, 60*time.Second, 1*time.Second).Should(ContainElement(expectedCond), "export should report missing pvc") + + dv, err = virtClient.CdiClient().CdiV1beta1().DataVolumes(testsuite.GetTestNamespace(nil)).Create(context.Background(), dv, metav1.CreateOptions{}) +- var pvc *k8sv1.PersistentVolumeClaim + Eventually(func() error { +- pvc, err = virtClient.CoreV1().PersistentVolumeClaims(testsuite.GetTestNamespace(dv)).Get(context.Background(), dv.Name, metav1.GetOptions{}) ++ _, err = virtClient.CoreV1().PersistentVolumeClaims(testsuite.GetTestNamespace(dv)).Get(context.Background(), dv.Name, metav1.GetOptions{}) + return err + }, 60*time.Second, 1*time.Second).Should(BeNil(), "persistent volume associated with DV should be created") +- ensurePVCBound(pvc) + + By("Making sure the DV is successful") + libstorage.EventuallyDV(dv, 90, HaveSucceeded()) +-- +2.41.0 + + +From 5b44741c1ca7df3b7121dff7db6a52f6599b7144 Mon Sep 17 00:00:00 2001 +From: Alex Kalenyuk +Date: Wed, 12 Jul 2023 19:57:57 +0300 +Subject: [PATCH 2/2] Don't check for CloneOf/CloneRequest with populator + target PVCs + +These simply don't exist (and are not needed) with populators + +Signed-off-by: Alex Kalenyuk +--- + tests/storage/restore.go | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/tests/storage/restore.go b/tests/storage/restore.go +index dffd0f1fe..5a09ca839 100644 +--- a/tests/storage/restore.go ++++ b/tests/storage/restore.go +@@ -1776,13 +1776,18 @@ var _ = SIGDescribe("VirtualMachineRestore Tests", func() { + } + pvc, err := virtClient.CoreV1().PersistentVolumeClaims(vm.Namespace).Get(context.TODO(), pvcName, metav1.GetOptions{}) + Expect(err).ToNot(HaveOccurred()) ++ if pvc.Spec.DataSourceRef != nil { ++ // These annotations only exist pre-k8s-populators flows ++ return ++ } + for _, a := range []string{"k8s.io/CloneRequest", "k8s.io/CloneOf"} { + _, ok := pvc.Annotations[a] + Expect(ok).Should(Equal(shouldExist)) + } + } + +- createVMFromSource := func() *v1.VirtualMachine { ++ createNetworkCloneVMFromSource := func() *v1.VirtualMachine { ++ // TODO: consider ensuring network clone gets done here using StorageProfile CloneStrategy + dataVolume := libdv.NewDataVolume( + libdv.WithPVCSource(sourceDV.Namespace, sourceDV.Name), + libdv.WithPVC(libdv.PVCWithStorageClass(snapshotStorageClass), libdv.PVCWithVolumeSize("1Gi")), +@@ -1796,7 +1801,7 @@ var _ = SIGDescribe("VirtualMachineRestore Tests", func() { + } + + DescribeTable("should restore a vm that boots from a network cloned datavolumetemplate", func(restoreToNewVM, deleteSourcePVC bool) { +- vm, vmi = createAndStartVM(createVMFromSource()) ++ vm, vmi = createAndStartVM(createNetworkCloneVMFromSource()) + + checkCloneAnnotations(vm, true) + if deleteSourcePVC { +@@ -1813,7 +1818,7 @@ var _ = SIGDescribe("VirtualMachineRestore Tests", func() { + ) + + DescribeTable("should restore a vm that boots from a network cloned datavolume (not template)", func(restoreToNewVM, deleteSourcePVC bool) { +- vm = createVMFromSource() ++ vm = createNetworkCloneVMFromSource() + dv := orphanDataVolumeTemplate(vm, 0) + + dv, err = virtClient.CdiClient().CdiV1beta1().DataVolumes(vm.Namespace).Create(context.Background(), dv, metav1.CreateOptions{}) +-- +2.41.0 + diff --git a/kubevirt.changes b/kubevirt.changes index 7cd7cd6..25b642e 100644 --- a/kubevirt.changes +++ b/kubevirt.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Wed Aug 16 07:13:42 UTC 2023 - Vasily Ulyanov + +- Bump client-go (fix possible panic in discovery) + 0011-Fix-Aggregated-Discovery.patch +- Wait for new hotplug attachment pod to be ready + 0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch +- Adapt the storage tests to the new populators flow + 0013-Adapt-e2e-tests-to-CDI-1.57.0.patch + ------------------------------------------------------------------- Tue Aug 8 06:02:05 UTC 2023 - Vasily Ulyanov diff --git a/kubevirt.spec b/kubevirt.spec index 909fae1..5ee52f2 100644 --- a/kubevirt.spec +++ b/kubevirt.spec @@ -38,6 +38,9 @@ Patch7: 0007-Fix-volume-detach-on-hotplug-attachment-pod-delete.patch Patch8: 0008-fix-ticker-leak.patch Patch9: 0009-tests-Run-helper-pod-as-qemu-107-user.patch Patch10: 0010-Fix-PR-leftover-mount-and-perms.patch +Patch11: 0011-Fix-Aggregated-Discovery.patch +Patch12: 0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch +Patch13: 0013-Adapt-e2e-tests-to-CDI-1.57.0.patch BuildRequires: glibc-devel-static BuildRequires: golang-packaging BuildRequires: pkgconfig From 17bc60771dfdb631c1f66ab0a1f31530fc366977bea1e9597c4e4f2ab2002f43 Mon Sep 17 00:00:00 2001 From: Vasily Ulyanov Date: Thu, 17 Aug 2023 09:15:47 +0000 Subject: [PATCH 2/2] Accepting request 1104343 from home:vulyanov:branches:Virtualization - Create export VM datavolumes compatible with populators 0014-Export-create-populator-compatible-datavolumes-from-.patch OBS-URL: https://build.opensuse.org/request/show/1104343 OBS-URL: https://build.opensuse.org/package/show/Virtualization/kubevirt?expand=0&rev=131 --- ...pulator-compatible-datavolumes-from-.patch | 56 +++++++++++++++++++ kubevirt.changes | 4 +- kubevirt.spec | 1 + 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 0014-Export-create-populator-compatible-datavolumes-from-.patch diff --git a/0014-Export-create-populator-compatible-datavolumes-from-.patch b/0014-Export-create-populator-compatible-datavolumes-from-.patch new file mode 100644 index 0000000..f8f59d5 --- /dev/null +++ b/0014-Export-create-populator-compatible-datavolumes-from-.patch @@ -0,0 +1,56 @@ +From 28f503c1417df30de3c7db8c14ced7c8985c9612 Mon Sep 17 00:00:00 2001 +From: Alexander Wels +Date: Thu, 13 Jul 2023 14:33:29 -0500 +Subject: [PATCH] Export create populator compatible datavolumes from VM + +The generated DataVolumes were not compatible with populator +populated sources. In particular the populators would have +a datasource or datasourceRef set. + +This commit clears the values so that the target CDI can +properly generate PVCs from the Datavolume + +Signed-off-by: Alexander Wels +--- + pkg/storage/export/export/export.go | 3 +++ + pkg/storage/export/export/export_test.go | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/pkg/storage/export/export/export.go b/pkg/storage/export/export/export.go +index c1ba57174..51eb69df6 100644 +--- a/pkg/storage/export/export/export.go ++++ b/pkg/storage/export/export/export.go +@@ -1429,6 +1429,9 @@ func (ctrl *VMExportController) createExportHttpDvFromPVC(namespace, name string + if pvc != nil { + pvc.Spec.VolumeName = "" + pvc.Spec.StorageClassName = nil ++ // Don't copy datasources, will be populated by CDI with the datavolume ++ pvc.Spec.DataSource = nil ++ pvc.Spec.DataSourceRef = nil + return &cdiv1.DataVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, +diff --git a/pkg/storage/export/export/export_test.go b/pkg/storage/export/export/export_test.go +index 15941984d..a341bdca6 100644 +--- a/pkg/storage/export/export/export_test.go ++++ b/pkg/storage/export/export/export_test.go +@@ -1310,12 +1310,16 @@ var _ = Describe("Export controller", func() { + + It("Should generate DataVolumes from VM", func() { + pvc := createPVC("pvc", string(cdiv1.DataVolumeKubeVirt)) ++ pvc.Spec.DataSource = &k8sv1.TypedLocalObjectReference{} ++ pvc.Spec.DataSourceRef = &k8sv1.TypedObjectReference{} + pvcInformer.GetStore().Add(pvc) + vm := createVMWithDVTemplateAndPVC() + dvs := controller.generateDataVolumesFromVm(vm) + Expect(dvs).To(HaveLen(1)) + Expect(dvs[0]).ToNot(BeNil()) + Expect(dvs[0].Name).To((Equal("pvc"))) ++ Expect(dvs[0].Spec.PVC.DataSource).To(BeNil()) ++ Expect(dvs[0].Spec.PVC.DataSourceRef).To(BeNil()) + }) + }) + +-- +2.41.0 + diff --git a/kubevirt.changes b/kubevirt.changes index 25b642e..7fd7f66 100644 --- a/kubevirt.changes +++ b/kubevirt.changes @@ -1,5 +1,5 @@ ------------------------------------------------------------------- -Wed Aug 16 07:13:42 UTC 2023 - Vasily Ulyanov +Thu Aug 17 09:10:31 UTC 2023 - Vasily Ulyanov - Bump client-go (fix possible panic in discovery) 0011-Fix-Aggregated-Discovery.patch @@ -7,6 +7,8 @@ Wed Aug 16 07:13:42 UTC 2023 - Vasily Ulyanov 0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch - Adapt the storage tests to the new populators flow 0013-Adapt-e2e-tests-to-CDI-1.57.0.patch +- Create export VM datavolumes compatible with populators + 0014-Export-create-populator-compatible-datavolumes-from-.patch ------------------------------------------------------------------- Tue Aug 8 06:02:05 UTC 2023 - Vasily Ulyanov diff --git a/kubevirt.spec b/kubevirt.spec index 5ee52f2..c2cb7ab 100644 --- a/kubevirt.spec +++ b/kubevirt.spec @@ -41,6 +41,7 @@ Patch10: 0010-Fix-PR-leftover-mount-and-perms.patch Patch11: 0011-Fix-Aggregated-Discovery.patch Patch12: 0012-Wait-for-new-hotplug-attachment-pod-to-be-ready.patch Patch13: 0013-Adapt-e2e-tests-to-CDI-1.57.0.patch +Patch14: 0014-Export-create-populator-compatible-datavolumes-from-.patch BuildRequires: glibc-devel-static BuildRequires: golang-packaging BuildRequires: pkgconfig