mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
build: move e2e dependencies into e2e/go.mod
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
committed by
mergify[bot]
parent
15da101b1b
commit
bec6090996
5
e2e/vendor/k8s.io/apiserver/pkg/storageversion/OWNERS
generated
vendored
Normal file
5
e2e/vendor/k8s.io/apiserver/pkg/storageversion/OWNERS
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- caesarxuchao
|
||||
- roycaihw
|
301
e2e/vendor/k8s.io/apiserver/pkg/storageversion/manager.go
generated
vendored
Normal file
301
e2e/vendor/k8s.io/apiserver/pkg/storageversion/manager.go
generated
vendored
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
Copyright 2020 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 storageversion
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
_ "k8s.io/component-base/metrics/prometheus/workqueue" // for workqueue metric registration
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// ResourceInfo contains the information to register the resource to the
|
||||
// storage version API.
|
||||
type ResourceInfo struct {
|
||||
GroupResource schema.GroupResource
|
||||
|
||||
EncodingVersion string
|
||||
// Used to calculate decodable versions. Can only be used after all
|
||||
// equivalent versions are registered by InstallREST.
|
||||
EquivalentResourceMapper runtime.EquivalentResourceRegistry
|
||||
|
||||
// DirectlyDecodableVersions is a list of versions that the converter for REST storage knows how to convert. This
|
||||
// contains items like apiextensions.k8s.io/v1beta1 even if we don't serve that version.
|
||||
DirectlyDecodableVersions []schema.GroupVersion
|
||||
|
||||
// ServedVersions holds a list of all versions of GroupResource that are served. Note that a server may be able to
|
||||
// decode a particular version, but still not serve it.
|
||||
ServedVersions []string
|
||||
}
|
||||
|
||||
// Manager records the resources whose StorageVersions need updates, and provides a method to update those StorageVersions.
|
||||
type Manager interface {
|
||||
// AddResourceInfo records resources whose StorageVersions need updates
|
||||
AddResourceInfo(resources ...*ResourceInfo)
|
||||
// UpdateStorageVersions tries to update the StorageVersions of the recorded resources
|
||||
UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, apiserverID string)
|
||||
// PendingUpdate returns true if the StorageVersion of the given resource is still pending update.
|
||||
PendingUpdate(gr schema.GroupResource) bool
|
||||
// LastUpdateError returns the last error hit when updating the storage version of the given resource.
|
||||
LastUpdateError(gr schema.GroupResource) error
|
||||
// Completed returns true if updating StorageVersions of all recorded resources has completed.
|
||||
Completed() bool
|
||||
}
|
||||
|
||||
var _ Manager = &defaultManager{}
|
||||
|
||||
// defaultManager indicates if an apiserver has completed reporting its storage versions.
|
||||
type defaultManager struct {
|
||||
completed atomic.Bool
|
||||
|
||||
mu sync.RWMutex
|
||||
// managedResourceInfos records the ResourceInfos whose StorageVersions will get updated in the next
|
||||
// UpdateStorageVersions call
|
||||
managedResourceInfos map[*ResourceInfo]struct{}
|
||||
// managedStatus records the update status of StorageVersion for each GroupResource. Since one
|
||||
// ResourceInfo may expand into multiple GroupResource (e.g. ingresses.networking.k8s.io and ingresses.extensions),
|
||||
// this map allows quick status lookup for a GroupResource, during API request handling.
|
||||
managedStatus map[schema.GroupResource]*updateStatus
|
||||
}
|
||||
|
||||
type updateStatus struct {
|
||||
done bool
|
||||
lastErr error
|
||||
}
|
||||
|
||||
// NewDefaultManager creates a new defaultManager.
|
||||
func NewDefaultManager() Manager {
|
||||
s := &defaultManager{}
|
||||
s.completed.Store(false)
|
||||
s.managedResourceInfos = make(map[*ResourceInfo]struct{})
|
||||
s.managedStatus = make(map[schema.GroupResource]*updateStatus)
|
||||
return s
|
||||
}
|
||||
|
||||
// AddResourceInfo adds ResourceInfo to the manager.
|
||||
func (s *defaultManager) AddResourceInfo(resources ...*ResourceInfo) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for _, r := range resources {
|
||||
s.managedResourceInfos[r] = struct{}{}
|
||||
s.addPendingManagedStatusLocked(r)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *defaultManager) addPendingManagedStatusLocked(r *ResourceInfo) {
|
||||
gvrs := r.EquivalentResourceMapper.EquivalentResourcesFor(r.GroupResource.WithVersion(""), "")
|
||||
for _, gvr := range gvrs {
|
||||
gr := gvr.GroupResource()
|
||||
if _, ok := s.managedStatus[gr]; !ok {
|
||||
s.managedStatus[gr] = &updateStatus{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateStorageVersions tries to update the StorageVersions of the recorded resources
|
||||
func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, serverID string) {
|
||||
clientset, err := kubernetes.NewForConfig(kubeAPIServerClientConfig)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("failed to get clientset: %v", err))
|
||||
return
|
||||
}
|
||||
sc := clientset.InternalV1alpha1().StorageVersions()
|
||||
|
||||
s.mu.RLock()
|
||||
resources := []ResourceInfo{}
|
||||
for resource := range s.managedResourceInfos {
|
||||
resources = append(resources, *resource)
|
||||
}
|
||||
s.mu.RUnlock()
|
||||
hasFailure := false
|
||||
// Sorting the list to make sure we have a consistent dedup result, and
|
||||
// therefore avoid creating unnecessarily duplicated StorageVersion objects.
|
||||
// For example, extensions.ingresses and networking.k8s.io.ingresses share
|
||||
// the same underlying storage. Without sorting, in an HA cluster, one
|
||||
// apiserver may dedup and update StorageVersion for extensions.ingresses,
|
||||
// while another apiserver may dedup and update StorageVersion for
|
||||
// networking.k8s.io.ingresses. The storage migrator (which migrates objects
|
||||
// per GroupResource) will migrate these resources twice, since both
|
||||
// StorageVersion objects have CommonEncodingVersion (each with one server registered).
|
||||
sortResourceInfosByGroupResource(resources)
|
||||
for _, r := range dedupResourceInfos(resources) {
|
||||
decodableVersions := decodableVersions(r.DirectlyDecodableVersions, r.EquivalentResourceMapper, r.GroupResource)
|
||||
gr := r.GroupResource
|
||||
// Group must be a valid subdomain in DNS (RFC 1123)
|
||||
if len(gr.Group) == 0 {
|
||||
gr.Group = "core"
|
||||
}
|
||||
|
||||
servedVersions := r.ServedVersions
|
||||
|
||||
if err := updateStorageVersionFor(sc, serverID, gr, r.EncodingVersion, decodableVersions, servedVersions); err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("failed to update storage version for %v: %v", r.GroupResource, err))
|
||||
s.recordStatusFailure(&r, err)
|
||||
hasFailure = true
|
||||
continue
|
||||
}
|
||||
klog.V(2).Infof("successfully updated storage version for %v", r.GroupResource)
|
||||
s.recordStatusSuccess(&r)
|
||||
}
|
||||
if hasFailure {
|
||||
return
|
||||
}
|
||||
klog.V(2).Infof("storage version updates complete")
|
||||
s.setComplete()
|
||||
}
|
||||
|
||||
// dedupResourceInfos dedups ResourceInfos with the same underlying storage.
|
||||
// ResourceInfos from the same Group with different Versions share the same underlying storage.
|
||||
// ResourceInfos from different Groups may share the same underlying storage, e.g.
|
||||
// networking.k8s.io ingresses and extensions ingresses. The StorageVersion manager
|
||||
// only needs to update one StorageVersion for the equivalent Groups.
|
||||
func dedupResourceInfos(infos []ResourceInfo) []ResourceInfo {
|
||||
var ret []ResourceInfo
|
||||
seen := make(map[schema.GroupResource]struct{})
|
||||
for _, info := range infos {
|
||||
gr := info.GroupResource
|
||||
if _, ok := seen[gr]; ok {
|
||||
continue
|
||||
}
|
||||
gvrs := info.EquivalentResourceMapper.EquivalentResourcesFor(gr.WithVersion(""), "")
|
||||
for _, gvr := range gvrs {
|
||||
seen[gvr.GroupResource()] = struct{}{}
|
||||
}
|
||||
ret = append(ret, info)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func sortResourceInfosByGroupResource(infos []ResourceInfo) {
|
||||
sort.Sort(byGroupResource(infos))
|
||||
}
|
||||
|
||||
type byGroupResource []ResourceInfo
|
||||
|
||||
func (s byGroupResource) Len() int { return len(s) }
|
||||
|
||||
func (s byGroupResource) Less(i, j int) bool {
|
||||
if s[i].GroupResource.Group == s[j].GroupResource.Group {
|
||||
return s[i].GroupResource.Resource < s[j].GroupResource.Resource
|
||||
}
|
||||
return s[i].GroupResource.Group < s[j].GroupResource.Group
|
||||
}
|
||||
|
||||
func (s byGroupResource) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// recordStatusSuccess marks updated ResourceInfo as completed.
|
||||
func (s *defaultManager) recordStatusSuccess(r *ResourceInfo) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.recordStatusSuccessLocked(r)
|
||||
}
|
||||
|
||||
func (s *defaultManager) recordStatusSuccessLocked(r *ResourceInfo) {
|
||||
gvrs := r.EquivalentResourceMapper.EquivalentResourcesFor(r.GroupResource.WithVersion(""), "")
|
||||
for _, gvr := range gvrs {
|
||||
s.recordSuccessGroupResourceLocked(gvr.GroupResource())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *defaultManager) recordSuccessGroupResourceLocked(gr schema.GroupResource) {
|
||||
if _, ok := s.managedStatus[gr]; !ok {
|
||||
return
|
||||
}
|
||||
s.managedStatus[gr].done = true
|
||||
s.managedStatus[gr].lastErr = nil
|
||||
}
|
||||
|
||||
// recordStatusFailure records latest error updating ResourceInfo.
|
||||
func (s *defaultManager) recordStatusFailure(r *ResourceInfo, err error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.recordStatusFailureLocked(r, err)
|
||||
}
|
||||
|
||||
func (s *defaultManager) recordStatusFailureLocked(r *ResourceInfo, err error) {
|
||||
gvrs := r.EquivalentResourceMapper.EquivalentResourcesFor(r.GroupResource.WithVersion(""), "")
|
||||
for _, gvr := range gvrs {
|
||||
s.recordErrorGroupResourceLocked(gvr.GroupResource(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *defaultManager) recordErrorGroupResourceLocked(gr schema.GroupResource, err error) {
|
||||
if _, ok := s.managedStatus[gr]; !ok {
|
||||
return
|
||||
}
|
||||
s.managedStatus[gr].lastErr = err
|
||||
}
|
||||
|
||||
// PendingUpdate returns if the StorageVersion of a resource is still wait to be updated.
|
||||
func (s *defaultManager) PendingUpdate(gr schema.GroupResource) bool {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if _, ok := s.managedStatus[gr]; !ok {
|
||||
return false
|
||||
}
|
||||
return !s.managedStatus[gr].done
|
||||
}
|
||||
|
||||
// LastUpdateError returns the last error hit when updating the storage version of the given resource.
|
||||
func (s *defaultManager) LastUpdateError(gr schema.GroupResource) error {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if _, ok := s.managedStatus[gr]; !ok {
|
||||
return fmt.Errorf("couldn't find managed status for %v", gr)
|
||||
}
|
||||
return s.managedStatus[gr].lastErr
|
||||
}
|
||||
|
||||
// setComplete marks the completion of updating StorageVersions. No write requests need to be blocked anymore.
|
||||
func (s *defaultManager) setComplete() {
|
||||
s.completed.Store(true)
|
||||
}
|
||||
|
||||
// Completed returns if updating StorageVersions has completed.
|
||||
func (s *defaultManager) Completed() bool {
|
||||
return s.completed.Load()
|
||||
}
|
||||
|
||||
func decodableVersions(directlyDecodableVersions []schema.GroupVersion, e runtime.EquivalentResourceRegistry, gr schema.GroupResource) []string {
|
||||
var versions []string
|
||||
for _, decodableVersions := range directlyDecodableVersions {
|
||||
versions = append(versions, decodableVersions.String())
|
||||
}
|
||||
|
||||
decodingGVRs := e.EquivalentResourcesFor(gr.WithVersion(""), "")
|
||||
for _, v := range decodingGVRs {
|
||||
found := false
|
||||
for _, existingVersion := range versions {
|
||||
if existingVersion == v.GroupVersion().String() {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
versions = append(versions, v.GroupVersion().String())
|
||||
}
|
||||
return versions
|
||||
}
|
197
e2e/vendor/k8s.io/apiserver/pkg/storageversion/updater.go
generated
vendored
Normal file
197
e2e/vendor/k8s.io/apiserver/pkg/storageversion/updater.go
generated
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
Copyright 2020 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 storageversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/apiserverinternal/v1alpha1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// Client has the methods required to update the storage version.
|
||||
type Client interface {
|
||||
Create(context.Context, *v1alpha1.StorageVersion, metav1.CreateOptions) (*v1alpha1.StorageVersion, error)
|
||||
UpdateStatus(context.Context, *v1alpha1.StorageVersion, metav1.UpdateOptions) (*v1alpha1.StorageVersion, error)
|
||||
Get(context.Context, string, metav1.GetOptions) (*v1alpha1.StorageVersion, error)
|
||||
}
|
||||
|
||||
// SetCommonEncodingVersion updates the CommonEncodingVersion and the AllEncodingVersionsEqual
|
||||
// condition based on the StorageVersions.
|
||||
func SetCommonEncodingVersion(sv *v1alpha1.StorageVersion) {
|
||||
var oldCommonEncodingVersion *string
|
||||
if sv.Status.CommonEncodingVersion != nil {
|
||||
version := *sv.Status.CommonEncodingVersion
|
||||
oldCommonEncodingVersion = &version
|
||||
}
|
||||
sv.Status.CommonEncodingVersion = nil
|
||||
if len(sv.Status.StorageVersions) != 0 {
|
||||
firstVersion := sv.Status.StorageVersions[0].EncodingVersion
|
||||
agreed := true
|
||||
for _, ssv := range sv.Status.StorageVersions {
|
||||
if ssv.EncodingVersion != firstVersion {
|
||||
agreed = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if agreed {
|
||||
sv.Status.CommonEncodingVersion = &firstVersion
|
||||
}
|
||||
}
|
||||
|
||||
condition := v1alpha1.StorageVersionCondition{
|
||||
Type: v1alpha1.AllEncodingVersionsEqual,
|
||||
Status: v1alpha1.ConditionFalse,
|
||||
ObservedGeneration: sv.Generation,
|
||||
LastTransitionTime: metav1.NewTime(time.Now()),
|
||||
Reason: "CommonEncodingVersionUnset",
|
||||
Message: "Common encoding version unset",
|
||||
}
|
||||
if sv.Status.CommonEncodingVersion != nil {
|
||||
condition.Status = v1alpha1.ConditionTrue
|
||||
condition.Reason = "CommonEncodingVersionSet"
|
||||
condition.Message = "Common encoding version set"
|
||||
}
|
||||
forceTransition := false
|
||||
if oldCommonEncodingVersion != nil && sv.Status.CommonEncodingVersion != nil &&
|
||||
*oldCommonEncodingVersion != *sv.Status.CommonEncodingVersion {
|
||||
forceTransition = true
|
||||
}
|
||||
setStatusCondition(&sv.Status.Conditions, condition, forceTransition)
|
||||
}
|
||||
|
||||
func findStatusCondition(conditions []v1alpha1.StorageVersionCondition,
|
||||
conditionType v1alpha1.StorageVersionConditionType) *v1alpha1.StorageVersionCondition {
|
||||
for i := range conditions {
|
||||
if conditions[i].Type == conditionType {
|
||||
return &conditions[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setStatusCondition sets the corresponding condition in conditions to newCondition.
|
||||
// conditions must be non-nil.
|
||||
// 1. if the condition of the specified type already exists: all fields of the existing condition are updated to
|
||||
// newCondition, LastTransitionTime is set to now if the new status differs from the old status
|
||||
// 2. if a condition of the specified type does not exist: LastTransitionTime is set to now() if unset,
|
||||
// and newCondition is appended
|
||||
//
|
||||
// NOTE: forceTransition allows overwriting LastTransitionTime even when the status doesn't change.
|
||||
func setStatusCondition(conditions *[]v1alpha1.StorageVersionCondition, newCondition v1alpha1.StorageVersionCondition,
|
||||
forceTransition bool) {
|
||||
if conditions == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if newCondition.LastTransitionTime.IsZero() {
|
||||
newCondition.LastTransitionTime = metav1.NewTime(time.Now())
|
||||
}
|
||||
existingCondition := findStatusCondition(*conditions, newCondition.Type)
|
||||
if existingCondition == nil {
|
||||
*conditions = append(*conditions, newCondition)
|
||||
return
|
||||
}
|
||||
|
||||
statusChanged := existingCondition.Status != newCondition.Status
|
||||
if statusChanged || forceTransition {
|
||||
existingCondition.LastTransitionTime = newCondition.LastTransitionTime
|
||||
}
|
||||
existingCondition.Status = newCondition.Status
|
||||
existingCondition.Reason = newCondition.Reason
|
||||
existingCondition.Message = newCondition.Message
|
||||
existingCondition.ObservedGeneration = newCondition.ObservedGeneration
|
||||
}
|
||||
|
||||
// updateStorageVersionFor updates the storage version object for the resource.
|
||||
func updateStorageVersionFor(c Client, apiserverID string, gr schema.GroupResource, encodingVersion string, decodableVersions []string, servedVersions []string) error {
|
||||
retries := 3
|
||||
var retry int
|
||||
var err error
|
||||
for retry < retries {
|
||||
err = singleUpdate(c, apiserverID, gr, encodingVersion, decodableVersions, servedVersions)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if apierrors.IsAlreadyExists(err) || apierrors.IsConflict(err) {
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
klog.Errorf("retry %d, failed to update storage version for %v: %v", retry, gr, err)
|
||||
retry++
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func singleUpdate(c Client, apiserverID string, gr schema.GroupResource, encodingVersion string, decodableVersions []string, servedVersions []string) error {
|
||||
shouldCreate := false
|
||||
name := fmt.Sprintf("%s.%s", gr.Group, gr.Resource)
|
||||
sv, err := c.Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if apierrors.IsNotFound(err) {
|
||||
shouldCreate = true
|
||||
sv = &v1alpha1.StorageVersion{}
|
||||
sv.ObjectMeta.Name = name
|
||||
}
|
||||
updatedSV := localUpdateStorageVersion(sv, apiserverID, encodingVersion, decodableVersions, servedVersions)
|
||||
if shouldCreate {
|
||||
createdSV, err := c.Create(context.TODO(), updatedSV, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// assign the calculated status to the object just created, then update status
|
||||
createdSV.Status = updatedSV.Status
|
||||
_, err = c.UpdateStatus(context.TODO(), createdSV, metav1.UpdateOptions{})
|
||||
return err
|
||||
}
|
||||
_, err = c.UpdateStatus(context.TODO(), updatedSV, metav1.UpdateOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
// localUpdateStorageVersion updates the input storageversion with given server storageversion info.
|
||||
// The function updates the input storageversion in place.
|
||||
func localUpdateStorageVersion(sv *v1alpha1.StorageVersion, apiserverID, encodingVersion string, decodableVersions []string, servedVersions []string) *v1alpha1.StorageVersion {
|
||||
newSSV := v1alpha1.ServerStorageVersion{
|
||||
APIServerID: apiserverID,
|
||||
EncodingVersion: encodingVersion,
|
||||
DecodableVersions: decodableVersions,
|
||||
ServedVersions: servedVersions,
|
||||
}
|
||||
foundSSV := false
|
||||
for i, ssv := range sv.Status.StorageVersions {
|
||||
if ssv.APIServerID == apiserverID {
|
||||
sv.Status.StorageVersions[i] = newSSV
|
||||
foundSSV = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundSSV {
|
||||
sv.Status.StorageVersions = append(sv.Status.StorageVersions, newSSV)
|
||||
}
|
||||
SetCommonEncodingVersion(sv)
|
||||
return sv
|
||||
}
|
Reference in New Issue
Block a user