diff --git a/go.mod b/go.mod index 1087b2c00..041eceb1d 100644 --- a/go.mod +++ b/go.mod @@ -8,32 +8,32 @@ require ( github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 go.uber.org/zap v1.27.0 - golang.org/x/sync v0.17.0 + golang.org/x/sync v0.18.0 golang.org/x/time v0.10.0 google.golang.org/grpc v1.75.0 - k8s.io/api v0.33.5 - k8s.io/apimachinery v0.33.5 - k8s.io/client-go v0.33.5 - k8s.io/code-generator v0.33.5 - k8s.io/utils v0.0.0-20241210054802-24370beab758 - knative.dev/hack v0.0.0-20251021013703-4fae78067103 - knative.dev/pkg v0.0.0-20251022152246-7bf6febca0b3 + k8s.io/api v0.34.2 + k8s.io/apimachinery v0.34.2 + k8s.io/client-go v0.34.2 + k8s.io/code-generator v0.34.2 + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 + knative.dev/hack v0.0.0-20251117013754-67a5b048bc27 + knative.dev/pkg v0.0.0-20251119125415-ab67eb7f8660 sigs.k8s.io/yaml v1.6.0 ) require ( github.com/blendle/zapdriver v1.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/gnostic-models v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -41,9 +41,10 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect @@ -53,6 +54,7 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/mod v0.29.0 // indirect golang.org/x/net v0.46.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect @@ -67,10 +69,10 @@ require ( gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 // indirect + k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) diff --git a/go.sum b/go.sum index b2521cff7..1a5ef5293 100644 --- a/go.sum +++ b/go.sum @@ -4,16 +4,16 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= -github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -31,9 +31,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= -github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -62,8 +61,9 @@ github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUt 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= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= @@ -116,8 +116,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= -go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= -go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -136,8 +136,8 @@ golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKl golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -184,33 +184,31 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.33.5 h1:YR+uhYj05jdRpcksv8kjSliW+v9hwXxn6Cv10aR8Juw= -k8s.io/api v0.33.5/go.mod h1:2gzShdwXKT5yPGiqrTrn/U/nLZ7ZyT4WuAj3XGDVgVs= -k8s.io/apimachinery v0.33.5 h1:NiT64hln4TQXeYR18/ES39OrNsjGz8NguxsBgp+6QIo= -k8s.io/apimachinery v0.33.5/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.5 h1:I8BdmQGxInpkMEnJvV6iG7dqzP3JRlpZZlib3OMFc3o= -k8s.io/client-go v0.33.5/go.mod h1:W8PQP4MxbM4ypgagVE65mUUqK1/ByQkSALF9tzuQ6u0= -k8s.io/code-generator v0.33.5 h1:KwkOvhwAaorjSwF2MQhhdhL3i8bBmAal/TWhX67kdHw= -k8s.io/code-generator v0.33.5/go.mod h1:Ra+sdZquRakeTGcEnQAPw6BmlZ92IvxwQQTX/XOvOIE= -k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog= -k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= +k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= +k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= +k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= +k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M= +k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE= +k8s.io/code-generator v0.34.2 h1:9bG6jTxmsU3HXE5BNYJTC8AZ1D6hVVfkm8yYSkdkGY0= +k8s.io/code-generator v0.34.2/go.mod h1:dnDDEd6S/z4uZ+PG1aE58ySCi/lR4+qT3a4DddE4/2I= +k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBbT2+x7Zq9ROIHmGn9Q= +k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= -k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= -k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/hack v0.0.0-20251021013703-4fae78067103 h1:j96YY5CLCTytWZsGVzixVvNasRbrni2NuXI54R+IPvA= -knative.dev/hack v0.0.0-20251021013703-4fae78067103/go.mod h1:L5RzHgbvam0u8QFHfzCX6MKxu/a/gIGEdaRBqNiVbl0= -knative.dev/pkg v0.0.0-20251022152246-7bf6febca0b3 h1:472SARbX5rEir4g3QC/UsKnHNXqdRNbWOe2a4DcJRwk= -knative.dev/pkg v0.0.0-20251022152246-7bf6febca0b3/go.mod h1:8L1vgh3WoZ4OH9gspPSt3QFcMJsrOUBwOs0FuM5Jne8= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +knative.dev/hack v0.0.0-20251117013754-67a5b048bc27 h1:yPzDTKOFtSYHxgXB2N7+nWT/3doNqPNCbCf7Bf9PeAE= +knative.dev/hack v0.0.0-20251117013754-67a5b048bc27/go.mod h1:L5RzHgbvam0u8QFHfzCX6MKxu/a/gIGEdaRBqNiVbl0= +knative.dev/pkg v0.0.0-20251119125415-ab67eb7f8660 h1:4lJPD8CTsOZ6cXFYkm3LtZ8bruSY9OQpyIFS6S5NPGQ= +knative.dev/pkg v0.0.0-20251119125415-ab67eb7f8660/go.mod h1:iVOYfi7BiB0jQEEiW3NUfBHVOjc0QIbdOqdNs47YEoI= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= -sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/pkg/client/injection/reconciler/networking/v1alpha1/certificate/controller.go b/pkg/client/injection/reconciler/networking/v1alpha1/certificate/controller.go index 4f6e5140b..3be44ced2 100644 --- a/pkg/client/injection/reconciler/networking/v1alpha1/certificate/controller.go +++ b/pkg/client/injection/reconciler/networking/v1alpha1/certificate/controller.go @@ -137,6 +137,14 @@ func NewImpl(ctx context.Context, r Interface, classValue string, optionsFns ... if opts.PromoteFunc != nil { promoteFunc = opts.PromoteFunc } + if opts.UseServerSideApplyForFinalizers { + if opts.FinalizerFieldManager == "" { + logger.Fatal("FinalizerFieldManager must be provided when UseServerSideApplyForFinalizers is enabled") + } + rec.useServerSideApplyForFinalizers = true + rec.finalizerFieldManager = opts.FinalizerFieldManager + rec.forceApplyFinalizers = opts.ForceApplyFinalizers + } } rec.Recorder = createRecorder(ctx, agentName) diff --git a/pkg/client/injection/reconciler/networking/v1alpha1/certificate/reconciler.go b/pkg/client/injection/reconciler/networking/v1alpha1/certificate/reconciler.go index 728913ed6..7b11a136c 100644 --- a/pkg/client/injection/reconciler/networking/v1alpha1/certificate/reconciler.go +++ b/pkg/client/injection/reconciler/networking/v1alpha1/certificate/reconciler.go @@ -32,6 +32,7 @@ import ( labels "k8s.io/apimachinery/pkg/labels" types "k8s.io/apimachinery/pkg/types" sets "k8s.io/apimachinery/pkg/util/sets" + scheme "k8s.io/client-go/kubernetes/scheme" record "k8s.io/client-go/tools/record" v1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1" versioned "knative.dev/networking/pkg/client/clientset/versioned" @@ -101,6 +102,15 @@ type reconcilerImpl struct { // finalizerName is the name of the finalizer to reconcile. finalizerName string + // useServerSideApplyForFinalizers configures whether to use server-side apply for finalizer management + useServerSideApplyForFinalizers bool + + // finalizerFieldManager is the field manager name for server-side apply of finalizers + finalizerFieldManager string + + // forceApplyFinalizers configures whether to force server-side apply for finalizers + forceApplyFinalizers bool + // skipStatusUpdates configures whether or not this reconciler automatically updates // the status of the reconciled resource. skipStatusUpdates bool @@ -165,6 +175,14 @@ func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versio if opts.DemoteFunc != nil { rec.DemoteFunc = opts.DemoteFunc } + if opts.UseServerSideApplyForFinalizers { + if opts.FinalizerFieldManager == "" { + logger.Fatal("FinalizerFieldManager must be provided when UseServerSideApplyForFinalizers is enabled") + } + rec.useServerSideApplyForFinalizers = true + rec.finalizerFieldManager = opts.FinalizerFieldManager + rec.forceApplyFinalizers = opts.ForceApplyFinalizers + } } return rec @@ -310,6 +328,8 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { // This is a wrapped error, don't emit an event. } else if ok, _ := controller.IsRequeueKey(reconcileEvent); ok { // This is a wrapped error, don't emit an event. + } else if errors.IsConflict(reconcileEvent) { + // Conflict errors are expected, don't emit an event. } else { logger.Errorw("Returned an error", zap.Error(reconcileEvent)) r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) @@ -358,6 +378,82 @@ func (r *reconcilerImpl) updateStatus(ctx context.Context, logger *zap.SugaredLo // TODO: this method could be generic and sync all finalizers. For now it only // updates defaultFinalizerName or its override. func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.Certificate, desiredFinalizers sets.Set[string]) (*v1alpha1.Certificate, error) { + if r.useServerSideApplyForFinalizers { + return r.updateFinalizersFilteredServerSideApply(ctx, resource, desiredFinalizers) + } + return r.updateFinalizersFilteredMergePatch(ctx, resource, desiredFinalizers) +} + +// updateFinalizersFilteredServerSideApply uses server-side apply to manage only this controller's finalizer. +func (r *reconcilerImpl) updateFinalizersFilteredServerSideApply(ctx context.Context, resource *v1alpha1.Certificate, desiredFinalizers sets.Set[string]) (*v1alpha1.Certificate, error) { + // Check if we need to do anything + existingFinalizers := sets.New[string](resource.Finalizers...) + + var finalizers []string + if desiredFinalizers.Has(r.finalizerName) { + if existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // Apply configuration with only our finalizer to add it. + finalizers = []string{r.finalizerName} + } else { + if !existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // For removal, we apply an empty configuration for our finalizer field manager. + // This effectively removes our finalizer while preserving others. + finalizers = []string{} // Empty array removes our managed finalizers + } + + // Determine GVK + gvks, _, err := scheme.Scheme.ObjectKinds(resource) + if err != nil || len(gvks) == 0 { + return resource, fmt.Errorf("failed to determine GVK for resource: %w", err) + } + gvk := gvks[0] + + // Create apply configuration + applyConfig := map[string]interface{}{ + "apiVersion": gvk.GroupVersion().String(), + "kind": gvk.Kind, + "metadata": map[string]interface{}{ + "name": resource.Name, + "uid": resource.UID, + "finalizers": finalizers, + }, + } + + applyConfig["metadata"].(map[string]interface{})["namespace"] = resource.Namespace + + patch, err := json.Marshal(applyConfig) + if err != nil { + return resource, err + } + + patcher := r.Client.NetworkingV1alpha1().Certificates(resource.Namespace) + + patchOpts := metav1.PatchOptions{ + FieldManager: r.finalizerFieldManager, + Force: &r.forceApplyFinalizers, + } + + updated, err := patcher.Patch(ctx, resource.Name, types.ApplyPatchType, patch, patchOpts) + if err != nil { + if !errors.IsConflict(err) { + r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", + "Failed to update finalizers for %q via server-side apply: %v", resource.Name, err) + } + } else { + r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate", + "Updated finalizers for %q via server-side apply", resource.GetName()) + } + return updated, err +} + +// updateFinalizersFilteredMergePatch uses merge patch to manage finalizers (legacy behavior). +func (r *reconcilerImpl) updateFinalizersFilteredMergePatch(ctx context.Context, resource *v1alpha1.Certificate, desiredFinalizers sets.Set[string]) (*v1alpha1.Certificate, error) { // Don't modify the informers copy. existing := resource.DeepCopy() @@ -400,8 +496,10 @@ func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource resourceName := resource.Name updated, err := patcher.Patch(ctx, resourceName, types.MergePatchType, patch, metav1.PatchOptions{}) if err != nil { - r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) + if !errors.IsConflict(err) { + r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed", + "Failed to update finalizers for %q: %v", resourceName, err) + } } else { r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", resource.GetName()) @@ -447,5 +545,28 @@ func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1. } // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource, finalizers) + updated, err := r.updateFinalizersFiltered(ctx, resource, finalizers) + if err != nil { + // Check if the resource still exists by querying the API server to avoid logging errors + // when reconciling stale object from cache while the object is actually deleted. + logger := logging.FromContext(ctx) + + getter := r.Client.NetworkingV1alpha1().Certificates(resource.Namespace) + + _, getErr := getter.Get(ctx, resource.Name, metav1.GetOptions{}) + if errors.IsNotFound(getErr) { + // Resource no longer exists, which could happen during deletion + logger.Debugw("Resource no longer exists while clearing finalizers", + "resource", resource.GetName(), + "namespace", resource.GetNamespace(), + "originalError", err) + // Return the original resource since the finalizer clearing is effectively complete + return resource, nil + } + + // For other errors, return the original error + return updated, err + } + + return updated, nil } diff --git a/pkg/client/injection/reconciler/networking/v1alpha1/ingress/controller.go b/pkg/client/injection/reconciler/networking/v1alpha1/ingress/controller.go index 8eb45e03e..9aa0162e6 100644 --- a/pkg/client/injection/reconciler/networking/v1alpha1/ingress/controller.go +++ b/pkg/client/injection/reconciler/networking/v1alpha1/ingress/controller.go @@ -137,6 +137,14 @@ func NewImpl(ctx context.Context, r Interface, classValue string, optionsFns ... if opts.PromoteFunc != nil { promoteFunc = opts.PromoteFunc } + if opts.UseServerSideApplyForFinalizers { + if opts.FinalizerFieldManager == "" { + logger.Fatal("FinalizerFieldManager must be provided when UseServerSideApplyForFinalizers is enabled") + } + rec.useServerSideApplyForFinalizers = true + rec.finalizerFieldManager = opts.FinalizerFieldManager + rec.forceApplyFinalizers = opts.ForceApplyFinalizers + } } rec.Recorder = createRecorder(ctx, agentName) diff --git a/pkg/client/injection/reconciler/networking/v1alpha1/ingress/reconciler.go b/pkg/client/injection/reconciler/networking/v1alpha1/ingress/reconciler.go index 41e161060..1ae4170fd 100644 --- a/pkg/client/injection/reconciler/networking/v1alpha1/ingress/reconciler.go +++ b/pkg/client/injection/reconciler/networking/v1alpha1/ingress/reconciler.go @@ -32,6 +32,7 @@ import ( labels "k8s.io/apimachinery/pkg/labels" types "k8s.io/apimachinery/pkg/types" sets "k8s.io/apimachinery/pkg/util/sets" + scheme "k8s.io/client-go/kubernetes/scheme" record "k8s.io/client-go/tools/record" v1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1" versioned "knative.dev/networking/pkg/client/clientset/versioned" @@ -101,6 +102,15 @@ type reconcilerImpl struct { // finalizerName is the name of the finalizer to reconcile. finalizerName string + // useServerSideApplyForFinalizers configures whether to use server-side apply for finalizer management + useServerSideApplyForFinalizers bool + + // finalizerFieldManager is the field manager name for server-side apply of finalizers + finalizerFieldManager string + + // forceApplyFinalizers configures whether to force server-side apply for finalizers + forceApplyFinalizers bool + // skipStatusUpdates configures whether or not this reconciler automatically updates // the status of the reconciled resource. skipStatusUpdates bool @@ -165,6 +175,14 @@ func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versio if opts.DemoteFunc != nil { rec.DemoteFunc = opts.DemoteFunc } + if opts.UseServerSideApplyForFinalizers { + if opts.FinalizerFieldManager == "" { + logger.Fatal("FinalizerFieldManager must be provided when UseServerSideApplyForFinalizers is enabled") + } + rec.useServerSideApplyForFinalizers = true + rec.finalizerFieldManager = opts.FinalizerFieldManager + rec.forceApplyFinalizers = opts.ForceApplyFinalizers + } } return rec @@ -310,6 +328,8 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { // This is a wrapped error, don't emit an event. } else if ok, _ := controller.IsRequeueKey(reconcileEvent); ok { // This is a wrapped error, don't emit an event. + } else if errors.IsConflict(reconcileEvent) { + // Conflict errors are expected, don't emit an event. } else { logger.Errorw("Returned an error", zap.Error(reconcileEvent)) r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) @@ -358,6 +378,82 @@ func (r *reconcilerImpl) updateStatus(ctx context.Context, logger *zap.SugaredLo // TODO: this method could be generic and sync all finalizers. For now it only // updates defaultFinalizerName or its override. func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.Ingress, desiredFinalizers sets.Set[string]) (*v1alpha1.Ingress, error) { + if r.useServerSideApplyForFinalizers { + return r.updateFinalizersFilteredServerSideApply(ctx, resource, desiredFinalizers) + } + return r.updateFinalizersFilteredMergePatch(ctx, resource, desiredFinalizers) +} + +// updateFinalizersFilteredServerSideApply uses server-side apply to manage only this controller's finalizer. +func (r *reconcilerImpl) updateFinalizersFilteredServerSideApply(ctx context.Context, resource *v1alpha1.Ingress, desiredFinalizers sets.Set[string]) (*v1alpha1.Ingress, error) { + // Check if we need to do anything + existingFinalizers := sets.New[string](resource.Finalizers...) + + var finalizers []string + if desiredFinalizers.Has(r.finalizerName) { + if existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // Apply configuration with only our finalizer to add it. + finalizers = []string{r.finalizerName} + } else { + if !existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // For removal, we apply an empty configuration for our finalizer field manager. + // This effectively removes our finalizer while preserving others. + finalizers = []string{} // Empty array removes our managed finalizers + } + + // Determine GVK + gvks, _, err := scheme.Scheme.ObjectKinds(resource) + if err != nil || len(gvks) == 0 { + return resource, fmt.Errorf("failed to determine GVK for resource: %w", err) + } + gvk := gvks[0] + + // Create apply configuration + applyConfig := map[string]interface{}{ + "apiVersion": gvk.GroupVersion().String(), + "kind": gvk.Kind, + "metadata": map[string]interface{}{ + "name": resource.Name, + "uid": resource.UID, + "finalizers": finalizers, + }, + } + + applyConfig["metadata"].(map[string]interface{})["namespace"] = resource.Namespace + + patch, err := json.Marshal(applyConfig) + if err != nil { + return resource, err + } + + patcher := r.Client.NetworkingV1alpha1().Ingresses(resource.Namespace) + + patchOpts := metav1.PatchOptions{ + FieldManager: r.finalizerFieldManager, + Force: &r.forceApplyFinalizers, + } + + updated, err := patcher.Patch(ctx, resource.Name, types.ApplyPatchType, patch, patchOpts) + if err != nil { + if !errors.IsConflict(err) { + r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", + "Failed to update finalizers for %q via server-side apply: %v", resource.Name, err) + } + } else { + r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate", + "Updated finalizers for %q via server-side apply", resource.GetName()) + } + return updated, err +} + +// updateFinalizersFilteredMergePatch uses merge patch to manage finalizers (legacy behavior). +func (r *reconcilerImpl) updateFinalizersFilteredMergePatch(ctx context.Context, resource *v1alpha1.Ingress, desiredFinalizers sets.Set[string]) (*v1alpha1.Ingress, error) { // Don't modify the informers copy. existing := resource.DeepCopy() @@ -400,8 +496,10 @@ func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource resourceName := resource.Name updated, err := patcher.Patch(ctx, resourceName, types.MergePatchType, patch, metav1.PatchOptions{}) if err != nil { - r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) + if !errors.IsConflict(err) { + r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed", + "Failed to update finalizers for %q: %v", resourceName, err) + } } else { r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", resource.GetName()) @@ -447,5 +545,28 @@ func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1. } // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource, finalizers) + updated, err := r.updateFinalizersFiltered(ctx, resource, finalizers) + if err != nil { + // Check if the resource still exists by querying the API server to avoid logging errors + // when reconciling stale object from cache while the object is actually deleted. + logger := logging.FromContext(ctx) + + getter := r.Client.NetworkingV1alpha1().Ingresses(resource.Namespace) + + _, getErr := getter.Get(ctx, resource.Name, metav1.GetOptions{}) + if errors.IsNotFound(getErr) { + // Resource no longer exists, which could happen during deletion + logger.Debugw("Resource no longer exists while clearing finalizers", + "resource", resource.GetName(), + "namespace", resource.GetNamespace(), + "originalError", err) + // Return the original resource since the finalizer clearing is effectively complete + return resource, nil + } + + // For other errors, return the original error + return updated, err + } + + return updated, nil } diff --git a/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/controller.go b/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/controller.go index ae3179a6c..04abba2ae 100644 --- a/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/controller.go +++ b/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/controller.go @@ -133,6 +133,14 @@ func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsF if opts.PromoteFunc != nil { promoteFunc = opts.PromoteFunc } + if opts.UseServerSideApplyForFinalizers { + if opts.FinalizerFieldManager == "" { + logger.Fatal("FinalizerFieldManager must be provided when UseServerSideApplyForFinalizers is enabled") + } + rec.useServerSideApplyForFinalizers = true + rec.finalizerFieldManager = opts.FinalizerFieldManager + rec.forceApplyFinalizers = opts.ForceApplyFinalizers + } } rec.Recorder = createRecorder(ctx, agentName) diff --git a/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go b/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go index c450f8df4..72a6baaa5 100644 --- a/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go +++ b/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go @@ -32,6 +32,7 @@ import ( labels "k8s.io/apimachinery/pkg/labels" types "k8s.io/apimachinery/pkg/types" sets "k8s.io/apimachinery/pkg/util/sets" + scheme "k8s.io/client-go/kubernetes/scheme" record "k8s.io/client-go/tools/record" v1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1" versioned "knative.dev/networking/pkg/client/clientset/versioned" @@ -101,6 +102,15 @@ type reconcilerImpl struct { // finalizerName is the name of the finalizer to reconcile. finalizerName string + // useServerSideApplyForFinalizers configures whether to use server-side apply for finalizer management + useServerSideApplyForFinalizers bool + + // finalizerFieldManager is the field manager name for server-side apply of finalizers + finalizerFieldManager string + + // forceApplyFinalizers configures whether to force server-side apply for finalizers + forceApplyFinalizers bool + // skipStatusUpdates configures whether or not this reconciler automatically updates // the status of the reconciled resource. skipStatusUpdates bool @@ -161,6 +171,14 @@ func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versio if opts.DemoteFunc != nil { rec.DemoteFunc = opts.DemoteFunc } + if opts.UseServerSideApplyForFinalizers { + if opts.FinalizerFieldManager == "" { + logger.Fatal("FinalizerFieldManager must be provided when UseServerSideApplyForFinalizers is enabled") + } + rec.useServerSideApplyForFinalizers = true + rec.finalizerFieldManager = opts.FinalizerFieldManager + rec.forceApplyFinalizers = opts.ForceApplyFinalizers + } } return rec @@ -299,6 +317,8 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { // This is a wrapped error, don't emit an event. } else if ok, _ := controller.IsRequeueKey(reconcileEvent); ok { // This is a wrapped error, don't emit an event. + } else if errors.IsConflict(reconcileEvent) { + // Conflict errors are expected, don't emit an event. } else { logger.Errorw("Returned an error", zap.Error(reconcileEvent)) r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) @@ -347,6 +367,82 @@ func (r *reconcilerImpl) updateStatus(ctx context.Context, logger *zap.SugaredLo // TODO: this method could be generic and sync all finalizers. For now it only // updates defaultFinalizerName or its override. func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.ServerlessService, desiredFinalizers sets.Set[string]) (*v1alpha1.ServerlessService, error) { + if r.useServerSideApplyForFinalizers { + return r.updateFinalizersFilteredServerSideApply(ctx, resource, desiredFinalizers) + } + return r.updateFinalizersFilteredMergePatch(ctx, resource, desiredFinalizers) +} + +// updateFinalizersFilteredServerSideApply uses server-side apply to manage only this controller's finalizer. +func (r *reconcilerImpl) updateFinalizersFilteredServerSideApply(ctx context.Context, resource *v1alpha1.ServerlessService, desiredFinalizers sets.Set[string]) (*v1alpha1.ServerlessService, error) { + // Check if we need to do anything + existingFinalizers := sets.New[string](resource.Finalizers...) + + var finalizers []string + if desiredFinalizers.Has(r.finalizerName) { + if existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // Apply configuration with only our finalizer to add it. + finalizers = []string{r.finalizerName} + } else { + if !existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // For removal, we apply an empty configuration for our finalizer field manager. + // This effectively removes our finalizer while preserving others. + finalizers = []string{} // Empty array removes our managed finalizers + } + + // Determine GVK + gvks, _, err := scheme.Scheme.ObjectKinds(resource) + if err != nil || len(gvks) == 0 { + return resource, fmt.Errorf("failed to determine GVK for resource: %w", err) + } + gvk := gvks[0] + + // Create apply configuration + applyConfig := map[string]interface{}{ + "apiVersion": gvk.GroupVersion().String(), + "kind": gvk.Kind, + "metadata": map[string]interface{}{ + "name": resource.Name, + "uid": resource.UID, + "finalizers": finalizers, + }, + } + + applyConfig["metadata"].(map[string]interface{})["namespace"] = resource.Namespace + + patch, err := json.Marshal(applyConfig) + if err != nil { + return resource, err + } + + patcher := r.Client.NetworkingV1alpha1().ServerlessServices(resource.Namespace) + + patchOpts := metav1.PatchOptions{ + FieldManager: r.finalizerFieldManager, + Force: &r.forceApplyFinalizers, + } + + updated, err := patcher.Patch(ctx, resource.Name, types.ApplyPatchType, patch, patchOpts) + if err != nil { + if !errors.IsConflict(err) { + r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", + "Failed to update finalizers for %q via server-side apply: %v", resource.Name, err) + } + } else { + r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate", + "Updated finalizers for %q via server-side apply", resource.GetName()) + } + return updated, err +} + +// updateFinalizersFilteredMergePatch uses merge patch to manage finalizers (legacy behavior). +func (r *reconcilerImpl) updateFinalizersFilteredMergePatch(ctx context.Context, resource *v1alpha1.ServerlessService, desiredFinalizers sets.Set[string]) (*v1alpha1.ServerlessService, error) { // Don't modify the informers copy. existing := resource.DeepCopy() @@ -389,8 +485,10 @@ func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource resourceName := resource.Name updated, err := patcher.Patch(ctx, resourceName, types.MergePatchType, patch, metav1.PatchOptions{}) if err != nil { - r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed", - "Failed to update finalizers for %q: %v", resourceName, err) + if !errors.IsConflict(err) { + r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed", + "Failed to update finalizers for %q: %v", resourceName, err) + } } else { r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate", "Updated %q finalizers", resource.GetName()) @@ -436,5 +534,28 @@ func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1. } // Synchronize the finalizers filtered by r.finalizerName. - return r.updateFinalizersFiltered(ctx, resource, finalizers) + updated, err := r.updateFinalizersFiltered(ctx, resource, finalizers) + if err != nil { + // Check if the resource still exists by querying the API server to avoid logging errors + // when reconciling stale object from cache while the object is actually deleted. + logger := logging.FromContext(ctx) + + getter := r.Client.NetworkingV1alpha1().ServerlessServices(resource.Namespace) + + _, getErr := getter.Get(ctx, resource.Name, metav1.GetOptions{}) + if errors.IsNotFound(getErr) { + // Resource no longer exists, which could happen during deletion + logger.Debugw("Resource no longer exists while clearing finalizers", + "resource", resource.GetName(), + "namespace", resource.GetNamespace(), + "originalError", err) + // Return the original resource since the finalizer clearing is effectively complete + return resource, nil + } + + // For other errors, return the original error + return updated, err + } + + return updated, nil } diff --git a/vendor/github.com/emicklei/go-restful/v3/CHANGES.md b/vendor/github.com/emicklei/go-restful/v3/CHANGES.md index 92b78048e..6f24dfff5 100644 --- a/vendor/github.com/emicklei/go-restful/v3/CHANGES.md +++ b/vendor/github.com/emicklei/go-restful/v3/CHANGES.md @@ -1,5 +1,8 @@ # Change history of go-restful +## [v3.12.2] - 2025-02-21 + +- allow empty payloads in post,put,patch, issue #580 ( thanks @liggitt, Jordan Liggitt) ## [v3.12.1] - 2024-05-28 @@ -18,7 +21,7 @@ - fix by restoring custom JSON handler functions (Mike Beaumont #540) -## [v3.12.0] - 2023-08-19 +## [v3.11.0] - 2023-08-19 - restored behavior as <= v3.9.0 with option to change path strategy using TrimRightSlashEnabled. diff --git a/vendor/github.com/emicklei/go-restful/v3/README.md b/vendor/github.com/emicklei/go-restful/v3/README.md index 7234604e4..3fb40d198 100644 --- a/vendor/github.com/emicklei/go-restful/v3/README.md +++ b/vendor/github.com/emicklei/go-restful/v3/README.md @@ -3,7 +3,7 @@ go-restful package for building REST-style Web Services using Google Go [](https://goreportcard.com/report/github.com/emicklei/go-restful) -[](https://pkg.go.dev/github.com/emicklei/go-restful) +[](https://pkg.go.dev/github.com/emicklei/go-restful/v3) [](https://codecov.io/gh/emicklei/go-restful) - [Code examples use v3](https://github.com/emicklei/go-restful/tree/v3/examples) diff --git a/vendor/github.com/emicklei/go-restful/v3/jsr311.go b/vendor/github.com/emicklei/go-restful/v3/jsr311.go index a9b3faaa8..7f04bd905 100644 --- a/vendor/github.com/emicklei/go-restful/v3/jsr311.go +++ b/vendor/github.com/emicklei/go-restful/v3/jsr311.go @@ -65,7 +65,7 @@ func (RouterJSR311) extractParams(pathExpr *pathExpression, matches []string) ma return params } -// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2 +// https://download.oracle.com/otndocs/jcp/jaxrs-1.1-mrel-eval-oth-JSpec/ func (r RouterJSR311) detectRoute(routes []Route, httpRequest *http.Request) (*Route, error) { candidates := make([]*Route, 0, 8) for i, each := range routes { @@ -126,9 +126,7 @@ func (r RouterJSR311) detectRoute(routes []Route, httpRequest *http.Request) (*R if trace { traceLogger.Printf("no Route found (from %d) that matches HTTP Content-Type: %s\n", len(previous), contentType) } - if httpRequest.ContentLength > 0 { - return nil, NewError(http.StatusUnsupportedMediaType, "415: Unsupported Media Type") - } + return nil, NewError(http.StatusUnsupportedMediaType, "415: Unsupported Media Type") } // accept @@ -151,20 +149,9 @@ func (r RouterJSR311) detectRoute(routes []Route, httpRequest *http.Request) (*R for _, candidate := range previous { available = append(available, candidate.Produces...) } - // if POST,PUT,PATCH without body - method, length := httpRequest.Method, httpRequest.Header.Get("Content-Length") - if (method == http.MethodPost || - method == http.MethodPut || - method == http.MethodPatch) && (length == "" || length == "0") { - return nil, NewError( - http.StatusUnsupportedMediaType, - fmt.Sprintf("415: Unsupported Media Type\n\nAvailable representations: %s", strings.Join(available, ", ")), - ) - } return nil, NewError( http.StatusNotAcceptable, - fmt.Sprintf("406: Not Acceptable\n\nAvailable representations: %s", strings.Join(available, ", ")), - ) + fmt.Sprintf("406: Not Acceptable\n\nAvailable representations: %s", strings.Join(available, ", "))) } // return r.bestMatchByMedia(outputMediaOk, contentType, accept), nil return candidates[0], nil diff --git a/vendor/github.com/emicklei/go-restful/v3/route.go b/vendor/github.com/emicklei/go-restful/v3/route.go index 306c44be7..a2056e2ac 100644 --- a/vendor/github.com/emicklei/go-restful/v3/route.go +++ b/vendor/github.com/emicklei/go-restful/v3/route.go @@ -111,6 +111,8 @@ func (r Route) matchesAccept(mimeTypesWithQuality string) bool { } // Return whether this Route can consume content with a type specified by mimeTypes (can be empty). +// If the route does not specify Consumes then return true (*/*). +// If no content type is set then return true for GET,HEAD,OPTIONS,DELETE and TRACE. func (r Route) matchesContentType(mimeTypes string) bool { if len(r.Consumes) == 0 { diff --git a/vendor/github.com/fxamacker/cbor/v2/README.md b/vendor/github.com/fxamacker/cbor/v2/README.md index af0a79507..d072b81c7 100644 --- a/vendor/github.com/fxamacker/cbor/v2/README.md +++ b/vendor/github.com/fxamacker/cbor/v2/README.md @@ -1,30 +1,31 @@ -# CBOR Codec in Go - - +