Skip to content

Commit

Permalink
Add ServiceCIDR to the REST Registry
Browse files Browse the repository at this point in the history
Change-Id: If2ab86505b1ffd94100f575e682702679dd2da72
  • Loading branch information
aojea committed Oct 31, 2023
1 parent 391b251 commit 2feb150
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 0 deletions.
12 changes: 12 additions & 0 deletions pkg/registry/networking/rest/storage_settings.go
Expand Up @@ -29,6 +29,7 @@ import (
ingressclassstore "k8s.io/kubernetes/pkg/registry/networking/ingressclass/storage"
ipaddressstore "k8s.io/kubernetes/pkg/registry/networking/ipaddress/storage"
networkpolicystore "k8s.io/kubernetes/pkg/registry/networking/networkpolicy/storage"
servicecidrstore "k8s.io/kubernetes/pkg/registry/networking/servicecidr/storage"
)

type RESTStorageProvider struct{}
Expand Down Expand Up @@ -98,6 +99,17 @@ func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstora
}
storage[resource] = ipAddressStorage
}

// servicecidrs
if resource := "servicecidrs"; apiResourceConfigSource.ResourceEnabled(networkingapiv1alpha1.SchemeGroupVersion.WithResource(resource)) {
serviceCIDRStorage, serviceCIDRStatusStorage, err := servicecidrstore.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage[resource] = serviceCIDRStorage
storage[resource+"/status"] = serviceCIDRStatusStorage
}

return storage, nil
}

