mirror of https://github.com/k3s-io/k3s
Ingress registry
parent
20a8caa369
commit
16921f961a
|
@ -371,3 +371,31 @@ func ValidateJobStatusUpdate(oldStatus, status experimental.JobStatus) errs.Vali
|
||||||
allErrs = append(allErrs, ValidateJobStatus(&status)...)
|
allErrs = append(allErrs, ValidateJobStatus(&status)...)
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateIngressName validates that the given name can be used as an Ingress name.
|
||||||
|
func ValidateIngressName(name string, prefix bool) (bool, string) {
|
||||||
|
return apivalidation.NameIsDNSSubdomain(name, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateIngressSpec tests if required fields in the IngressSpec are set.
|
||||||
|
func ValidateIngressSpec(spec *experimental.IngressSpec) errs.ValidationErrorList {
|
||||||
|
allErrs := errs.ValidationErrorList{}
|
||||||
|
// TODO: Validate IngressHosts/Rules etc.
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateIngress tests if required fields in the Ingress are set.
|
||||||
|
func ValidateIngress(ingress *experimental.Ingress) errs.ValidationErrorList {
|
||||||
|
allErrs := errs.ValidationErrorList{}
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName).Prefix("metadata")...)
|
||||||
|
allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec).Prefix("spec")...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateIngressUpdate tests if required fields in the Ingress are set.
|
||||||
|
func ValidateIngressUpdate(oldController, ingress *experimental.Ingress) errs.ValidationErrorList {
|
||||||
|
allErrs := errs.ValidationErrorList{}
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldController.ObjectMeta).Prefix("metadata")...)
|
||||||
|
allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec).Prefix("spec")...)
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ import (
|
||||||
endpointsetcd "k8s.io/kubernetes/pkg/registry/endpoint/etcd"
|
endpointsetcd "k8s.io/kubernetes/pkg/registry/endpoint/etcd"
|
||||||
eventetcd "k8s.io/kubernetes/pkg/registry/event/etcd"
|
eventetcd "k8s.io/kubernetes/pkg/registry/event/etcd"
|
||||||
expcontrolleretcd "k8s.io/kubernetes/pkg/registry/experimental/controller/etcd"
|
expcontrolleretcd "k8s.io/kubernetes/pkg/registry/experimental/controller/etcd"
|
||||||
|
ingressetcd "k8s.io/kubernetes/pkg/registry/ingress/etcd"
|
||||||
jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd"
|
jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd"
|
||||||
limitrangeetcd "k8s.io/kubernetes/pkg/registry/limitrange/etcd"
|
limitrangeetcd "k8s.io/kubernetes/pkg/registry/limitrange/etcd"
|
||||||
"k8s.io/kubernetes/pkg/registry/namespace"
|
"k8s.io/kubernetes/pkg/registry/namespace"
|
||||||
|
@ -961,6 +962,7 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
|
||||||
daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(c.ExpDatabaseStorage)
|
daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(c.ExpDatabaseStorage)
|
||||||
deploymentStorage := deploymentetcd.NewStorage(c.ExpDatabaseStorage)
|
deploymentStorage := deploymentetcd.NewStorage(c.ExpDatabaseStorage)
|
||||||
jobStorage, jobStatusStorage := jobetcd.NewREST(c.ExpDatabaseStorage)
|
jobStorage, jobStatusStorage := jobetcd.NewREST(c.ExpDatabaseStorage)
|
||||||
|
ingressStorage := ingressetcd.NewREST(c.ExpDatabaseStorage)
|
||||||
|
|
||||||
thirdPartyControl := ThirdPartyController{
|
thirdPartyControl := ThirdPartyController{
|
||||||
master: m,
|
master: m,
|
||||||
|
@ -984,6 +986,7 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
|
||||||
strings.ToLower("deployments/scale"): deploymentStorage.Scale,
|
strings.ToLower("deployments/scale"): deploymentStorage.Scale,
|
||||||
strings.ToLower("jobs"): jobStorage,
|
strings.ToLower("jobs"): jobStorage,
|
||||||
strings.ToLower("jobs/status"): jobStatusStorage,
|
strings.ToLower("jobs/status"): jobStatusStorage,
|
||||||
|
strings.ToLower("ingress"): ingressStorage,
|
||||||
}
|
}
|
||||||
|
|
||||||
expMeta := latest.GroupOrDie("experimental")
|
expMeta := latest.GroupOrDie("experimental")
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015 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 ingress
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015 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 etcd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/experimental"
|
||||||
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
|
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
|
||||||
|
ingress "k8s.io/kubernetes/pkg/registry/ingress"
|
||||||
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
"k8s.io/kubernetes/pkg/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
IngressPath string = "/ingress"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rest implements a RESTStorage for replication controllers against etcd
|
||||||
|
type REST struct {
|
||||||
|
*etcdgeneric.Etcd
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewREST returns a RESTStorage object that will work against replication controllers.
|
||||||
|
func NewREST(s storage.Interface) *REST {
|
||||||
|
store := &etcdgeneric.Etcd{
|
||||||
|
NewFunc: func() runtime.Object { return &experimental.Ingress{} },
|
||||||
|
|
||||||
|
// NewListFunc returns an object capable of storing results of an etcd list.
|
||||||
|
NewListFunc: func() runtime.Object { return &experimental.IngressList{} },
|
||||||
|
// Produces a ingress that etcd understands, to the root of the resource
|
||||||
|
// by combining the namespace in the context with the given prefix
|
||||||
|
KeyRootFunc: func(ctx api.Context) string {
|
||||||
|
return etcdgeneric.NamespaceKeyRootFunc(ctx, IngressPath)
|
||||||
|
},
|
||||||
|
// Produces a ingress that etcd understands, to the resource by combining
|
||||||
|
// the namespace in the context with the given prefix
|
||||||
|
KeyFunc: func(ctx api.Context, name string) (string, error) {
|
||||||
|
return etcdgeneric.NamespaceKeyFunc(ctx, IngressPath, name)
|
||||||
|
},
|
||||||
|
// Retrieve the name field of a replication controller
|
||||||
|
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||||
|
return obj.(*experimental.Ingress).Name, nil
|
||||||
|
},
|
||||||
|
// Used to match objects based on labels/fields for list and watch
|
||||||
|
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||||
|
return ingress.MatchIngress(label, field)
|
||||||
|
},
|
||||||
|
EndpointName: "ingress",
|
||||||
|
|
||||||
|
// Used to validate controller creation
|
||||||
|
CreateStrategy: ingress.Strategy,
|
||||||
|
|
||||||
|
// Used to validate controller updates
|
||||||
|
UpdateStrategy: ingress.Strategy,
|
||||||
|
|
||||||
|
Storage: s,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &REST{store}
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015 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 etcd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/experimental"
|
||||||
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
|
"k8s.io/kubernetes/pkg/registry/registrytest"
|
||||||
|
"k8s.io/kubernetes/pkg/runtime"
|
||||||
|
"k8s.io/kubernetes/pkg/tools"
|
||||||
|
"k8s.io/kubernetes/pkg/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newStorage(t *testing.T) (*REST, *tools.FakeEtcdClient) {
|
||||||
|
etcdStorage, fakeClient := registrytest.NewEtcdStorage(t, "experimental")
|
||||||
|
ingressStorage := NewREST(etcdStorage)
|
||||||
|
return ingressStorage, fakeClient
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
namespace = "foo-namespace"
|
||||||
|
name = "foo-ingress"
|
||||||
|
defaultHostname = "foo.bar.com"
|
||||||
|
defaultBackendName = "default-backend"
|
||||||
|
defaultBackendPort = util.IntOrString{Kind: util.IntstrInt, IntVal: 80}
|
||||||
|
defaultLoadBalancer = "127.0.0.1"
|
||||||
|
defaultPath = "/foo"
|
||||||
|
defaultPathMap = map[string]string{defaultPath: defaultBackendName}
|
||||||
|
)
|
||||||
|
|
||||||
|
type IngressRuleValues map[string]string
|
||||||
|
|
||||||
|
func toHTTPIngressPaths(pathMap map[string]string) []experimental.HTTPIngressPath {
|
||||||
|
httpPaths := []experimental.HTTPIngressPath{}
|
||||||
|
for path, backend := range pathMap {
|
||||||
|
httpPaths = append(httpPaths, experimental.HTTPIngressPath{
|
||||||
|
Path: path,
|
||||||
|
Backend: experimental.IngressBackend{
|
||||||
|
ServiceName: backend,
|
||||||
|
ServicePort: defaultBackendPort,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return httpPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
func toIngressRules(hostRules map[string]IngressRuleValues) []experimental.IngressRule {
|
||||||
|
rules := []experimental.IngressRule{}
|
||||||
|
for host, pathMap := range hostRules {
|
||||||
|
rules = append(rules, experimental.IngressRule{
|
||||||
|
Host: host,
|
||||||
|
IngressRuleValue: experimental.IngressRuleValue{
|
||||||
|
HTTP: &experimental.HTTPIngressRuleValue{
|
||||||
|
Paths: toHTTPIngressPaths(pathMap),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func newIngress(pathMap map[string]string) *experimental.Ingress {
|
||||||
|
return &experimental.Ingress{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
Spec: experimental.IngressSpec{
|
||||||
|
Backend: &experimental.IngressBackend{
|
||||||
|
ServiceName: defaultBackendName,
|
||||||
|
ServicePort: defaultBackendPort,
|
||||||
|
},
|
||||||
|
Rules: toIngressRules(map[string]IngressRuleValues{
|
||||||
|
defaultHostname: pathMap,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Status: experimental.IngressStatus{
|
||||||
|
LoadBalancer: api.LoadBalancerStatus{
|
||||||
|
Ingress: []api.LoadBalancerIngress{
|
||||||
|
{IP: defaultLoadBalancer},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validNewIngress() *experimental.Ingress {
|
||||||
|
return newIngress(defaultPathMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
var validIngress = *validNewIngress()
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
storage, fakeClient := newStorage(t)
|
||||||
|
test := registrytest.New(t, fakeClient, storage.Etcd)
|
||||||
|
ingress := validNewIngress()
|
||||||
|
noDefaultBackendAndRules := validNewIngress()
|
||||||
|
noDefaultBackendAndRules.Spec.Backend = &experimental.IngressBackend{}
|
||||||
|
noDefaultBackendAndRules.Spec.Rules = []experimental.IngressRule{}
|
||||||
|
badPath := validIngress()
|
||||||
|
badPath.Spec.Rules = toIngressRules(map[string]IngressRuleValues{
|
||||||
|
"foo.bar.com": {"/invalid[": "svc"}})
|
||||||
|
test.TestCreate(
|
||||||
|
// valid
|
||||||
|
ingress,
|
||||||
|
// TODO: Add invalid Ingress tests once we have validation.
|
||||||
|
noDefaultBackendAndRules,
|
||||||
|
noIngressHosts,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdate(t *testing.T) {
|
||||||
|
storage, fakeClient := newStorage(t)
|
||||||
|
test := registrytest.New(t, fakeClient, storage.Etcd)
|
||||||
|
test.TestUpdate(
|
||||||
|
// valid
|
||||||
|
validNewIngress(),
|
||||||
|
// updateFunc
|
||||||
|
func(obj runtime.Object) runtime.Object {
|
||||||
|
object := obj.(*experimental.Ingress)
|
||||||
|
object.Spec.Rules = toIngressRules(map[string]IngressRuleValues{
|
||||||
|
"bar.foo.com": {"/bar": defaultBackendName},
|
||||||
|
})
|
||||||
|
return object
|
||||||
|
},
|
||||||
|
// invalid updateFunc: ObjeceMeta is not to be tampered with.
|
||||||
|
func(obj runtime.Object) runtime.Object {
|
||||||
|
object := obj.(*experimental.Ingress)
|
||||||
|
object.UID = "newUID"
|
||||||
|
return object
|
||||||
|
},
|
||||||
|
|
||||||
|
func(obj runtime.Object) runtime.Object {
|
||||||
|
object := obj.(*experimental.Ingress)
|
||||||
|
object.Name = ""
|
||||||
|
return object
|
||||||
|
},
|
||||||
|
|
||||||
|
func(obj runtime.Object) runtime.Object {
|
||||||
|
object := obj.(*experimental.Ingress)
|
||||||
|
object.Spec.Rules = toIngressRules(map[string]IngressRuleValues{
|
||||||
|
"foo.bar.com": {"/invalid[": "svc"}})
|
||||||
|
return object
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
storage, fakeClient := newStorage(t)
|
||||||
|
test := registrytest.New(t, fakeClient, storage.Etcd)
|
||||||
|
test.TestDelete(validNewIngress())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
storage, fakeClient := newStorage(t)
|
||||||
|
test := registrytest.New(t, fakeClient, storage.Etcd)
|
||||||
|
test.TestGet(validNewIngress())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestList(t *testing.T) {
|
||||||
|
storage, fakeClient := newStorage(t)
|
||||||
|
test := registrytest.New(t, fakeClient, storage.Etcd)
|
||||||
|
test.TestList(validNewIngress())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWatch(t *testing.T) {
|
||||||
|
storage, fakeClient := newStorage(t)
|
||||||
|
test := registrytest.New(t, fakeClient, storage.Etcd)
|
||||||
|
test.TestWatch(
|
||||||
|
validNewIngress(),
|
||||||
|
// matching labels
|
||||||
|
[]labels.Set{},
|
||||||
|
// not matching labels
|
||||||
|
[]labels.Set{
|
||||||
|
{"a": "c"},
|
||||||
|
{"foo": "bar"},
|
||||||
|
},
|
||||||
|
// matching fields
|
||||||
|
[]fields.Set{
|
||||||
|
{"metadata.name": name},
|
||||||
|
},
|
||||||
|
// not matching fields
|
||||||
|
[]fields.Set{
|
||||||
|
{"metadata.name": "bar"},
|
||||||
|
{"name": name},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
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 ingress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/experimental"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/experimental/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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ingressStrategy implements verification logic for Replication Ingresss.
|
||||||
|
type ingressStrategy struct {
|
||||||
|
runtime.ObjectTyper
|
||||||
|
api.NameGenerator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategy is the default logic that applies when creating and updating Replication Ingress objects.
|
||||||
|
var Strategy = ingressStrategy{api.Scheme, api.SimpleNameGenerator}
|
||||||
|
|
||||||
|
// NamespaceScoped returns true because all Ingress' need to be within a namespace.
|
||||||
|
func (ingressStrategy) NamespaceScoped() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ingressStrategy) PrepareForCreate(obj runtime.Object) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ingressStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
|
newIngress := obj.(*experimental.Ingress)
|
||||||
|
oldIngress := old.(*experimental.Ingress)
|
||||||
|
|
||||||
|
// Any changes to the spec increment the generation number, any changes to the
|
||||||
|
// status should reflect the generation number of the corresponding object.
|
||||||
|
// See api.ObjectMeta description for more information on Generation.
|
||||||
|
if !reflect.DeepEqual(oldIngress.Spec, newIngress.Spec) {
|
||||||
|
newIngress.Generation = oldIngress.Generation + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ingressStrategy) Validate(ctx api.Context, obj runtime.Object) fielderrors.ValidationErrorList {
|
||||||
|
ingress := obj.(*experimental.Ingress)
|
||||||
|
err := validation.ValidateIngress(ingress)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ingressStrategy) AllowCreateOnUpdate() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateUpdate is the default update validation for an end user.
|
||||||
|
func (ingressStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) fielderrors.ValidationErrorList {
|
||||||
|
validationErrorList := validation.ValidateIngress(obj.(*experimental.Ingress))
|
||||||
|
updateErrorList := validation.ValidateIngressUpdate(old.(*experimental.Ingress), obj.(*experimental.Ingress))
|
||||||
|
return append(validationErrorList, updateErrorList...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ingressStrategy) AllowUnconditionalUpdate() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressToSelectableFields returns a label set that represents the object.
|
||||||
|
func IngressToSelectableFields(ingress *experimental.Ingress) fields.Set {
|
||||||
|
return fields.Set{
|
||||||
|
"metadata.name": ingress.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchIngress is the filter used by the generic etcd backend to ingress
|
||||||
|
// watch events from etcd to clients of the apiserver only interested in specific
|
||||||
|
// labels/fields.
|
||||||
|
func MatchIngress(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) {
|
||||||
|
ingress, ok := obj.(*experimental.Ingress)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("Given object is not an Ingress.")
|
||||||
|
}
|
||||||
|
return labels.Set(ingress.ObjectMeta.Labels), IngressToSelectableFields(ingress), nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue