mirror of https://github.com/k3s-io/k3s
Move service strategy to registry/service package
parent
fcbf1c1012
commit
3603b14977
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 rest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
)
|
||||
|
||||
func TestCheckGeneratedNameError(t *testing.T) {
|
||||
expect := errors.NewNotFound("foo", "bar")
|
||||
if err := CheckGeneratedNameError(Services, expect, &api.Pod{}); err != expect {
|
||||
t.Errorf("NotFoundError should be ignored: %v", err)
|
||||
}
|
||||
|
||||
expect = errors.NewAlreadyExists("foo", "bar")
|
||||
if err := CheckGeneratedNameError(Services, expect, &api.Pod{}); err != expect {
|
||||
t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err)
|
||||
}
|
||||
|
||||
expect = errors.NewAlreadyExists("foo", "bar")
|
||||
if err := CheckGeneratedNameError(Services, expect, &api.Pod{ObjectMeta: api.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) {
|
||||
t.Errorf("expected try again later error: %v", err)
|
||||
}
|
||||
}
|
|
@ -17,10 +17,7 @@ limitations under the License.
|
|||
package rest
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/fielderrors"
|
||||
)
|
||||
|
||||
// ObjectFunc is a function to act on a given object. An error may be returned
|
||||
|
@ -43,51 +40,3 @@ func AllFuncs(fns ...ObjectFunc) ObjectFunc {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// svcStrategy implements behavior for Services
|
||||
// TODO: move to a service specific package.
|
||||
type svcStrategy struct {
|
||||
runtime.ObjectTyper
|
||||
api.NameGenerator
|
||||
}
|
||||
|
||||
// Services is the default logic that applies when creating and updating Service
|
||||
// objects.
|
||||
var Services = svcStrategy{api.Scheme, api.SimpleNameGenerator}
|
||||
|
||||
// NamespaceScoped is true for services.
|
||||
func (svcStrategy) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
||||
func (svcStrategy) PrepareForCreate(obj runtime.Object) {
|
||||
service := obj.(*api.Service)
|
||||
service.Status = api.ServiceStatus{}
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (svcStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||
// TODO: once service has a status sub-resource we can enable this.
|
||||
//newService := obj.(*api.Service)
|
||||
//oldService := old.(*api.Service)
|
||||
//newService.Status = oldService.Status
|
||||
}
|
||||
|
||||
// Validate validates a new service.
|
||||
func (svcStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList {
|
||||
service := obj.(*api.Service)
|
||||
return validation.ValidateService(service)
|
||||
}
|
||||
|
||||
func (svcStrategy) AllowCreateOnUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (svcStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
|
||||
return validation.ValidateServiceUpdate(old.(*api.Service), obj.(*api.Service))
|
||||
}
|
||||
|
||||
func (svcStrategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ func (c *Controller) CreateOrUpdateMasterServiceIfNeeded(serviceName string, ser
|
|||
Type: serviceType,
|
||||
},
|
||||
}
|
||||
if err := rest.BeforeCreate(rest.Services, ctx, svc); err != nil {
|
||||
if err := rest.BeforeCreate(service.Strategy, ctx, svc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ type ResourceGetter interface {
|
|||
Get(api.Context, string) (runtime.Object, error)
|
||||
}
|
||||
|
||||
// NodeToSelectableFields returns a label set that represents the object.
|
||||
// NodeToSelectableFields returns a field set that represents the object.
|
||||
func NodeToSelectableFields(node *api.Node) fields.Set {
|
||||
objectMetaFieldsSet := generic.ObjectMetaFieldsSet(node.ObjectMeta, false)
|
||||
specificFieldsSet := fields.Set{
|
||||
|
|
|
@ -17,14 +17,12 @@ limitations under the License.
|
|||
package etcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/rest"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
|
||||
"k8s.io/kubernetes/pkg/registry/service"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/storage"
|
||||
)
|
||||
|
@ -49,29 +47,14 @@ func NewREST(s storage.Interface) *REST {
|
|||
return obj.(*api.Service).Name, nil
|
||||
},
|
||||
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||
return MatchServices(label, field)
|
||||
return service.MatchServices(label, field)
|
||||
},
|
||||
EndpointName: "services",
|
||||
|
||||
CreateStrategy: rest.Services,
|
||||
UpdateStrategy: rest.Services,
|
||||
CreateStrategy: service.Strategy,
|
||||
UpdateStrategy: service.Strategy,
|
||||
|
||||
Storage: s,
|
||||
}
|
||||
return &REST{store}
|
||||
}
|
||||
|
||||
// FIXME: Move it.
|
||||
func MatchServices(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||
return &generic.SelectionPredicate{Label: label, Field: field, GetAttrs: ServiceAttributes}
|
||||
}
|
||||
|
||||
func ServiceAttributes(obj runtime.Object) (objLabels labels.Set, objFields fields.Set, err error) {
|
||||
service, ok := obj.(*api.Service)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("invalid object type %#v", obj)
|
||||
}
|
||||
return service.Labels, fields.Set{
|
||||
"metadata.name": service.Name,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ func NewStorage(registry Registry, endpoints endpoint.Registry, serviceIPs ipall
|
|||
func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) {
|
||||
service := obj.(*api.Service)
|
||||
|
||||
if err := rest.BeforeCreate(rest.Services, ctx, obj); err != nil {
|
||||
if err := rest.BeforeCreate(Strategy, ctx, obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, err
|
|||
|
||||
out, err := rs.registry.CreateService(ctx, service)
|
||||
if err != nil {
|
||||
err = rest.CheckGeneratedNameError(rest.Services, err, service)
|
||||
err = rest.CheckGeneratedNameError(Strategy, err, service)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/fielderrors"
|
||||
)
|
||||
|
||||
// svcStrategy implements behavior for Services
|
||||
type svcStrategy struct {
|
||||
runtime.ObjectTyper
|
||||
api.NameGenerator
|
||||
}
|
||||
|
||||
// Services is the default logic that applies when creating and updating Service
|
||||
// objects.
|
||||
var Strategy = svcStrategy{api.Scheme, api.SimpleNameGenerator}
|
||||
|
||||
// NamespaceScoped is true for services.
|
||||
func (svcStrategy) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
||||
func (svcStrategy) PrepareForCreate(obj runtime.Object) {
|
||||
service := obj.(*api.Service)
|
||||
service.Status = api.ServiceStatus{}
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (svcStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||
// TODO: once service has a status sub-resource we can enable this.
|
||||
//newService := obj.(*api.Service)
|
||||
//oldService := old.(*api.Service)
|
||||
//newService.Status = oldService.Status
|
||||
}
|
||||
|
||||
// Validate validates a new service.
|
||||
func (svcStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList {
|
||||
service := obj.(*api.Service)
|
||||
return validation.ValidateService(service)
|
||||
}
|
||||
|
||||
func (svcStrategy) AllowCreateOnUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (svcStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
|
||||
return validation.ValidateServiceUpdate(old.(*api.Service), obj.(*api.Service))
|
||||
}
|
||||
|
||||
func (svcStrategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func MatchServices(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||
return &generic.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
service, ok := obj.(*api.Service)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("Given object is not a service")
|
||||
}
|
||||
return labels.Set(service.ObjectMeta.Labels), ServiceToSelectableFields(service), nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ServiceToSelectableFields(service *api.Service) fields.Set {
|
||||
return generic.ObjectMetaFieldsSet(service.ObjectMeta, true)
|
||||
}
|
|
@ -14,16 +14,35 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package rest
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api/rest"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
func TestCheckGeneratedNameError(t *testing.T) {
|
||||
expect := errors.NewNotFound("foo", "bar")
|
||||
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
|
||||
t.Errorf("NotFoundError should be ignored: %v", err)
|
||||
}
|
||||
|
||||
expect = errors.NewAlreadyExists("foo", "bar")
|
||||
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{}); err != expect {
|
||||
t.Errorf("AlreadyExists should be returned when no GenerateName field: %v", err)
|
||||
}
|
||||
|
||||
expect = errors.NewAlreadyExists("foo", "bar")
|
||||
if err := rest.CheckGeneratedNameError(Strategy, expect, &api.Pod{ObjectMeta: api.ObjectMeta{GenerateName: "foo"}}); err == nil || !errors.IsServerTimeout(err) {
|
||||
t.Errorf("expected try again later error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func makeValidService() api.Service {
|
||||
return api.Service{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
|
@ -99,7 +118,7 @@ func TestBeforeUpdate(t *testing.T) {
|
|||
newSvc := makeValidService()
|
||||
tc.tweakSvc(&oldSvc, &newSvc)
|
||||
ctx := api.NewDefaultContext()
|
||||
err := BeforeUpdate(Services, ctx, runtime.Object(&oldSvc), runtime.Object(&newSvc))
|
||||
err := rest.BeforeUpdate(Strategy, ctx, runtime.Object(&oldSvc), runtime.Object(&newSvc))
|
||||
if tc.expectErr && err == nil {
|
||||
t.Errorf("unexpected non-error for %q", tc.name)
|
||||
}
|
Loading…
Reference in New Issue