Expand Down
17 changes: 17 additions & 0 deletions pkg/registry/networking/servicecidr/doc.go
@@ -0,0 +1,17 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package servicecidr // import "k8s.io/kubernetes/pkg/registry/networking/servicecidr"
101 changes: 101 additions & 0 deletions pkg/registry/networking/servicecidr/storage/storage.go
@@ -0,0 +1,101 @@
/*
Copyright 2023 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 storage

import (
"context"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/kubernetes/pkg/apis/networking"
"k8s.io/kubernetes/pkg/printers"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
printerstorage "k8s.io/kubernetes/pkg/printers/storage"
"k8s.io/kubernetes/pkg/registry/networking/servicecidr"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
)

// REST implements a RESTStorage for IPRange against etcd
type REST struct {
*genericregistry.Store
}

// NewREST returns a RESTStorage object that will work against service CIDRs.
func NewREST(optsGetter generic.RESTOptionsGetter) (*REST, *StatusREST, error) {
store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &networking.ServiceCIDR{} },
NewListFunc: func() runtime.Object { return &networking.ServiceCIDRList{} },
DefaultQualifiedResource: networking.Resource("servicecidrs"),
SingularQualifiedResource: networking.Resource("servicecidr"),

CreateStrategy: servicecidr.Strategy,
UpdateStrategy: servicecidr.Strategy,
DeleteStrategy: servicecidr.Strategy,
ResetFieldsStrategy: servicecidr.Strategy,

TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(printersinternal.AddHandlers)},
}
options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil {
return nil, nil, err
}

statusStore := *store
statusStore.UpdateStrategy = servicecidr.StatusStrategy
statusStore.ResetFieldsStrategy = servicecidr.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore}, nil
}

// StatusREST implements the REST endpoint for changing the status of an ingress
type StatusREST struct {
store *genericregistry.Store
}

// New creates an instance of the StatusREST object
func (r *StatusREST) New() runtime.Object {
return &networking.ServiceCIDR{}
}

// Destroy cleans up resources on shutdown.
func (r *StatusREST) Destroy() {
// Given that underlying store is shared with REST,
// we don't destroy it here explicitly.
}

// Get retrieves the object from the storage. It is required to support Patch.
func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
return r.store.Get(ctx, name, options)
}

// Update alters the status subset of an object.
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
// subresources should never allow create on update.
return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
}

func (r *StatusREST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
return r.store.ConvertToTable(ctx, object, tableOptions)
}

// GetResetFields implements rest.ResetFieldsStrategy
func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
return r.store.GetResetFields()
}
151 changes: 151 additions & 0 deletions pkg/registry/networking/servicecidr/strategy.go
@@ -0,0 +1,151 @@
/*
Copyright 2023 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 servicecidr

import (
"context"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/networking"
"k8s.io/kubernetes/pkg/apis/networking/validation"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
)

// serviceCIDRStrategy implements verification logic for ServiceCIDR allocators.
type serviceCIDRStrategy struct {
runtime.ObjectTyper
names.NameGenerator
}

// Strategy is the default logic that applies when creating and updating Replication ServiceCIDR objects.
var Strategy = serviceCIDRStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}

// Strategy should implement rest.RESTCreateStrategy
var _ rest.RESTCreateStrategy = Strategy

// Strategy should implement rest.RESTUpdateStrategy
var _ rest.RESTUpdateStrategy = Strategy

// NamespaceScoped returns false because all ServiceCIDRes is cluster scoped.
func (serviceCIDRStrategy) NamespaceScoped() bool {
return false
}

// GetResetFields returns the set of fields that get reset by the strategy
// and should not be modified by the user.
func (serviceCIDRStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
fields := map[fieldpath.APIVersion]*fieldpath.Set{
"networking/v1alpha1": fieldpath.NewSet(
fieldpath.MakePathOrDie("status"),
),
}
return fields
}

// PrepareForCreate clears the status of an ServiceCIDR before creation.
func (serviceCIDRStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
_ = obj.(*networking.ServiceCIDR)

}

// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
func (serviceCIDRStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
newServiceCIDR := obj.(*networking.ServiceCIDR)
oldServiceCIDR := old.(*networking.ServiceCIDR)

_, _ = newServiceCIDR, oldServiceCIDR
}

// Validate validates a new ServiceCIDR.
func (serviceCIDRStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
cidrConfig := obj.(*networking.ServiceCIDR)
err := validation.ValidateServiceCIDR(cidrConfig)
return err
}

// Canonicalize normalizes the object after validation.
func (serviceCIDRStrategy) Canonicalize(obj runtime.Object) {
}

// AllowCreateOnUpdate is false for ServiceCIDR; this means POST is needed to create one.
func (serviceCIDRStrategy) AllowCreateOnUpdate() bool {
return false
}

// WarningsOnCreate returns warnings for the creation of the given object.
func (serviceCIDRStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string {
return nil
}

// ValidateUpdate is the default update validation for an end user.
func (serviceCIDRStrategy) ValidateUpdate(ctx context.Context, new, old runtime.Object) field.ErrorList {
newServiceCIDR := new.(*networking.ServiceCIDR)
oldServiceCIDR := old.(*networking.ServiceCIDR)
errList := validation.ValidateServiceCIDR(newServiceCIDR)
errList = append(errList, validation.ValidateServiceCIDRUpdate(newServiceCIDR, oldServiceCIDR)...)
return errList
}

// AllowUnconditionalUpdate is the default update policy for ServiceCIDR objects.
func (serviceCIDRStrategy) AllowUnconditionalUpdate() bool {
return true
}

// WarningsOnUpdate returns warnings for the given update.
func (serviceCIDRStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
return nil
}

type serviceCIDRStatusStrategy struct {
serviceCIDRStrategy
}

// StatusStrategy implements logic used to validate and prepare for updates of the status subresource
var StatusStrategy = serviceCIDRStatusStrategy{Strategy}

// GetResetFields returns the set of fields that get reset by the strategy
// and should not be modified by the user.
func (serviceCIDRStatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
fields := map[fieldpath.APIVersion]*fieldpath.Set{
"networking/v1alpha1": fieldpath.NewSet(
fieldpath.MakePathOrDie("spec"),
),
}
return fields
}

// PrepareForUpdate clears fields that are not allowed to be set by end users on update of status
func (serviceCIDRStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
newServiceCIDR := obj.(*networking.ServiceCIDR)
oldServiceCIDR := old.(*networking.ServiceCIDR)
// status changes are not allowed to update spec
newServiceCIDR.Spec = oldServiceCIDR.Spec
}

// ValidateUpdate is the default update validation for an end user updating status
func (serviceCIDRStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
return validation.ValidateServiceCIDRStatusUpdate(obj.(*networking.ServiceCIDR), old.(*networking.ServiceCIDR))
}

// WarningsOnUpdate returns warnings for the given update.
func (serviceCIDRStatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
return nil
}
17 changes: 17 additions & 0 deletions pkg/registry/networking/servicecidr/strategy_test.go
@@ -0,0 +1,17 @@
/*
Copyright 2023 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 servicecidr

0 comments on commit 2feb150

Please sign in to comment.