mirror of
https://github.com/kubernetes/client-go.git
synced 2025-09-23 12:07:05 +00:00
Merge pull request #123484 from erikgb/csa-upgrade-subresource
Add option to upgrade subresource from CSA to SSA Kubernetes-commit: 65d75501f7d7348db1610e755e654b67c6639897
This commit is contained in:
4
go.mod
4
go.mod
@@ -25,7 +25,7 @@ require (
|
|||||||
golang.org/x/time v0.3.0
|
golang.org/x/time v0.3.0
|
||||||
google.golang.org/protobuf v1.31.0
|
google.golang.org/protobuf v1.31.0
|
||||||
k8s.io/api v0.0.0-20240301204737-cd36300dc819
|
k8s.io/api v0.0.0-20240301204737-cd36300dc819
|
||||||
k8s.io/apimachinery v0.0.0-20240301204447-c9969982b5df
|
k8s.io/apimachinery v0.0.0-20240302004725-df38a01ea799
|
||||||
k8s.io/klog/v2 v2.120.1
|
k8s.io/klog/v2 v2.120.1
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
|
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
|
||||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||||
@@ -62,5 +62,5 @@ require (
|
|||||||
|
|
||||||
replace (
|
replace (
|
||||||
k8s.io/api => k8s.io/api v0.0.0-20240301204737-cd36300dc819
|
k8s.io/api => k8s.io/api v0.0.0-20240301204737-cd36300dc819
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20240301204447-c9969982b5df
|
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20240302004725-df38a01ea799
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@@ -159,8 +159,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
k8s.io/api v0.0.0-20240301204737-cd36300dc819 h1:F87SZX4P+r/LNtLhFtsZjylRqRLRSX7rcvGKdjVy1UM=
|
k8s.io/api v0.0.0-20240301204737-cd36300dc819 h1:F87SZX4P+r/LNtLhFtsZjylRqRLRSX7rcvGKdjVy1UM=
|
||||||
k8s.io/api v0.0.0-20240301204737-cd36300dc819/go.mod h1:TYylmz5ON3nmsvimIN46iaRIjQwS/RcA5nYFRkdJmT4=
|
k8s.io/api v0.0.0-20240301204737-cd36300dc819/go.mod h1:TYylmz5ON3nmsvimIN46iaRIjQwS/RcA5nYFRkdJmT4=
|
||||||
k8s.io/apimachinery v0.0.0-20240301204447-c9969982b5df h1:kVut1P6llpgJ5z8PeeXh/f7f8Nkf0Zo4Rai0nhfq7bI=
|
k8s.io/apimachinery v0.0.0-20240302004725-df38a01ea799 h1:QqDm+JeV6HCqng5kBgyWDazPe4nK0P20XhjX5Bx9elE=
|
||||||
k8s.io/apimachinery v0.0.0-20240301204447-c9969982b5df/go.mod h1:qPsrq6INURDMMgqxK78MEuC8GzI1f2oHvfHzg5ZOa6s=
|
k8s.io/apimachinery v0.0.0-20240302004725-df38a01ea799/go.mod h1:qPsrq6INURDMMgqxK78MEuC8GzI1f2oHvfHzg5ZOa6s=
|
||||||
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||||
|
30
util/csaupgrade/options.go
Normal file
30
util/csaupgrade/options.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package csaupgrade
|
||||||
|
|
||||||
|
type Option func(*options)
|
||||||
|
|
||||||
|
// Subresource set the subresource to upgrade from CSA to SSA.
|
||||||
|
func Subresource(s string) Option {
|
||||||
|
return func(opts *options) {
|
||||||
|
opts.subresource = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type options struct {
|
||||||
|
subresource string
|
||||||
|
}
|
@@ -82,7 +82,13 @@ func UpgradeManagedFields(
|
|||||||
obj runtime.Object,
|
obj runtime.Object,
|
||||||
csaManagerNames sets.Set[string],
|
csaManagerNames sets.Set[string],
|
||||||
ssaManagerName string,
|
ssaManagerName string,
|
||||||
|
opts ...Option,
|
||||||
) error {
|
) error {
|
||||||
|
o := options{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&o)
|
||||||
|
}
|
||||||
|
|
||||||
accessor, err := meta.Accessor(obj)
|
accessor, err := meta.Accessor(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -92,7 +98,7 @@ func UpgradeManagedFields(
|
|||||||
|
|
||||||
for csaManagerName := range csaManagerNames {
|
for csaManagerName := range csaManagerNames {
|
||||||
filteredManagers, err = upgradedManagedFields(
|
filteredManagers, err = upgradedManagedFields(
|
||||||
filteredManagers, csaManagerName, ssaManagerName)
|
filteredManagers, csaManagerName, ssaManagerName, o)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -116,7 +122,14 @@ func UpgradeManagedFields(
|
|||||||
func UpgradeManagedFieldsPatch(
|
func UpgradeManagedFieldsPatch(
|
||||||
obj runtime.Object,
|
obj runtime.Object,
|
||||||
csaManagerNames sets.Set[string],
|
csaManagerNames sets.Set[string],
|
||||||
ssaManagerName string) ([]byte, error) {
|
ssaManagerName string,
|
||||||
|
opts ...Option,
|
||||||
|
) ([]byte, error) {
|
||||||
|
o := options{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&o)
|
||||||
|
}
|
||||||
|
|
||||||
accessor, err := meta.Accessor(obj)
|
accessor, err := meta.Accessor(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -126,7 +139,7 @@ func UpgradeManagedFieldsPatch(
|
|||||||
filteredManagers := accessor.GetManagedFields()
|
filteredManagers := accessor.GetManagedFields()
|
||||||
for csaManagerName := range csaManagerNames {
|
for csaManagerName := range csaManagerNames {
|
||||||
filteredManagers, err = upgradedManagedFields(
|
filteredManagers, err = upgradedManagedFields(
|
||||||
filteredManagers, csaManagerName, ssaManagerName)
|
filteredManagers, csaManagerName, ssaManagerName, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -166,6 +179,7 @@ func upgradedManagedFields(
|
|||||||
managedFields []metav1.ManagedFieldsEntry,
|
managedFields []metav1.ManagedFieldsEntry,
|
||||||
csaManagerName string,
|
csaManagerName string,
|
||||||
ssaManagerName string,
|
ssaManagerName string,
|
||||||
|
opts options,
|
||||||
) ([]metav1.ManagedFieldsEntry, error) {
|
) ([]metav1.ManagedFieldsEntry, error) {
|
||||||
if managedFields == nil {
|
if managedFields == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -183,7 +197,7 @@ func upgradedManagedFields(
|
|||||||
func(entry metav1.ManagedFieldsEntry) bool {
|
func(entry metav1.ManagedFieldsEntry) bool {
|
||||||
return entry.Manager == ssaManagerName &&
|
return entry.Manager == ssaManagerName &&
|
||||||
entry.Operation == metav1.ManagedFieldsOperationApply &&
|
entry.Operation == metav1.ManagedFieldsOperationApply &&
|
||||||
entry.Subresource == ""
|
entry.Subresource == opts.subresource
|
||||||
})
|
})
|
||||||
|
|
||||||
if !managerExists {
|
if !managerExists {
|
||||||
@@ -196,7 +210,7 @@ func upgradedManagedFields(
|
|||||||
func(entry metav1.ManagedFieldsEntry) bool {
|
func(entry metav1.ManagedFieldsEntry) bool {
|
||||||
return entry.Manager == csaManagerName &&
|
return entry.Manager == csaManagerName &&
|
||||||
entry.Operation == metav1.ManagedFieldsOperationUpdate &&
|
entry.Operation == metav1.ManagedFieldsOperationUpdate &&
|
||||||
entry.Subresource == ""
|
entry.Subresource == opts.subresource
|
||||||
})
|
})
|
||||||
|
|
||||||
if !managerExists {
|
if !managerExists {
|
||||||
@@ -209,7 +223,7 @@ func upgradedManagedFields(
|
|||||||
managedFields[replaceIndex].Operation = metav1.ManagedFieldsOperationApply
|
managedFields[replaceIndex].Operation = metav1.ManagedFieldsOperationApply
|
||||||
managedFields[replaceIndex].Manager = ssaManagerName
|
managedFields[replaceIndex].Manager = ssaManagerName
|
||||||
}
|
}
|
||||||
err := unionManagerIntoIndex(managedFields, replaceIndex, csaManagerName)
|
err := unionManagerIntoIndex(managedFields, replaceIndex, csaManagerName, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -218,7 +232,7 @@ func upgradedManagedFields(
|
|||||||
filteredManagers := filter(managedFields, func(entry metav1.ManagedFieldsEntry) bool {
|
filteredManagers := filter(managedFields, func(entry metav1.ManagedFieldsEntry) bool {
|
||||||
return !(entry.Manager == csaManagerName &&
|
return !(entry.Manager == csaManagerName &&
|
||||||
entry.Operation == metav1.ManagedFieldsOperationUpdate &&
|
entry.Operation == metav1.ManagedFieldsOperationUpdate &&
|
||||||
entry.Subresource == "")
|
entry.Subresource == opts.subresource)
|
||||||
})
|
})
|
||||||
|
|
||||||
return filteredManagers, nil
|
return filteredManagers, nil
|
||||||
@@ -231,6 +245,7 @@ func unionManagerIntoIndex(
|
|||||||
entries []metav1.ManagedFieldsEntry,
|
entries []metav1.ManagedFieldsEntry,
|
||||||
targetIndex int,
|
targetIndex int,
|
||||||
csaManagerName string,
|
csaManagerName string,
|
||||||
|
opts options,
|
||||||
) error {
|
) error {
|
||||||
ssaManager := entries[targetIndex]
|
ssaManager := entries[targetIndex]
|
||||||
|
|
||||||
@@ -240,9 +255,7 @@ func unionManagerIntoIndex(
|
|||||||
func(entry metav1.ManagedFieldsEntry) bool {
|
func(entry metav1.ManagedFieldsEntry) bool {
|
||||||
return entry.Manager == csaManagerName &&
|
return entry.Manager == csaManagerName &&
|
||||||
entry.Operation == metav1.ManagedFieldsOperationUpdate &&
|
entry.Operation == metav1.ManagedFieldsOperationUpdate &&
|
||||||
//!TODO: some users may want to migrate subresources.
|
entry.Subresource == opts.subresource &&
|
||||||
// should thread through the args at some point.
|
|
||||||
entry.Subresource == "" &&
|
|
||||||
entry.APIVersion == ssaManager.APIVersion
|
entry.APIVersion == ssaManager.APIVersion
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -294,6 +294,7 @@ func TestUpgradeCSA(t *testing.T) {
|
|||||||
Name string
|
Name string
|
||||||
CSAManagers []string
|
CSAManagers []string
|
||||||
SSAManager string
|
SSAManager string
|
||||||
|
Options []csaupgrade.Option
|
||||||
OriginalObject []byte
|
OriginalObject []byte
|
||||||
ExpectedObject []byte
|
ExpectedObject []byte
|
||||||
}{
|
}{
|
||||||
@@ -1079,6 +1080,163 @@ metadata:
|
|||||||
time: "2022-11-03T23:22:40Z"
|
time: "2022-11-03T23:22:40Z"
|
||||||
name: test
|
name: test
|
||||||
namespace: default
|
namespace: default
|
||||||
|
`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Expect multiple targets to be merged into a new ssa manager
|
||||||
|
Name: "subresource",
|
||||||
|
CSAManagers: []string{"kube-controller-manager"},
|
||||||
|
SSAManager: "kube-controller-manager",
|
||||||
|
Options: []csaupgrade.Option{csaupgrade.Subresource("status")},
|
||||||
|
OriginalObject: []byte(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
pv.kubernetes.io/bind-completed: "yes"
|
||||||
|
pv.kubernetes.io/bound-by-controller: "yes"
|
||||||
|
volume.beta.kubernetes.io/storage-provisioner: openshift-storage.cephfs.csi.ceph.com
|
||||||
|
volume.kubernetes.io/storage-provisioner: openshift-storage.cephfs.csi.ceph.com
|
||||||
|
creationTimestamp: "2024-02-24T15:24:31Z"
|
||||||
|
finalizers:
|
||||||
|
- kubernetes.io/pvc-protection
|
||||||
|
managedFields:
|
||||||
|
- apiVersion: v1
|
||||||
|
fieldsType: FieldsV1
|
||||||
|
fieldsV1:
|
||||||
|
f:spec:
|
||||||
|
f:accessModes: {}
|
||||||
|
f:resources:
|
||||||
|
f:requests:
|
||||||
|
.: {}
|
||||||
|
f:storage: {}
|
||||||
|
f:storageClassName: {}
|
||||||
|
f:volumeMode: {}
|
||||||
|
manager: Mozilla
|
||||||
|
operation: Update
|
||||||
|
time: "2024-02-24T15:24:31Z"
|
||||||
|
- apiVersion: v1
|
||||||
|
fieldsType: FieldsV1
|
||||||
|
fieldsV1:
|
||||||
|
f:metadata:
|
||||||
|
f:annotations:
|
||||||
|
.: {}
|
||||||
|
f:pv.kubernetes.io/bind-completed: {}
|
||||||
|
f:pv.kubernetes.io/bound-by-controller: {}
|
||||||
|
f:volume.beta.kubernetes.io/storage-provisioner: {}
|
||||||
|
f:volume.kubernetes.io/storage-provisioner: {}
|
||||||
|
f:spec:
|
||||||
|
f:volumeName: {}
|
||||||
|
manager: kube-controller-manager
|
||||||
|
operation: Update
|
||||||
|
time: "2024-02-24T15:24:32Z"
|
||||||
|
- apiVersion: v1
|
||||||
|
fieldsType: FieldsV1
|
||||||
|
fieldsV1:
|
||||||
|
f:status:
|
||||||
|
f:accessModes: {}
|
||||||
|
f:capacity:
|
||||||
|
.: {}
|
||||||
|
f:storage: {}
|
||||||
|
f:phase: {}
|
||||||
|
manager: kube-controller-manager
|
||||||
|
operation: Update
|
||||||
|
subresource: status
|
||||||
|
time: "2024-02-24T15:24:32Z"
|
||||||
|
name: test
|
||||||
|
namespace: default
|
||||||
|
resourceVersion: "948647140"
|
||||||
|
uid: f0692a61-0ffe-4fd5-b00f-0b95f3654fb9
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: ocs-storagecluster-cephfs
|
||||||
|
volumeMode: Filesystem
|
||||||
|
volumeName: pvc-f0692a61-0ffe-4fd5-b00f-0b95f3654fb9
|
||||||
|
status:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
capacity:
|
||||||
|
storage: 1Gi
|
||||||
|
phase: Bound
|
||||||
|
`),
|
||||||
|
ExpectedObject: []byte(`
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
pv.kubernetes.io/bind-completed: "yes"
|
||||||
|
pv.kubernetes.io/bound-by-controller: "yes"
|
||||||
|
volume.beta.kubernetes.io/storage-provisioner: openshift-storage.cephfs.csi.ceph.com
|
||||||
|
volume.kubernetes.io/storage-provisioner: openshift-storage.cephfs.csi.ceph.com
|
||||||
|
creationTimestamp: "2024-02-24T15:24:31Z"
|
||||||
|
finalizers:
|
||||||
|
- kubernetes.io/pvc-protection
|
||||||
|
managedFields:
|
||||||
|
- apiVersion: v1
|
||||||
|
fieldsType: FieldsV1
|
||||||
|
fieldsV1:
|
||||||
|
f:spec:
|
||||||
|
f:accessModes: {}
|
||||||
|
f:resources:
|
||||||
|
f:requests:
|
||||||
|
.: {}
|
||||||
|
f:storage: {}
|
||||||
|
f:storageClassName: {}
|
||||||
|
f:volumeMode: {}
|
||||||
|
manager: Mozilla
|
||||||
|
operation: Update
|
||||||
|
time: "2024-02-24T15:24:31Z"
|
||||||
|
- apiVersion: v1
|
||||||
|
fieldsType: FieldsV1
|
||||||
|
fieldsV1:
|
||||||
|
f:metadata:
|
||||||
|
f:annotations:
|
||||||
|
.: {}
|
||||||
|
f:pv.kubernetes.io/bind-completed: {}
|
||||||
|
f:pv.kubernetes.io/bound-by-controller: {}
|
||||||
|
f:volume.beta.kubernetes.io/storage-provisioner: {}
|
||||||
|
f:volume.kubernetes.io/storage-provisioner: {}
|
||||||
|
f:spec:
|
||||||
|
f:volumeName: {}
|
||||||
|
manager: kube-controller-manager
|
||||||
|
operation: Update
|
||||||
|
time: "2024-02-24T15:24:32Z"
|
||||||
|
- apiVersion: v1
|
||||||
|
fieldsType: FieldsV1
|
||||||
|
fieldsV1:
|
||||||
|
f:status:
|
||||||
|
f:accessModes: {}
|
||||||
|
f:capacity:
|
||||||
|
.: {}
|
||||||
|
f:storage: {}
|
||||||
|
f:phase: {}
|
||||||
|
manager: kube-controller-manager
|
||||||
|
operation: Apply
|
||||||
|
subresource: status
|
||||||
|
time: "2024-02-24T15:24:32Z"
|
||||||
|
name: test
|
||||||
|
namespace: default
|
||||||
|
resourceVersion: "948647140"
|
||||||
|
uid: f0692a61-0ffe-4fd5-b00f-0b95f3654fb9
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: ocs-storagecluster-cephfs
|
||||||
|
volumeMode: Filesystem
|
||||||
|
volumeName: pvc-f0692a61-0ffe-4fd5-b00f-0b95f3654fb9
|
||||||
|
status:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
capacity:
|
||||||
|
storage: 1Gi
|
||||||
|
phase: Bound
|
||||||
`),
|
`),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1096,6 +1254,7 @@ metadata:
|
|||||||
upgraded,
|
upgraded,
|
||||||
sets.New(testCase.CSAManagers...),
|
sets.New(testCase.CSAManagers...),
|
||||||
testCase.SSAManager,
|
testCase.SSAManager,
|
||||||
|
testCase.Options...,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1118,7 +1277,7 @@ metadata:
|
|||||||
|
|
||||||
initialCopy := initialObject.DeepCopyObject()
|
initialCopy := initialObject.DeepCopyObject()
|
||||||
patchBytes, err := csaupgrade.UpgradeManagedFieldsPatch(
|
patchBytes, err := csaupgrade.UpgradeManagedFieldsPatch(
|
||||||
initialCopy, sets.New(testCase.CSAManagers...), testCase.SSAManager)
|
initialCopy, sets.New(testCase.CSAManagers...), testCase.SSAManager, testCase.Options...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
Reference in New Issue
Block a user