Merge pull request #88587 from cmluciano/cml/v1beta1paths

Adding PathType to Ingress
This commit is contained in:
Kubernetes Prow Robot 2020-03-03 18:13:47 -08:00 committed by GitHub
commit aeb88b6ecd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1384 additions and 508 deletions

View File

@ -10789,14 +10789,18 @@
"type": "object" "type": "object"
}, },
"io.k8s.api.extensions.v1beta1.HTTPIngressPath": { "io.k8s.api.extensions.v1beta1.HTTPIngressPath": {
"description": "HTTPIngressPath associates a path regex with a backend. Incoming urls matching the path are forwarded to the backend.", "description": "HTTPIngressPath associates a path with a backend. Incoming urls matching the path are forwarded to the backend.",
"properties": { "properties": {
"backend": { "backend": {
"$ref": "#/definitions/io.k8s.api.extensions.v1beta1.IngressBackend", "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.IngressBackend",
"description": "Backend defines the referenced service endpoint to which the traffic will be forwarded to." "description": "Backend defines the referenced service endpoint to which the traffic will be forwarded to."
}, },
"path": { "path": {
"description": "Path is an extended POSIX regex as defined by IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. If unspecified, the path defaults to a catch all sending traffic to the backend.", "description": "Path is matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. When unspecified, all paths from incoming requests are matched.",
"type": "string"
},
"pathType": {
"description": "PathType determines the interpretation of the Path matching. PathType can be one of the following values: * Exact: Matches the URL path exactly. * Prefix: Matches based on a URL path prefix split by '/'. Matching is\n done on a path element by element basis. A path element refers is the\n list of labels in the path split by the '/' separator. A request is a\n match for path p if every p is an element-wise prefix of p of the\n request path. Note that if the last element of the path is a substring\n of the last element in request path, it is not a match (e.g. /foo/bar\n matches /foo/bar/baz, but does not match /foo/barbaz).\n* ImplementationSpecific: Interpretation of the Path matching is up to\n the IngressClass. Implementations can treat this as a separate PathType\n or treat it identically to Prefix or Exact path types.\nImplementations are required to support all path types. Defaults to ImplementationSpecific.",
"type": "string" "type": "string"
} }
}, },
@ -11714,14 +11718,18 @@
"type": "object" "type": "object"
}, },
"io.k8s.api.networking.v1beta1.HTTPIngressPath": { "io.k8s.api.networking.v1beta1.HTTPIngressPath": {
"description": "HTTPIngressPath associates a path regex with a backend. Incoming urls matching the path are forwarded to the backend.", "description": "HTTPIngressPath associates a path with a backend. Incoming urls matching the path are forwarded to the backend.",
"properties": { "properties": {
"backend": { "backend": {
"$ref": "#/definitions/io.k8s.api.networking.v1beta1.IngressBackend", "$ref": "#/definitions/io.k8s.api.networking.v1beta1.IngressBackend",
"description": "Backend defines the referenced service endpoint to which the traffic will be forwarded to." "description": "Backend defines the referenced service endpoint to which the traffic will be forwarded to."
}, },
"path": { "path": {
"description": "Path is an extended POSIX regex as defined by IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. If unspecified, the path defaults to a catch all sending traffic to the backend.", "description": "Path is matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. When unspecified, all paths from incoming requests are matched.",
"type": "string"
},
"pathType": {
"description": "PathType determines the interpretation of the Path matching. PathType can be one of the following values: * Exact: Matches the URL path exactly. * Prefix: Matches based on a URL path prefix split by '/'. Matching is\n done on a path element by element basis. A path element refers is the\n list of labels in the path split by the '/' separator. A request is a\n match for path p if every p is an element-wise prefix of p of the\n request path. Note that if the last element of the path is a substring\n of the last element in request path, it is not a match (e.g. /foo/bar\n matches /foo/bar/baz, but does not match /foo/barbaz).\n* ImplementationSpecific: Interpretation of the Path matching is up to\n the IngressClass. Implementations can treat this as a separate PathType\n or treat it identically to Prefix or Exact path types.\nImplementations are required to support all path types. Defaults to ImplementationSpecific.",
"type": "string" "type": "string"
} }
}, },

View File

@ -34,6 +34,7 @@ pkg/apis/events/v1beta1
pkg/apis/extensions/v1beta1 pkg/apis/extensions/v1beta1
pkg/apis/flowcontrol/v1alpha1 pkg/apis/flowcontrol/v1alpha1
pkg/apis/networking/v1 pkg/apis/networking/v1
pkg/apis/networking/v1beta1
pkg/apis/node/v1alpha1 pkg/apis/node/v1alpha1
pkg/apis/policy/v1beta1 pkg/apis/policy/v1beta1
pkg/apis/rbac/v1 pkg/apis/rbac/v1

View File

@ -113,6 +113,8 @@ func TestDefaulting(t *testing.T) {
{Group: "apps", Version: "v1beta2", Kind: "DeploymentList"}: {}, {Group: "apps", Version: "v1beta2", Kind: "DeploymentList"}: {},
{Group: "apps", Version: "v1", Kind: "Deployment"}: {}, {Group: "apps", Version: "v1", Kind: "Deployment"}: {},
{Group: "apps", Version: "v1", Kind: "DeploymentList"}: {}, {Group: "apps", Version: "v1", Kind: "DeploymentList"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "Ingress"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "IngressList"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicy"}: {}, {Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicy"}: {},
{Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicyList"}: {}, {Group: "extensions", Version: "v1beta1", Kind: "PodSecurityPolicyList"}: {},
{Group: "apps", Version: "v1beta2", Kind: "ReplicaSet"}: {}, {Group: "apps", Version: "v1beta2", Kind: "ReplicaSet"}: {},
@ -151,6 +153,8 @@ func TestDefaulting(t *testing.T) {
{Group: "auditregistration.k8s.io", Version: "v1alpha1", Kind: "AuditSinkList"}: {}, {Group: "auditregistration.k8s.io", Version: "v1alpha1", Kind: "AuditSinkList"}: {},
{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicy"}: {}, {Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicy"}: {},
{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicyList"}: {}, {Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicyList"}: {},
{Group: "networking.k8s.io", Version: "v1beta1", Kind: "Ingress"}: {},
{Group: "networking.k8s.io", Version: "v1beta1", Kind: "IngressList"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}: {}, {Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClassList"}: {}, {Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClassList"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSIDriver"}: {}, {Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSIDriver"}: {},

View File

@ -20,7 +20,6 @@ import (
"fmt" "fmt"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion" "k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"

View File

@ -165,3 +165,10 @@ func SetDefaults_NetworkPolicy(obj *extensionsv1beta1.NetworkPolicy) {
} }
} }
} }
func SetDefaults_HTTPIngressPath(obj *extensionsv1beta1.HTTPIngressPath) {
var defaultPathType = extensionsv1beta1.PathTypeImplementationSpecific
if obj.PathType == nil {
obj.PathType = &defaultPathType
}
}

View File

@ -1161,6 +1161,7 @@ func Convert_policy_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions(in
func autoConvert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *v1beta1.HTTPIngressPath, out *networking.HTTPIngressPath, s conversion.Scope) error { func autoConvert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *v1beta1.HTTPIngressPath, out *networking.HTTPIngressPath, s conversion.Scope) error {
out.Path = in.Path out.Path = in.Path
out.PathType = (*networking.PathType)(unsafe.Pointer(in.PathType))
if err := Convert_v1beta1_IngressBackend_To_networking_IngressBackend(&in.Backend, &out.Backend, s); err != nil { if err := Convert_v1beta1_IngressBackend_To_networking_IngressBackend(&in.Backend, &out.Backend, s); err != nil {
return err return err
} }
@ -1174,6 +1175,7 @@ func Convert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *v1beta1.H
func autoConvert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(in *networking.HTTPIngressPath, out *v1beta1.HTTPIngressPath, s conversion.Scope) error { func autoConvert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(in *networking.HTTPIngressPath, out *v1beta1.HTTPIngressPath, s conversion.Scope) error {
out.Path = in.Path out.Path = in.Path
out.PathType = (*v1beta1.PathType)(unsafe.Pointer(in.PathType))
if err := Convert_networking_IngressBackend_To_v1beta1_IngressBackend(&in.Backend, &out.Backend, s); err != nil { if err := Convert_networking_IngressBackend_To_v1beta1_IngressBackend(&in.Backend, &out.Backend, s); err != nil {
return err return err
} }

View File

@ -34,6 +34,8 @@ func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&v1beta1.DaemonSetList{}, func(obj interface{}) { SetObjectDefaults_DaemonSetList(obj.(*v1beta1.DaemonSetList)) }) scheme.AddTypeDefaultingFunc(&v1beta1.DaemonSetList{}, func(obj interface{}) { SetObjectDefaults_DaemonSetList(obj.(*v1beta1.DaemonSetList)) })
scheme.AddTypeDefaultingFunc(&v1beta1.Deployment{}, func(obj interface{}) { SetObjectDefaults_Deployment(obj.(*v1beta1.Deployment)) }) scheme.AddTypeDefaultingFunc(&v1beta1.Deployment{}, func(obj interface{}) { SetObjectDefaults_Deployment(obj.(*v1beta1.Deployment)) })
scheme.AddTypeDefaultingFunc(&v1beta1.DeploymentList{}, func(obj interface{}) { SetObjectDefaults_DeploymentList(obj.(*v1beta1.DeploymentList)) }) scheme.AddTypeDefaultingFunc(&v1beta1.DeploymentList{}, func(obj interface{}) { SetObjectDefaults_DeploymentList(obj.(*v1beta1.DeploymentList)) })
scheme.AddTypeDefaultingFunc(&v1beta1.Ingress{}, func(obj interface{}) { SetObjectDefaults_Ingress(obj.(*v1beta1.Ingress)) })
scheme.AddTypeDefaultingFunc(&v1beta1.IngressList{}, func(obj interface{}) { SetObjectDefaults_IngressList(obj.(*v1beta1.IngressList)) })
scheme.AddTypeDefaultingFunc(&v1beta1.NetworkPolicy{}, func(obj interface{}) { SetObjectDefaults_NetworkPolicy(obj.(*v1beta1.NetworkPolicy)) }) scheme.AddTypeDefaultingFunc(&v1beta1.NetworkPolicy{}, func(obj interface{}) { SetObjectDefaults_NetworkPolicy(obj.(*v1beta1.NetworkPolicy)) })
scheme.AddTypeDefaultingFunc(&v1beta1.NetworkPolicyList{}, func(obj interface{}) { SetObjectDefaults_NetworkPolicyList(obj.(*v1beta1.NetworkPolicyList)) }) scheme.AddTypeDefaultingFunc(&v1beta1.NetworkPolicyList{}, func(obj interface{}) { SetObjectDefaults_NetworkPolicyList(obj.(*v1beta1.NetworkPolicyList)) })
scheme.AddTypeDefaultingFunc(&v1beta1.PodSecurityPolicy{}, func(obj interface{}) { SetObjectDefaults_PodSecurityPolicy(obj.(*v1beta1.PodSecurityPolicy)) }) scheme.AddTypeDefaultingFunc(&v1beta1.PodSecurityPolicy{}, func(obj interface{}) { SetObjectDefaults_PodSecurityPolicy(obj.(*v1beta1.PodSecurityPolicy)) })
@ -457,6 +459,25 @@ func SetObjectDefaults_DeploymentList(in *v1beta1.DeploymentList) {
} }
} }
func SetObjectDefaults_Ingress(in *v1beta1.Ingress) {
for i := range in.Spec.Rules {
a := &in.Spec.Rules[i]
if a.IngressRuleValue.HTTP != nil {
for j := range a.IngressRuleValue.HTTP.Paths {
b := &a.IngressRuleValue.HTTP.Paths[j]
SetDefaults_HTTPIngressPath(b)
}
}
}
}
func SetObjectDefaults_IngressList(in *v1beta1.IngressList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Ingress(a)
}
}
func SetObjectDefaults_NetworkPolicy(in *v1beta1.NetworkPolicy) { func SetObjectDefaults_NetworkPolicy(in *v1beta1.NetworkPolicy) {
SetDefaults_NetworkPolicy(in) SetDefaults_NetworkPolicy(in)
} }

View File

@ -44,5 +44,10 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
np.Spec.PolicyTypes = []networking.PolicyType{networking.PolicyTypeIngress} np.Spec.PolicyTypes = []networking.PolicyType{networking.PolicyTypeIngress}
} }
}, },
func(path *networking.HTTPIngressPath, c fuzz.Continue) {
c.FuzzNoCustom(path) // fuzz self without calling this function again
pathTypes := []networking.PathType{networking.PathTypeExact, networking.PathTypePrefix, networking.PathTypeImplementationSpecific}
path.PathType = &pathTypes[c.Rand.Intn(len(pathTypes))]
},
} }
} }

View File

@ -345,8 +345,9 @@ type IngressStatus struct {
} }
// IngressRule represents the rules mapping the paths under a specified host to // IngressRule represents the rules mapping the paths under a specified host to
// the related backend services. Incoming requests are first evaluated for a host // the related backend services. Incoming requests are first evaluated for a
// match, then routed to the backend associated with the matching IngressRuleValue. // host match, then routed to the backend associated with the matching
// IngressRuleValue.
type IngressRule struct { type IngressRule struct {
// Host is the fully qualified domain name of a network host, as defined // Host is the fully qualified domain name of a network host, as defined
// by RFC 3986. Note the following deviations from the "host" part of the // by RFC 3986. Note the following deviations from the "host" part of the
@ -362,11 +363,12 @@ type IngressRule struct {
// specified IngressRuleValue. // specified IngressRuleValue.
// +optional // +optional
Host string Host string
// IngressRuleValue represents a rule to route requests for this IngressRule. // IngressRuleValue represents a rule to route requests for this
// If unspecified, the rule defaults to a http catch-all. Whether that sends // IngressRule. If unspecified, the rule defaults to a http catch-all.
// just traffic matching the host to the default backend or all traffic to the // Whether that sends just traffic matching the host to the default backend
// default backend, is left to the controller fulfilling the Ingress. Http is // or all traffic to the default backend, is left to the controller
// currently the only supported IngressRuleValue. // fulfilling the Ingress. Http is currently the only supported
// IngressRuleValue.
// +optional // +optional
IngressRuleValue IngressRuleValue
} }
@ -398,19 +400,52 @@ type HTTPIngressRuleValue struct {
// options usable by a loadbalancer, like http keep-alive. // options usable by a loadbalancer, like http keep-alive.
} }
// HTTPIngressPath associates a path regex with a backend. Incoming urls matching // PathType represents the type of path referred to by a HTTPIngressPath.
// the path are forwarded to the backend. type PathType string
const (
// PathTypeExact matches the URL path exactly and with case sensitivity.
PathTypeExact = PathType("Exact")
// PathTypePrefix matches based on a URL path prefix split by '/'. Matching
// is case sensitive and done on a path element by element basis. A path
// element refers to the list of labels in the path split by the '/'
// separator. A request is a match for path p if every p is an element-wise
// prefix of p of the request path. Note that if the last element of the
// path is a substring of the last element in request path, it is not a
// match (e.g. /foo/bar matches /foo/bar/baz, but does not match
// /foo/barbaz). If multiple matching paths exist in an Ingress spec, the
// longest matching path is given priority.
// Examples:
// - /foo/bar does not match requests to /foo/barbaz
// - /foo/bar matches request to /foo/bar and /foo/bar/baz
// - /foo and /foo/ both match requests to /foo and /foo/. If both paths are
// present in an Ingress spec, the longest matching path (/foo/) is given
// priority.
PathTypePrefix = PathType("Prefix")
// PathTypeImplementationSpecific matching is up to the IngressClass.
// Implementations can treat this as a separate PathType or treat it
// identically to Prefix or Exact path types.
PathTypeImplementationSpecific = PathType("ImplementationSpecific")
)
// HTTPIngressPath associates a path with a backend. Incoming urls matching the
// path are forwarded to the backend.
type HTTPIngressPath struct { type HTTPIngressPath struct {
// Path is an extended POSIX regex as defined by IEEE Std 1003.1, // Path is matched against the path of an incoming request. Currently it can
// (i.e this follows the egrep/unix syntax, not the perl syntax) // contain characters disallowed from the conventional "path" part of a URL
// matched against the path of an incoming request. Currently it can // as defined by RFC 3986. Paths must begin with a '/'. When unspecified,
// contain characters disallowed from the conventional "path" // all paths from incoming requests are matched.
// part of a URL as defined by RFC 3986. Paths must begin with
// a '/'. If unspecified, the path defaults to a catch all sending
// traffic to the backend.
// +optional // +optional
Path string Path string
// PathType determines the interpretation of the Path matching. PathType can
// be one of Exact, Prefix, or ImplementationSpecific. Implementations are
// required to support all path types.
// +optional
PathType *PathType
// Backend defines the referenced service endpoint to which the traffic // Backend defines the referenced service endpoint to which the traffic
// will be forwarded to. // will be forwarded to.
Backend IngressBackend Backend IngressBackend

View File

@ -21,7 +21,6 @@ import (
"testing" "testing"
networkingv1 "k8s.io/api/networking/v1" networkingv1 "k8s.io/api/networking/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -236,6 +235,7 @@ func TestSetDefaultNetworkPolicy(t *testing.T) {
} }
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
t.Helper()
data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(SchemeGroupVersion), obj) data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(SchemeGroupVersion), obj)
if err != nil { if err != nil {
t.Errorf("%v\n %#v", err, obj) t.Errorf("%v\n %#v", err, obj)

View File

@ -1,6 +1,6 @@
package(default_visibility = ["//visibility:public"]) package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
@ -36,3 +36,16 @@ filegroup(
srcs = [":package-srcs"], srcs = [":package-srcs"],
tags = ["automanaged"], tags = ["automanaged"],
) )
go_test(
name = "go_default_test",
srcs = ["defaults_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/networking/install:go_default_library",
"//staging/src/k8s.io/api/networking/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)

View File

@ -17,9 +17,17 @@ limitations under the License.
package v1beta1 package v1beta1
import ( import (
networkingv1beta1 "k8s.io/api/networking/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
) )
func addDefaultingFuncs(scheme *runtime.Scheme) error { func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme) return RegisterDefaults(scheme)
} }
func SetDefaults_HTTPIngressPath(obj *networkingv1beta1.HTTPIngressPath) {
var defaultPathType = networkingv1beta1.PathTypeImplementationSpecific
if obj.PathType == nil {
obj.PathType = &defaultPathType
}
}

View File

@ -0,0 +1,101 @@
/*
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 v1beta1_test
import (
"reflect"
"testing"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/api/legacyscheme"
_ "k8s.io/kubernetes/pkg/apis/networking/install"
. "k8s.io/kubernetes/pkg/apis/networking/v1beta1"
)
func TestSetIngressPathDefaults(t *testing.T) {
pathTypeImplementationSpecific := networkingv1beta1.PathTypeImplementationSpecific
pathTypeExact := networkingv1beta1.PathTypeExact
testCases := map[string]struct {
original *networkingv1beta1.HTTPIngressPath
expected *networkingv1beta1.HTTPIngressPath
}{
"empty pathType should default to ImplementationSpecific": {
original: &networkingv1beta1.HTTPIngressPath{},
expected: &networkingv1beta1.HTTPIngressPath{PathType: &pathTypeImplementationSpecific},
},
"ImplementationSpecific pathType should not change": {
original: &networkingv1beta1.HTTPIngressPath{PathType: &pathTypeImplementationSpecific},
expected: &networkingv1beta1.HTTPIngressPath{PathType: &pathTypeImplementationSpecific},
},
"Exact pathType should not change": {
original: &networkingv1beta1.HTTPIngressPath{PathType: &pathTypeExact},
expected: &networkingv1beta1.HTTPIngressPath{PathType: &pathTypeExact},
},
}
for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
ingressOriginal := wrapIngressPath(testCase.original)
ingressExpected := wrapIngressPath(testCase.expected)
runtimeObj := roundTrip(t, runtime.Object(ingressOriginal))
ingressActual, ok := runtimeObj.(*networkingv1beta1.Ingress)
if !ok {
t.Fatalf("Unexpected object: %v", ingressActual)
}
if !apiequality.Semantic.DeepEqual(ingressActual.Spec, ingressExpected.Spec) {
t.Errorf("Expected: %+v, got: %+v", ingressExpected.Spec, ingressActual.Spec)
}
})
}
}
func wrapIngressPath(path *networkingv1beta1.HTTPIngressPath) *networkingv1beta1.Ingress {
return &networkingv1beta1.Ingress{
Spec: networkingv1beta1.IngressSpec{
Rules: []networkingv1beta1.IngressRule{{
IngressRuleValue: networkingv1beta1.IngressRuleValue{
HTTP: &networkingv1beta1.HTTPIngressRuleValue{
Paths: []networkingv1beta1.HTTPIngressPath{*path},
},
},
}},
},
}
}
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
t.Helper()
data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(SchemeGroupVersion), obj)
if err != nil {
t.Errorf("%v\n %#v", err, obj)
return nil
}
obj2, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), data)
if err != nil {
t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj)
return nil
}
obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object)
err = legacyscheme.Scheme.Convert(obj2, obj3, nil)
if err != nil {
t.Errorf("%v\nSource: %#v", err, obj2)
return nil
}
return obj3
}

View File

@ -174,6 +174,7 @@ func RegisterConversions(s *runtime.Scheme) error {
func autoConvert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *v1beta1.HTTPIngressPath, out *networking.HTTPIngressPath, s conversion.Scope) error { func autoConvert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *v1beta1.HTTPIngressPath, out *networking.HTTPIngressPath, s conversion.Scope) error {
out.Path = in.Path out.Path = in.Path
out.PathType = (*networking.PathType)(unsafe.Pointer(in.PathType))
if err := Convert_v1beta1_IngressBackend_To_networking_IngressBackend(&in.Backend, &out.Backend, s); err != nil { if err := Convert_v1beta1_IngressBackend_To_networking_IngressBackend(&in.Backend, &out.Backend, s); err != nil {
return err return err
} }
@ -187,6 +188,7 @@ func Convert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *v1beta1.H
func autoConvert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(in *networking.HTTPIngressPath, out *v1beta1.HTTPIngressPath, s conversion.Scope) error { func autoConvert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(in *networking.HTTPIngressPath, out *v1beta1.HTTPIngressPath, s conversion.Scope) error {
out.Path = in.Path out.Path = in.Path
out.PathType = (*v1beta1.PathType)(unsafe.Pointer(in.PathType))
if err := Convert_networking_IngressBackend_To_v1beta1_IngressBackend(&in.Backend, &out.Backend, s); err != nil { if err := Convert_networking_IngressBackend_To_v1beta1_IngressBackend(&in.Backend, &out.Backend, s); err != nil {
return err return err
} }

View File

@ -21,6 +21,7 @@ limitations under the License.
package v1beta1 package v1beta1
import ( import (
v1beta1 "k8s.io/api/networking/v1beta1"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
) )
@ -28,5 +29,26 @@ import (
// Public to allow building arbitrary schemes. // Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters. // All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error { func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&v1beta1.Ingress{}, func(obj interface{}) { SetObjectDefaults_Ingress(obj.(*v1beta1.Ingress)) })
scheme.AddTypeDefaultingFunc(&v1beta1.IngressList{}, func(obj interface{}) { SetObjectDefaults_IngressList(obj.(*v1beta1.IngressList)) })
return nil return nil
} }
func SetObjectDefaults_Ingress(in *v1beta1.Ingress) {
for i := range in.Spec.Rules {
a := &in.Spec.Rules[i]
if a.IngressRuleValue.HTTP != nil {
for j := range a.IngressRuleValue.HTTP.Paths {
b := &a.IngressRuleValue.HTTP.Paths[j]
SetDefaults_HTTPIngressPath(b)
}
}
}
}
func SetObjectDefaults_IngressList(in *v1beta1.IngressList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Ingress(a)
}
}

View File

@ -17,8 +17,11 @@ go_test(
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/networking:go_default_library", "//pkg/apis/networking:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//staging/src/k8s.io/api/networking/v1:go_default_library",
"//staging/src/k8s.io/api/networking/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
@ -43,6 +46,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/validation/path:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/validation/path:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",

View File

@ -17,6 +17,7 @@ limitations under the License.
package validation package validation
import ( import (
"fmt"
"net" "net"
"regexp" "regexp"
"strings" "strings"
@ -24,6 +25,7 @@ import (
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation" apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
pathvalidation "k8s.io/apimachinery/pkg/api/validation/path" pathvalidation "k8s.io/apimachinery/pkg/api/validation/path"
unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation"
@ -38,6 +40,16 @@ const (
maxLenIngressClassController = 250 maxLenIngressClassController = 250
) )
var (
supportedPathTypes = sets.NewString(
string(networking.PathTypeExact),
string(networking.PathTypePrefix),
string(networking.PathTypeImplementationSpecific),
)
invalidPathSequences = []string{"//", "/./", "/../", "%2f", "%2F"}
invalidPathSuffixes = []string{"/..", "/."}
)
// ValidateNetworkPolicyName can be used to check whether the given networkpolicy // ValidateNetworkPolicyName can be used to check whether the given networkpolicy
// name is valid. // name is valid.
func ValidateNetworkPolicyName(name string, prefix bool) []string { func ValidateNetworkPolicyName(name string, prefix bool) []string {
@ -184,17 +196,27 @@ func ValidateIPBlock(ipb *networking.IPBlock, fldPath *field.Path) field.ErrorLi
// name. // name.
var ValidateIngressName = apimachineryvalidation.NameIsDNSSubdomain var ValidateIngressName = apimachineryvalidation.NameIsDNSSubdomain
// IngressValidationOptions cover beta to GA transitions for HTTP PathType
type IngressValidationOptions struct {
requireRegexPath bool
}
// ValidateIngress validates Ingresses on create and update. // ValidateIngress validates Ingresses on create and update.
func ValidateIngress(ingress *networking.Ingress) field.ErrorList { func validateIngress(ingress *networking.Ingress, opts IngressValidationOptions, requestGV schema.GroupVersion) field.ErrorList {
allErrs := apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName, field.NewPath("metadata")) allErrs := apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName, field.NewPath("metadata"))
allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec, field.NewPath("spec"))...) allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec, field.NewPath("spec"), opts, requestGV)...)
return allErrs return allErrs
} }
// ValidateIngressCreate validates Ingresses on create. // ValidateIngressCreate validates Ingresses on create.
func ValidateIngressCreate(ingress *networking.Ingress) field.ErrorList { func ValidateIngressCreate(ingress *networking.Ingress, requestGV schema.GroupVersion) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
allErrs = append(allErrs, ValidateIngress(ingress)...) var opts IngressValidationOptions
opts = IngressValidationOptions{
// TODO(robscott): Remove regex validation for 1.19.
requireRegexPath: true,
}
allErrs = append(allErrs, validateIngress(ingress, opts, requestGV)...)
annotationVal, annotationIsSet := ingress.Annotations[annotationIngressClass] annotationVal, annotationIsSet := ingress.Annotations[annotationIngressClass]
if annotationIsSet && ingress.Spec.IngressClassName != nil { if annotationIsSet && ingress.Spec.IngressClassName != nil {
annotationPath := field.NewPath("annotations").Child(annotationIngressClass) annotationPath := field.NewPath("annotations").Child(annotationIngressClass)
@ -204,9 +226,17 @@ func ValidateIngressCreate(ingress *networking.Ingress) field.ErrorList {
} }
// ValidateIngressUpdate validates ingresses on update. // ValidateIngressUpdate validates ingresses on update.
func ValidateIngressUpdate(ingress, oldIngress *networking.Ingress) field.ErrorList { func ValidateIngressUpdate(ingress, oldIngress *networking.Ingress, requestGV schema.GroupVersion) field.ErrorList {
allErrs := apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta, field.NewPath("metadata")) allErrs := apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta, field.NewPath("metadata"))
allErrs = append(allErrs, ValidateIngress(ingress)...) var opts IngressValidationOptions
opts = IngressValidationOptions{
// TODO(robscott): Remove regex validation for 1.19.
// Only require regex path validation for this Ingress if the previous
// version of the Ingress also passed that validation.
requireRegexPath: allPathsPassRegexValidation(oldIngress),
}
allErrs = append(allErrs, validateIngress(ingress, opts, requestGV)...)
return allErrs return allErrs
} }
@ -232,16 +262,17 @@ func validateIngressTLS(spec *networking.IngressSpec, fldPath *field.Path) field
} }
// ValidateIngressSpec tests if required fields in the IngressSpec are set. // ValidateIngressSpec tests if required fields in the IngressSpec are set.
func ValidateIngressSpec(spec *networking.IngressSpec, fldPath *field.Path) field.ErrorList { func ValidateIngressSpec(spec *networking.IngressSpec, fldPath *field.Path, opts IngressValidationOptions, requestGV schema.GroupVersion) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
// TODO: Is a default backend mandatory? if len(spec.Rules) == 0 && spec.Backend == nil {
errMsg := "either `backend` or `rules` must be specified"
allErrs = append(allErrs, field.Invalid(fldPath, spec.Rules, errMsg))
}
if spec.Backend != nil { if spec.Backend != nil {
allErrs = append(allErrs, validateIngressBackend(spec.Backend, fldPath.Child("backend"))...) allErrs = append(allErrs, validateIngressBackend(spec.Backend, fldPath.Child("backend"))...)
} else if len(spec.Rules) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath, spec.Rules, "either `backend` or `rules` must be specified"))
} }
if len(spec.Rules) > 0 { if len(spec.Rules) > 0 {
allErrs = append(allErrs, validateIngressRules(spec.Rules, fldPath.Child("rules"))...) allErrs = append(allErrs, validateIngressRules(spec.Rules, fldPath.Child("rules"), opts)...)
} }
if len(spec.TLS) > 0 { if len(spec.TLS) > 0 {
allErrs = append(allErrs, validateIngressTLS(spec, fldPath.Child("tls"))...) allErrs = append(allErrs, validateIngressTLS(spec, fldPath.Child("tls"))...)
@ -261,7 +292,7 @@ func ValidateIngressStatusUpdate(ingress, oldIngress *networking.Ingress) field.
return allErrs return allErrs
} }
func validateIngressRules(ingressRules []networking.IngressRule, fldPath *field.Path) field.ErrorList { func validateIngressRules(ingressRules []networking.IngressRule, fldPath *field.Path, opts IngressValidationOptions) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if len(ingressRules) == 0 { if len(ingressRules) == 0 {
return append(allErrs, field.Required(fldPath, "")) return append(allErrs, field.Required(fldPath, ""))
@ -283,45 +314,74 @@ func validateIngressRules(ingressRules []networking.IngressRule, fldPath *field.
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg)) allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg))
} }
} }
allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue, fldPath.Index(0))...) allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue, fldPath.Index(0), opts)...)
} }
return allErrs return allErrs
} }
func validateIngressRuleValue(ingressRule *networking.IngressRuleValue, fldPath *field.Path) field.ErrorList { func validateIngressRuleValue(ingressRule *networking.IngressRuleValue, fldPath *field.Path, opts IngressValidationOptions) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if ingressRule.HTTP != nil { if ingressRule.HTTP != nil {
allErrs = append(allErrs, validateHTTPIngressRuleValue(ingressRule.HTTP, fldPath.Child("http"))...) allErrs = append(allErrs, validateHTTPIngressRuleValue(ingressRule.HTTP, fldPath.Child("http"), opts)...)
} }
return allErrs return allErrs
} }
func validateHTTPIngressRuleValue(httpIngressRuleValue *networking.HTTPIngressRuleValue, fldPath *field.Path) field.ErrorList { func validateHTTPIngressRuleValue(httpIngressRuleValue *networking.HTTPIngressRuleValue, fldPath *field.Path, opts IngressValidationOptions) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if len(httpIngressRuleValue.Paths) == 0 { if len(httpIngressRuleValue.Paths) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("paths"), "")) allErrs = append(allErrs, field.Required(fldPath.Child("paths"), ""))
} }
for i, rule := range httpIngressRuleValue.Paths { for i, path := range httpIngressRuleValue.Paths {
if len(rule.Path) > 0 { allErrs = append(allErrs, validateHTTPIngressPath(&path, fldPath.Child("paths").Index(i), opts)...)
if !strings.HasPrefix(rule.Path, "/") { }
allErrs = append(allErrs, field.Invalid(fldPath.Child("paths").Index(i).Child("path"), rule.Path, "must be an absolute path")) return allErrs
}
func validateHTTPIngressPath(path *networking.HTTPIngressPath, fldPath *field.Path, opts IngressValidationOptions) field.ErrorList {
allErrs := field.ErrorList{}
if path.PathType == nil {
return append(allErrs, field.Required(fldPath.Child("pathType"), "pathType must be specified"))
}
switch *path.PathType {
case networking.PathTypeExact, networking.PathTypePrefix:
if !strings.HasPrefix(path.Path, "/") {
allErrs = append(allErrs, field.Invalid(fldPath.Child("path"), path.Path, "must be an absolute path"))
}
if len(path.Path) > 0 {
for _, invalidSeq := range invalidPathSequences {
if strings.Contains(path.Path, invalidSeq) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("path"), path.Path, fmt.Sprintf("must not contain '%s'", invalidSeq)))
}
} }
// TODO: More draconian path regex validation.
// Path must be a valid regex. This is the basic requirement. for _, invalidSuff := range invalidPathSuffixes {
// In addition to this any characters not allowed in a path per if strings.HasSuffix(path.Path, invalidSuff) {
// RFC 3986 section-3.3 cannot appear as a literal in the regex. allErrs = append(allErrs, field.Invalid(fldPath.Child("path"), path.Path, fmt.Sprintf("cannot end with '%s'", invalidSuff)))
// Consider the example: http://host/valid?#bar, everything after }
// the last '/' is a valid regex that matches valid#bar, which
// isn't a valid path, because the path terminates at the first ?
// or #. A more sophisticated form of validation would detect that
// the user is confusing url regexes with path regexes.
_, err := regexp.CompilePOSIX(rule.Path)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("paths").Index(i).Child("path"), rule.Path, "must be a valid regex"))
} }
} }
allErrs = append(allErrs, validateIngressBackend(&rule.Backend, fldPath.Child("backend"))...) case networking.PathTypeImplementationSpecific:
if len(path.Path) > 0 {
if !strings.HasPrefix(path.Path, "/") {
allErrs = append(allErrs, field.Invalid(fldPath.Child("path"), path.Path, "must be an absolute path"))
}
}
default:
allErrs = append(allErrs, field.NotSupported(fldPath.Child("pathType"), *path.PathType, supportedPathTypes.List()))
} }
// TODO(robscott): Remove regex validation for 1.19.
if opts.requireRegexPath {
_, err := regexp.CompilePOSIX(path.Path)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("path"), path.Path, "must be a valid regex"))
}
}
allErrs = append(allErrs, validateIngressBackend(&path.Backend, fldPath.Child("backend"))...)
return allErrs return allErrs
} }
@ -408,3 +468,22 @@ func validateIngressClassParameters(params *api.TypedLocalObjectReference, fldPa
return allErrs return allErrs
} }
// allPathsPassRegexValidation returns true if the Ingress has paths that all
// match the Ingress path validation with requireRegexPath enabled.
func allPathsPassRegexValidation(ingress *networking.Ingress) bool {
for _, rule := range ingress.Spec.Rules {
if rule.HTTP == nil {
continue
}
for _, path := range rule.HTTP.Paths {
if len(path.Path) == 0 {
continue
}
if _, err := regexp.CompilePOSIX(path.Path); err != nil {
return false
}
}
}
return true
}

View File

@ -18,19 +18,22 @@ package validation
import ( import (
"fmt" "fmt"
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
utilpointer "k8s.io/utils/pointer"
"strings" "strings"
"testing" "testing"
networkingv1 "k8s.io/api/networking/v1"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing" featuregatetesting "k8s.io/component-base/featuregate/testing"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/pkg/apis/networking"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
utilpointer "k8s.io/utils/pointer"
) )
func TestValidateNetworkPolicy(t *testing.T) { func TestValidateNetworkPolicy(t *testing.T) {
@ -897,106 +900,265 @@ func TestValidateIngress(t *testing.T) {
ServiceName: "default-backend", ServiceName: "default-backend",
ServicePort: intstr.FromInt(80), ServicePort: intstr.FromInt(80),
} }
pathTypePrefix := networking.PathTypePrefix
pathTypeImplementationSpecific := networking.PathTypeImplementationSpecific
pathTypeFoo := networking.PathType("foo")
newValid := func() networking.Ingress { baseIngress := networking.Ingress{
return networking.Ingress{ ObjectMeta: metav1.ObjectMeta{
ObjectMeta: metav1.ObjectMeta{ Name: "foo",
Name: "foo", Namespace: metav1.NamespaceDefault,
Namespace: metav1.NamespaceDefault, },
Spec: networking.IngressSpec{
Backend: &networking.IngressBackend{
ServiceName: "default-backend",
ServicePort: intstr.FromInt(80),
}, },
Spec: networking.IngressSpec{ Rules: []networking.IngressRule{
Backend: &networking.IngressBackend{ {
ServiceName: "default-backend", Host: "foo.bar.com",
ServicePort: intstr.FromInt(80), IngressRuleValue: networking.IngressRuleValue{
}, HTTP: &networking.HTTPIngressRuleValue{
Rules: []networking.IngressRule{ Paths: []networking.HTTPIngressPath{
{ {
Host: "foo.bar.com", Path: "/foo",
IngressRuleValue: networking.IngressRuleValue{ PathType: &pathTypeImplementationSpecific,
HTTP: &networking.HTTPIngressRuleValue{ Backend: defaultBackend,
Paths: []networking.HTTPIngressPath{
{
Path: "/foo",
Backend: defaultBackend,
},
}, },
}, },
}, },
}, },
}, },
}, },
Status: networking.IngressStatus{ },
LoadBalancer: api.LoadBalancerStatus{ Status: networking.IngressStatus{
Ingress: []api.LoadBalancerIngress{ LoadBalancer: api.LoadBalancerStatus{
{IP: "127.0.0.1"}, Ingress: []api.LoadBalancerIngress{
}, {IP: "127.0.0.1"},
}, },
}, },
}
}
servicelessBackend := newValid()
servicelessBackend.Spec.Backend.ServiceName = ""
invalidNameBackend := newValid()
invalidNameBackend.Spec.Backend.ServiceName = "defaultBackend"
noPortBackend := newValid()
noPortBackend.Spec.Backend = &networking.IngressBackend{ServiceName: defaultBackend.ServiceName}
noForwardSlashPath := newValid()
noForwardSlashPath.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []networking.HTTPIngressPath{
{
Path: "invalid",
Backend: defaultBackend,
}, },
} }
noPaths := newValid()
noPaths.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []networking.HTTPIngressPath{} testCases := map[string]struct {
badHost := newValid() groupVersion *schema.GroupVersion
badHost.Spec.Rules[0].Host = "foobar:80" tweakIngress func(ing *networking.Ingress)
badRegexPath := newValid() expectErrsOnFields []string
badPathExpr := "/invalid[" }{
badRegexPath.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []networking.HTTPIngressPath{ "empty path (implementation specific)": {
{ tweakIngress: func(ing *networking.Ingress) {
Path: badPathExpr, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path = ""
Backend: defaultBackend, },
expectErrsOnFields: []string{},
},
"valid path": {
tweakIngress: func(ing *networking.Ingress) {
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path = "/valid"
},
expectErrsOnFields: []string{},
},
// invalid use cases
"backend (v1beta1) with no service": {
groupVersion: &networkingv1beta1.SchemeGroupVersion,
tweakIngress: func(ing *networking.Ingress) {
ing.Spec.Backend.ServiceName = ""
},
expectErrsOnFields: []string{
"spec.backend.serviceName",
},
},
"invalid path type": {
tweakIngress: func(ing *networking.Ingress) {
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &pathTypeFoo
},
expectErrsOnFields: []string{
"spec.rules[0].http.paths[0].pathType",
},
},
"empty path (prefix)": {
tweakIngress: func(ing *networking.Ingress) {
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path = ""
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &pathTypePrefix
},
expectErrsOnFields: []string{
"spec.rules[0].http.paths[0].path",
},
},
"no paths": {
tweakIngress: func(ing *networking.Ingress) {
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []networking.HTTPIngressPath{}
},
expectErrsOnFields: []string{
"spec.rules[0].http.paths",
},
},
"invalid host (foobar:80)": {
tweakIngress: func(ing *networking.Ingress) {
ing.Spec.Rules[0].Host = "foobar:80"
},
expectErrsOnFields: []string{
"spec.rules[0].host",
},
},
"invalid host (127.0.0.1)": {
tweakIngress: func(ing *networking.Ingress) {
ing.Spec.Rules[0].Host = "127.0.0.1"
},
expectErrsOnFields: []string{
"spec.rules[0].host",
},
}, },
} }
badPathErr := fmt.Sprintf("spec.rules[0].http.paths[0].path: Invalid value: '%v'", badPathExpr)
hostIP := "127.0.0.1"
badHostIP := newValid()
badHostIP.Spec.Rules[0].Host = hostIP
badHostIPErr := fmt.Sprintf("spec.rules[0].host: Invalid value: '%v'", hostIP)
errorCases := map[string]networking.Ingress{ for name, testCase := range testCases {
"spec.backend.serviceName: Required value": servicelessBackend, t.Run(name, func(t *testing.T) {
"spec.backend.serviceName: Invalid value": invalidNameBackend, ingress := baseIngress.DeepCopy()
"spec.backend.servicePort: Invalid value": noPortBackend, testCase.tweakIngress(ingress)
"spec.rules[0].host: Invalid value": badHost, gv := testCase.groupVersion
"spec.rules[0].http.paths: Required value": noPaths, if gv == nil {
"spec.rules[0].http.paths[0].path: Invalid value": noForwardSlashPath, gv = &networkingv1.SchemeGroupVersion
}
errorCases[badPathErr] = badRegexPath
errorCases[badHostIPErr] = badHostIP
wildcardHost := "foo.*.bar.com"
badWildcard := newValid()
badWildcard.Spec.Rules[0].Host = wildcardHost
badWildcardErr := fmt.Sprintf("spec.rules[0].host: Invalid value: '%v'", wildcardHost)
errorCases[badWildcardErr] = badWildcard
for k, v := range errorCases {
errs := ValidateIngress(&v)
if len(errs) == 0 {
t.Errorf("expected failure for %q", k)
} else {
s := strings.Split(k, ":")
err := errs[0]
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
t.Errorf("unexpected error: %q, expected: %q", err, k)
} }
} errs := validateIngress(ingress, IngressValidationOptions{requireRegexPath: true}, *gv)
if len(testCase.expectErrsOnFields) != len(errs) {
t.Fatalf("Expected %d errors, got %d errors: %v", len(testCase.expectErrsOnFields), len(errs), errs)
}
for i, err := range errs {
if err.Field != testCase.expectErrsOnFields[i] {
t.Errorf("Expected error on field: %s, got: %s", testCase.expectErrsOnFields[i], err.Error())
}
}
})
}
}
func TestValidateIngressRuleValue(t *testing.T) {
fldPath := field.NewPath("testing.http.paths[0].path")
testCases := map[string]struct {
pathType networking.PathType
path string
requireRegexPath bool
expectedErrs field.ErrorList
}{
"implementation specific: no leading slash": {
pathType: networking.PathTypeImplementationSpecific,
path: "foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "foo", "must be an absolute path")},
},
"implementation specific: leading slash": {
pathType: networking.PathTypeImplementationSpecific,
path: "/foo",
expectedErrs: field.ErrorList{},
},
"implementation specific: many slashes": {
pathType: networking.PathTypeImplementationSpecific,
path: "/foo/bar/foo",
expectedErrs: field.ErrorList{},
},
"implementation specific: repeating slashes": {
pathType: networking.PathTypeImplementationSpecific,
path: "/foo//bar/foo",
expectedErrs: field.ErrorList{},
},
"prefix: no leading slash": {
pathType: networking.PathTypePrefix,
path: "foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "foo", "must be an absolute path")},
},
"prefix: leading slash": {
pathType: networking.PathTypePrefix,
path: "/foo",
expectedErrs: field.ErrorList{},
},
"prefix: many slashes": {
pathType: networking.PathTypePrefix,
path: "/foo/bar/foo",
expectedErrs: field.ErrorList{},
},
"prefix: repeating slashes": {
pathType: networking.PathTypePrefix,
path: "/foo//bar/foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "/foo//bar/foo", "must not contain '//'")},
},
"exact: no leading slash": {
pathType: networking.PathTypeExact,
path: "foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "foo", "must be an absolute path")},
},
"exact: leading slash": {
pathType: networking.PathTypeExact,
path: "/foo",
expectedErrs: field.ErrorList{},
},
"exact: many slashes": {
pathType: networking.PathTypeExact,
path: "/foo/bar/foo",
expectedErrs: field.ErrorList{},
},
"exact: repeating slashes": {
pathType: networking.PathTypeExact,
path: "/foo//bar/foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "/foo//bar/foo", "must not contain '//'")},
},
"prefix: with /./": {
pathType: networking.PathTypePrefix,
path: "/foo/./foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "/foo/./foo", "must not contain '/./'")},
},
"exact: with /../": {
pathType: networking.PathTypeExact,
path: "/foo/../foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "/foo/../foo", "must not contain '/../'")},
},
"prefix: with %2f": {
pathType: networking.PathTypePrefix,
path: "/foo/%2f/foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "/foo/%2f/foo", "must not contain '%2f'")},
},
"exact: with %2F": {
pathType: networking.PathTypeExact,
path: "/foo/%2F/foo",
expectedErrs: field.ErrorList{field.Invalid(fldPath, "/foo/%2F/foo", "must not contain '%2F'")},
},
}
for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
irv := &networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: testCase.path,
PathType: &testCase.pathType,
Backend: networking.IngressBackend{
ServiceName: "default-backend",
ServicePort: intstr.FromInt(80),
},
},
},
},
}
errs := validateIngressRuleValue(irv, field.NewPath("testing"), IngressValidationOptions{requireRegexPath: true})
if len(errs) != len(testCase.expectedErrs) {
t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs)
}
for i, err := range errs {
if err.Error() != testCase.expectedErrs[i].Error() {
t.Fatalf("Expected error: %v, got %v", testCase.expectedErrs[i], err)
}
}
})
} }
} }
func TestValidateIngressCreate(t *testing.T) { func TestValidateIngressCreate(t *testing.T) {
implementationPathType := networking.PathTypeImplementationSpecific
defaultBackend := networking.IngressBackend{
ServiceName: "default-backend",
ServicePort: intstr.FromInt(80),
}
baseIngress := networking.Ingress{ baseIngress := networking.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "test123", Name: "test123",
@ -1004,10 +1166,8 @@ func TestValidateIngressCreate(t *testing.T) {
ResourceVersion: "1234", ResourceVersion: "1234",
}, },
Spec: networking.IngressSpec{ Spec: networking.IngressSpec{
Backend: &networking.IngressBackend{ Backend: &defaultBackend,
ServiceName: "default-backend", Rules: []networking.IngressRule{},
ServicePort: intstr.FromInt(80),
},
}, },
} }
@ -1034,6 +1194,40 @@ func TestValidateIngressCreate(t *testing.T) {
}, },
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("annotations").Child(annotationIngressClass), "foo", "can not be set when the class field is also set")}, expectedErrs: field.ErrorList{field.Invalid(field.NewPath("annotations").Child(annotationIngressClass), "foo", "can not be set when the class field is also set")},
}, },
"valid regex path": {
tweakIngress: func(ingress *networking.Ingress) {
ingress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/([a-z0-9]*)",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
},
expectedErrs: field.ErrorList{},
},
"invalid regex path": {
tweakIngress: func(ingress *networking.Ingress) {
ingress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/([a-z0-9]*)[",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec.rules[0].http.paths[0].path"), "/([a-z0-9]*)[", "must be a valid regex")},
},
} }
for name, testCase := range testCases { for name, testCase := range testCases {
@ -1041,7 +1235,7 @@ func TestValidateIngressCreate(t *testing.T) {
newIngress := baseIngress.DeepCopy() newIngress := baseIngress.DeepCopy()
testCase.tweakIngress(newIngress) testCase.tweakIngress(newIngress)
errs := ValidateIngressCreate(newIngress) errs := ValidateIngressCreate(newIngress, networkingv1beta1.SchemeGroupVersion)
if len(errs) != len(testCase.expectedErrs) { if len(errs) != len(testCase.expectedErrs) {
t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs) t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs)
} }
@ -1056,6 +1250,11 @@ func TestValidateIngressCreate(t *testing.T) {
} }
func TestValidateIngressUpdate(t *testing.T) { func TestValidateIngressUpdate(t *testing.T) {
implementationPathType := networking.PathTypeImplementationSpecific
defaultBackend := networking.IngressBackend{
ServiceName: "default-backend",
ServicePort: intstr.FromInt(80),
}
baseIngress := networking.Ingress{ baseIngress := networking.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "test123", Name: "test123",
@ -1063,10 +1262,7 @@ func TestValidateIngressUpdate(t *testing.T) {
ResourceVersion: "1234", ResourceVersion: "1234",
}, },
Spec: networking.IngressSpec{ Spec: networking.IngressSpec{
Backend: &networking.IngressBackend{ Backend: &defaultBackend,
ServiceName: "default-backend",
ServicePort: intstr.FromInt(80),
},
}, },
} }
@ -1093,6 +1289,122 @@ func TestValidateIngressUpdate(t *testing.T) {
}, },
expectedErrs: field.ErrorList{}, expectedErrs: field.ErrorList{},
}, },
"valid regex path -> valid regex path": {
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
oldIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/([a-z0-9]*)",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
newIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/([a-z0-9%]*)",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
},
expectedErrs: field.ErrorList{},
},
"valid regex path -> invalid regex path": {
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
oldIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/([a-z0-9]*)",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
newIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/bar[",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
},
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec.rules[0].http.paths[0].path"), "/bar[", "must be a valid regex")},
},
"invalid regex path -> valid regex path": {
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
oldIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/bar[",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
newIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/([a-z0-9]*)",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
},
expectedErrs: field.ErrorList{},
},
"invalid regex path -> invalid regex path": {
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
oldIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/foo[",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
newIngress.Spec.Rules = []networking.IngressRule{{
Host: "foo.bar.com",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{{
Path: "/bar[",
PathType: &implementationPathType,
Backend: defaultBackend,
}},
},
},
}}
},
expectedErrs: field.ErrorList{},
},
} }
for name, testCase := range testCases { for name, testCase := range testCases {
@ -1101,7 +1413,7 @@ func TestValidateIngressUpdate(t *testing.T) {
oldIngress := baseIngress.DeepCopy() oldIngress := baseIngress.DeepCopy()
testCase.tweakIngresses(newIngress, oldIngress) testCase.tweakIngresses(newIngress, oldIngress)
errs := ValidateIngressUpdate(newIngress, oldIngress) errs := ValidateIngressUpdate(newIngress, oldIngress, networkingv1beta1.SchemeGroupVersion)
if len(errs) != len(testCase.expectedErrs) { if len(errs) != len(testCase.expectedErrs) {
t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs) t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs)
@ -1360,7 +1672,7 @@ func TestValidateIngressTLS(t *testing.T) {
errorCases[badWildcardTLSErr] = badWildcardTLS errorCases[badWildcardTLSErr] = badWildcardTLS
for k, v := range errorCases { for k, v := range errorCases {
errs := ValidateIngress(&v) errs := validateIngress(&v, IngressValidationOptions{requireRegexPath: true}, networkingv1beta1.SchemeGroupVersion)
if len(errs) == 0 { if len(errs) == 0 {
t.Errorf("expected failure for %q", k) t.Errorf("expected failure for %q", k)
} else { } else {

View File

@ -30,6 +30,11 @@ import (
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) { func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) {
*out = *in *out = *in
if in.PathType != nil {
in, out := &in.PathType, &out.PathType
*out = new(PathType)
**out = **in
}
out.Backend = in.Backend out.Backend = in.Backend
return return
} }
@ -50,7 +55,9 @@ func (in *HTTPIngressRuleValue) DeepCopyInto(out *HTTPIngressRuleValue) {
if in.Paths != nil { if in.Paths != nil {
in, out := &in.Paths, &out.Paths in, out := &in.Paths, &out.Paths
*out = make([]HTTPIngressPath, len(*in)) *out = make([]HTTPIngressPath, len(*in))
copy(*out, *in) for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
} }
return return
} }

View File

@ -19,7 +19,9 @@ go_library(
"//pkg/apis/networking/validation:go_default_library", "//pkg/apis/networking/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
], ],
) )

View File

@ -57,6 +57,7 @@ var (
defaultBackendPort = intstr.FromInt(80) defaultBackendPort = intstr.FromInt(80)
defaultLoadBalancer = "127.0.0.1" defaultLoadBalancer = "127.0.0.1"
defaultPath = "/foo" defaultPath = "/foo"
defaultPathType = networking.PathTypeImplementationSpecific
defaultPathMap = map[string]string{defaultPath: defaultBackendName} defaultPathMap = map[string]string{defaultPath: defaultBackendName}
defaultTLS = []networking.IngressTLS{ defaultTLS = []networking.IngressTLS{
{Hosts: []string{"foo.bar.com", "*.bar.com"}, SecretName: "fooSecret"}, {Hosts: []string{"foo.bar.com", "*.bar.com"}, SecretName: "fooSecret"},
@ -69,7 +70,8 @@ func toHTTPIngressPaths(pathMap map[string]string) []networking.HTTPIngressPath
httpPaths := []networking.HTTPIngressPath{} httpPaths := []networking.HTTPIngressPath{}
for path, backend := range pathMap { for path, backend := range pathMap {
httpPaths = append(httpPaths, networking.HTTPIngressPath{ httpPaths = append(httpPaths, networking.HTTPIngressPath{
Path: path, Path: path,
PathType: &defaultPathType,
Backend: networking.IngressBackend{ Backend: networking.IngressBackend{
ServiceName: backend, ServiceName: backend,
ServicePort: defaultBackendPort, ServicePort: defaultBackendPort,
@ -130,16 +132,16 @@ func TestCreate(t *testing.T) {
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store) test := genericregistrytest.New(t, storage.Store)
ingress := validIngress() ingress := validIngress()
noDefaultBackendAndRules := validIngress() noBackendAndRules := validIngress()
noDefaultBackendAndRules.Spec.Backend = &networking.IngressBackend{} noBackendAndRules.Spec.Backend = &networking.IngressBackend{}
noDefaultBackendAndRules.Spec.Rules = []networking.IngressRule{} noBackendAndRules.Spec.Rules = []networking.IngressRule{}
badPath := validIngress() badPath := validIngress()
badPath.Spec.Rules = toIngressRules(map[string]IngressRuleValues{ badPath.Spec.Rules = toIngressRules(map[string]IngressRuleValues{
"foo.bar.com": {"/invalid[": "svc"}}) "foo.bar.com": {"/invalid[": "svc"}})
test.TestCreate( test.TestCreate(
// valid // valid
ingress, ingress,
noDefaultBackendAndRules, noBackendAndRules,
badPath, badPath,
) )
} }

View File

@ -18,10 +18,11 @@ package ingress
import ( import (
"context" "context"
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/storage/names" "k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/pkg/apis/networking"
@ -67,11 +68,14 @@ func (ingressStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Ob
} }
// Validate validates a new Ingress. // Validate validates ingresses on create.
func (ingressStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { func (ingressStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
var requestGV schema.GroupVersion
if requestInfo, ok := request.RequestInfoFrom(ctx); ok {
requestGV = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion}
}
ingress := obj.(*networking.Ingress) ingress := obj.(*networking.Ingress)
err := validation.ValidateIngress(ingress) return validation.ValidateIngressCreate(ingress, requestGV)
return err
} }
// Canonicalize normalizes the object after validation. // Canonicalize normalizes the object after validation.
@ -83,11 +87,13 @@ func (ingressStrategy) AllowCreateOnUpdate() bool {
return false return false
} }
// ValidateUpdate is the default update validation for an end user. // ValidateUpdate validates ingresses on update.
func (ingressStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { func (ingressStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
validationErrorList := validation.ValidateIngress(obj.(*networking.Ingress)) var requestGV schema.GroupVersion
updateErrorList := validation.ValidateIngressUpdate(obj.(*networking.Ingress), old.(*networking.Ingress)) if requestInfo, ok := request.RequestInfoFrom(ctx); ok {
return append(validationErrorList, updateErrorList...) requestGV = schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion}
}
return validation.ValidateIngressUpdate(obj.(*networking.Ingress), old.(*networking.Ingress), requestGV)
} }
// AllowUnconditionalUpdate is the default update policy for Ingress objects. // AllowUnconditionalUpdate is the default update policy for Ingress objects.

View File

@ -31,6 +31,7 @@ func newIngress() networking.Ingress {
ServiceName: "default-backend", ServiceName: "default-backend",
ServicePort: intstr.FromInt(80), ServicePort: intstr.FromInt(80),
} }
implementationPathType := networking.PathTypeImplementationSpecific
return networking.Ingress{ return networking.Ingress{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "foo", Name: "foo",
@ -48,8 +49,9 @@ func newIngress() networking.Ingress {
HTTP: &networking.HTTPIngressRuleValue{ HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{ Paths: []networking.HTTPIngressPath{
{ {
Path: "/foo", Path: "/foo",
Backend: defaultBackend, PathType: &implementationPathType,
Backend: defaultBackend,
}, },
}, },
}, },
@ -69,6 +71,11 @@ func newIngress() networking.Ingress {
func TestIngressStrategy(t *testing.T) { func TestIngressStrategy(t *testing.T) {
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
apiRequest := genericapirequest.RequestInfo{APIGroup: "networking.k8s.io",
APIVersion: "v1beta1",
Resource: "ingresses",
}
ctx = genericapirequest.WithRequestInfo(ctx, &apiRequest)
if !Strategy.NamespaceScoped() { if !Strategy.NamespaceScoped() {
t.Errorf("Ingress must be namespace scoped") t.Errorf("Ingress must be namespace scoped")
} }

View File

@ -1683,238 +1683,239 @@ func init() {
} }
var fileDescriptor_cdc93917efc28165 = []byte{ var fileDescriptor_cdc93917efc28165 = []byte{
// 3684 bytes of a gzipped FileDescriptorProto // 3705 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0x4f, 0x6c, 0x1b, 0x47, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5b, 0x4f, 0x6c, 0x1b, 0x47,
0x77, 0xf7, 0x92, 0x94, 0x48, 0x3d, 0xfd, 0x1f, 0xc9, 0x12, 0x3f, 0xfb, 0xb3, 0xe8, 0x6f, 0x03, 0x77, 0xf7, 0x92, 0x94, 0x48, 0x3d, 0xfd, 0x1f, 0xc9, 0x12, 0x3f, 0xfb, 0xb3, 0xe8, 0x6f, 0x03,
0xb8, 0x4e, 0x6a, 0x93, 0xb1, 0x63, 0xfb, 0x73, 0x6d, 0x34, 0x89, 0x28, 0x59, 0xb6, 0x52, 0xfd, 0xb8, 0x4e, 0x6a, 0x93, 0xb1, 0x63, 0xfb, 0x73, 0x6d, 0x34, 0x89, 0x28, 0x59, 0xb6, 0x52, 0xfd,
0x61, 0x86, 0x92, 0x1b, 0x04, 0x4d, 0x9a, 0x15, 0x39, 0xa2, 0xd6, 0x5a, 0xee, 0x6e, 0x76, 0x96, 0x61, 0x86, 0x92, 0x1b, 0x04, 0x4d, 0x9a, 0x15, 0x39, 0xa2, 0xd6, 0x5a, 0xee, 0x6e, 0x76, 0x96,
0x8a, 0x08, 0xf4, 0xd0, 0x43, 0x51, 0xa0, 0x40, 0x8b, 0xf6, 0x92, 0xb6, 0xc7, 0x06, 0x05, 0x7a, 0x8a, 0x08, 0xf4, 0xd0, 0x43, 0x51, 0xa0, 0x40, 0x81, 0xf6, 0x92, 0xb6, 0xc7, 0x06, 0x05, 0x7a,
0x6a, 0xd1, 0xde, 0xda, 0x43, 0x10, 0xb4, 0x40, 0x0a, 0x18, 0x45, 0x5a, 0xe4, 0xd6, 0x9c, 0x84, 0x6a, 0xd1, 0xde, 0xda, 0x43, 0x10, 0xb4, 0x68, 0x0a, 0x18, 0x45, 0x5a, 0xe4, 0xd6, 0x9c, 0x84,
0x46, 0x39, 0x15, 0x3d, 0xf5, 0x56, 0xf8, 0x54, 0xcc, 0xec, 0xec, 0xff, 0x5d, 0x71, 0xa5, 0xd8, 0x46, 0x39, 0x15, 0x3d, 0xf5, 0x56, 0xf8, 0x54, 0xcc, 0xec, 0xec, 0xff, 0x5d, 0x71, 0xa5, 0xd8,
0x42, 0x03, 0xf4, 0x26, 0xce, 0x7b, 0xef, 0xf7, 0xde, 0xcc, 0xbc, 0x79, 0xef, 0xcd, 0xec, 0x13, 0x42, 0x03, 0xf4, 0x64, 0x71, 0xde, 0x7b, 0xbf, 0xf7, 0x66, 0xe6, 0xcd, 0x7b, 0x6f, 0x66, 0x9f,
0xac, 0xec, 0xdf, 0xa7, 0x55, 0xd5, 0xa8, 0xed, 0xf7, 0x76, 0x88, 0xa5, 0x13, 0x9b, 0xd0, 0xda, 0x61, 0x65, 0xff, 0x3e, 0xad, 0xaa, 0x46, 0x6d, 0xbf, 0xb7, 0x43, 0x2c, 0x9d, 0xd8, 0x84, 0xd6,
0x01, 0xd1, 0xdb, 0x86, 0x55, 0x13, 0x04, 0xc5, 0x54, 0x6b, 0xe4, 0xd0, 0x26, 0x3a, 0x55, 0x0d, 0x0e, 0x88, 0xde, 0x36, 0xac, 0x9a, 0x20, 0x28, 0xa6, 0x5a, 0x23, 0x87, 0x36, 0xd1, 0xa9, 0x6a,
0x9d, 0xd6, 0x0e, 0x6e, 0xed, 0x10, 0x5b, 0xb9, 0x55, 0xeb, 0x10, 0x9d, 0x58, 0x8a, 0x4d, 0xda, 0xe8, 0xb4, 0x76, 0x70, 0x6b, 0x87, 0xd8, 0xca, 0xad, 0x5a, 0x87, 0xe8, 0xc4, 0x52, 0x6c, 0xd2,
0x55, 0xd3, 0x32, 0x6c, 0x03, 0x5d, 0x71, 0xd8, 0xab, 0x8a, 0xa9, 0x56, 0x7d, 0xf6, 0xaa, 0x60, 0xae, 0x9a, 0x96, 0x61, 0x1b, 0xe8, 0x8a, 0xc3, 0x5e, 0x55, 0x4c, 0xb5, 0xea, 0xb3, 0x57, 0x05,
0xbf, 0x74, 0xb3, 0xa3, 0xda, 0x7b, 0xbd, 0x9d, 0x6a, 0xcb, 0xe8, 0xd6, 0x3a, 0x46, 0xc7, 0xa8, 0xfb, 0xa5, 0x9b, 0x1d, 0xd5, 0xde, 0xeb, 0xed, 0x54, 0x5b, 0x46, 0xb7, 0xd6, 0x31, 0x3a, 0x46,
0x71, 0xa9, 0x9d, 0xde, 0x2e, 0xff, 0xc5, 0x7f, 0xf0, 0xbf, 0x1c, 0xb4, 0x4b, 0x72, 0x40, 0x79, 0x8d, 0x4b, 0xed, 0xf4, 0x76, 0xf9, 0x2f, 0xfe, 0x83, 0xff, 0xe5, 0xa0, 0x5d, 0x92, 0x03, 0xca,
0xcb, 0xb0, 0x48, 0xed, 0x20, 0xa6, 0xf1, 0xd2, 0x1d, 0x9f, 0xa7, 0xab, 0xb4, 0xf6, 0x54, 0x9d, 0x5b, 0x86, 0x45, 0x6a, 0x07, 0x31, 0x8d, 0x97, 0xee, 0xf8, 0x3c, 0x5d, 0xa5, 0xb5, 0xa7, 0xea,
0x58, 0xfd, 0x9a, 0xb9, 0xdf, 0x61, 0x03, 0xb4, 0xd6, 0x25, 0xb6, 0x92, 0x24, 0x55, 0x4b, 0x93, 0xc4, 0xea, 0xd7, 0xcc, 0xfd, 0x0e, 0x1b, 0xa0, 0xb5, 0x2e, 0xb1, 0x95, 0x24, 0xa9, 0x5a, 0x9a,
0xb2, 0x7a, 0xba, 0xad, 0x76, 0x49, 0x4c, 0xe0, 0xde, 0x20, 0x01, 0xda, 0xda, 0x23, 0x5d, 0x25, 0x94, 0xd5, 0xd3, 0x6d, 0xb5, 0x4b, 0x62, 0x02, 0xf7, 0x06, 0x09, 0xd0, 0xd6, 0x1e, 0xe9, 0x2a,
0x26, 0xf7, 0x56, 0x9a, 0x5c, 0xcf, 0x56, 0xb5, 0x9a, 0xaa, 0xdb, 0xd4, 0xb6, 0xa2, 0x42, 0xf2, 0x31, 0xb9, 0xb7, 0xd2, 0xe4, 0x7a, 0xb6, 0xaa, 0xd5, 0x54, 0xdd, 0xa6, 0xb6, 0x15, 0x15, 0x92,
0x1d, 0x98, 0x5a, 0xd4, 0x34, 0xe3, 0x33, 0xd2, 0x5e, 0x6a, 0xae, 0x2e, 0x5b, 0xea, 0x01, 0xb1, 0xef, 0xc0, 0xd4, 0xa2, 0xa6, 0x19, 0x9f, 0x91, 0xf6, 0x52, 0x73, 0x75, 0xd9, 0x52, 0x0f, 0x88,
0xd0, 0x55, 0x28, 0xe8, 0x4a, 0x97, 0x94, 0xa5, 0xab, 0xd2, 0xf5, 0x91, 0xfa, 0xd8, 0xf3, 0xa3, 0x85, 0xae, 0x42, 0x41, 0x57, 0xba, 0xa4, 0x2c, 0x5d, 0x95, 0xae, 0x8f, 0xd4, 0xc7, 0x9e, 0x1f,
0xca, 0x85, 0xe3, 0xa3, 0x4a, 0x61, 0x43, 0xe9, 0x12, 0xcc, 0x29, 0xf2, 0x43, 0x98, 0x16, 0x52, 0x55, 0x2e, 0x1c, 0x1f, 0x55, 0x0a, 0x1b, 0x4a, 0x97, 0x60, 0x4e, 0x91, 0x1f, 0xc2, 0xb4, 0x90,
0x2b, 0x1a, 0x39, 0x7c, 0x6a, 0x68, 0xbd, 0x2e, 0x41, 0xd7, 0x60, 0xb8, 0xcd, 0x01, 0x84, 0xe0, 0x5a, 0xd1, 0xc8, 0xe1, 0x53, 0x43, 0xeb, 0x75, 0x09, 0xba, 0x06, 0xc3, 0x6d, 0x0e, 0x20, 0x04,
0x84, 0x10, 0x1c, 0x76, 0x60, 0xb1, 0xa0, 0xca, 0x14, 0x26, 0x85, 0xf0, 0x13, 0x83, 0xda, 0x0d, 0x27, 0x84, 0xe0, 0xb0, 0x03, 0x8b, 0x05, 0x55, 0xa6, 0x30, 0x29, 0x84, 0x9f, 0x18, 0xd4, 0x6e,
0xc5, 0xde, 0x43, 0xb7, 0x01, 0x4c, 0xc5, 0xde, 0x6b, 0x58, 0x64, 0x57, 0x3d, 0x14, 0xe2, 0x48, 0x28, 0xf6, 0x1e, 0xba, 0x0d, 0x60, 0x2a, 0xf6, 0x5e, 0xc3, 0x22, 0xbb, 0xea, 0xa1, 0x10, 0x47,
0x88, 0x43, 0xc3, 0xa3, 0xe0, 0x00, 0x17, 0xba, 0x01, 0x25, 0x8b, 0x28, 0xed, 0x4d, 0x5d, 0xeb, 0x42, 0x1c, 0x1a, 0x1e, 0x05, 0x07, 0xb8, 0xd0, 0x0d, 0x28, 0x59, 0x44, 0x69, 0x6f, 0xea, 0x5a,
0x97, 0x73, 0x57, 0xa5, 0xeb, 0xa5, 0xfa, 0x94, 0x90, 0x28, 0x61, 0x31, 0x8e, 0x3d, 0x0e, 0xf9, 0xbf, 0x9c, 0xbb, 0x2a, 0x5d, 0x2f, 0xd5, 0xa7, 0x84, 0x44, 0x09, 0x8b, 0x71, 0xec, 0x71, 0xc8,
0xf3, 0x1c, 0x8c, 0x2c, 0x2b, 0xa4, 0x6b, 0xe8, 0x4d, 0x62, 0xa3, 0x4f, 0xa0, 0xc4, 0xb6, 0xab, 0x9f, 0xe7, 0x60, 0x64, 0x59, 0x21, 0x5d, 0x43, 0x6f, 0x12, 0x1b, 0x7d, 0x02, 0x25, 0xb6, 0x5d,
0xad, 0xd8, 0x0a, 0xd7, 0x36, 0x7a, 0xfb, 0xcd, 0xaa, 0xef, 0x4e, 0xde, 0xea, 0x55, 0xcd, 0xfd, 0x6d, 0xc5, 0x56, 0xb8, 0xb6, 0xd1, 0xdb, 0x6f, 0x56, 0x7d, 0x77, 0xf2, 0x56, 0xaf, 0x6a, 0xee,
0x0e, 0x1b, 0xa0, 0x55, 0xc6, 0x5d, 0x3d, 0xb8, 0x55, 0xdd, 0xdc, 0x79, 0x46, 0x5a, 0xf6, 0x3a, 0x77, 0xd8, 0x00, 0xad, 0x32, 0xee, 0xea, 0xc1, 0xad, 0xea, 0xe6, 0xce, 0x33, 0xd2, 0xb2, 0xd7,
0xb1, 0x15, 0xdf, 0x3e, 0x7f, 0x0c, 0x7b, 0xa8, 0x68, 0x03, 0x0a, 0xd4, 0x24, 0x2d, 0x6e, 0xd9, 0x89, 0xad, 0xf8, 0xf6, 0xf9, 0x63, 0xd8, 0x43, 0x45, 0x1b, 0x50, 0xa0, 0x26, 0x69, 0x71, 0xcb,
0xe8, 0xed, 0x1b, 0xd5, 0x13, 0x9d, 0xb5, 0xea, 0x59, 0xd6, 0x34, 0x49, 0xcb, 0x5f, 0x71, 0xf6, 0x46, 0x6f, 0xdf, 0xa8, 0x9e, 0xe8, 0xac, 0x55, 0xcf, 0xb2, 0xa6, 0x49, 0x5a, 0xfe, 0x8a, 0xb3,
0x0b, 0x73, 0x1c, 0xf4, 0x14, 0x86, 0xa9, 0xad, 0xd8, 0x3d, 0x5a, 0xce, 0x73, 0xc4, 0x6a, 0x66, 0x5f, 0x98, 0xe3, 0xa0, 0xa7, 0x30, 0x4c, 0x6d, 0xc5, 0xee, 0xd1, 0x72, 0x9e, 0x23, 0x56, 0x33,
0x44, 0x2e, 0xe5, 0x6f, 0x86, 0xf3, 0x1b, 0x0b, 0x34, 0xf9, 0x3f, 0x73, 0x80, 0x3c, 0xde, 0x25, 0x23, 0x72, 0x29, 0x7f, 0x33, 0x9c, 0xdf, 0x58, 0xa0, 0xc9, 0xff, 0x99, 0x03, 0xe4, 0xf1, 0x2e,
0x43, 0x6f, 0xab, 0xb6, 0x6a, 0xe8, 0xe8, 0x01, 0x14, 0xec, 0xbe, 0xe9, 0xba, 0xc0, 0x35, 0xd7, 0x19, 0x7a, 0x5b, 0xb5, 0x55, 0x43, 0x47, 0x0f, 0xa0, 0x60, 0xf7, 0x4d, 0xd7, 0x05, 0xae, 0xb9,
0xa0, 0xad, 0xbe, 0x49, 0x5e, 0x1c, 0x55, 0xe6, 0xe2, 0x12, 0x8c, 0x82, 0xb9, 0x0c, 0x5a, 0xf3, 0x06, 0x6d, 0xf5, 0x4d, 0xf2, 0xe2, 0xa8, 0x32, 0x17, 0x97, 0x60, 0x14, 0xcc, 0x65, 0xd0, 0x9a,
0x4c, 0xcd, 0x71, 0xe9, 0x3b, 0x61, 0xd5, 0x2f, 0x8e, 0x2a, 0x09, 0x87, 0xad, 0xea, 0x21, 0x85, 0x67, 0x6a, 0x8e, 0x4b, 0xdf, 0x09, 0xab, 0x7e, 0x71, 0x54, 0x49, 0x38, 0x6c, 0x55, 0x0f, 0x29,
0x0d, 0x44, 0x07, 0x80, 0x34, 0x85, 0xda, 0x5b, 0x96, 0xa2, 0x53, 0x47, 0x93, 0xda, 0x25, 0x62, 0x6c, 0x20, 0x3a, 0x00, 0xa4, 0x29, 0xd4, 0xde, 0xb2, 0x14, 0x9d, 0x3a, 0x9a, 0xd4, 0x2e, 0x11,
0x11, 0xde, 0xc8, 0xb6, 0x69, 0x4c, 0xa2, 0x7e, 0x49, 0x58, 0x81, 0xd6, 0x62, 0x68, 0x38, 0x41, 0x8b, 0xf0, 0x46, 0xb6, 0x4d, 0x63, 0x12, 0xf5, 0x4b, 0xc2, 0x0a, 0xb4, 0x16, 0x43, 0xc3, 0x09,
0x03, 0xf3, 0x66, 0x8b, 0x28, 0xd4, 0xd0, 0xcb, 0x85, 0xb0, 0x37, 0x63, 0x3e, 0x8a, 0x05, 0x15, 0x1a, 0x98, 0x37, 0x5b, 0x44, 0xa1, 0x86, 0x5e, 0x2e, 0x84, 0xbd, 0x19, 0xf3, 0x51, 0x2c, 0xa8,
0xbd, 0x0e, 0xc5, 0x2e, 0xa1, 0x54, 0xe9, 0x90, 0xf2, 0x10, 0x67, 0x9c, 0x14, 0x8c, 0xc5, 0x75, 0xe8, 0x75, 0x28, 0x76, 0x09, 0xa5, 0x4a, 0x87, 0x94, 0x87, 0x38, 0xe3, 0xa4, 0x60, 0x2c, 0xae,
0x67, 0x18, 0xbb, 0x74, 0xf9, 0x4b, 0x09, 0xc6, 0xbd, 0x95, 0x5b, 0x53, 0xa9, 0x8d, 0x7e, 0x2b, 0x3b, 0xc3, 0xd8, 0xa5, 0xcb, 0x5f, 0x4a, 0x30, 0xee, 0xad, 0xdc, 0x9a, 0x4a, 0x6d, 0xf4, 0x5b,
0xe6, 0x87, 0xd5, 0x6c, 0x53, 0x62, 0xd2, 0xdc, 0x0b, 0x3d, 0x9f, 0x77, 0x47, 0x02, 0x3e, 0xb8, 0x31, 0x3f, 0xac, 0x66, 0x9b, 0x12, 0x93, 0xe6, 0x5e, 0xe8, 0xf9, 0xbc, 0x3b, 0x12, 0xf0, 0xc1,
0x0e, 0x43, 0xaa, 0x4d, 0xba, 0x6c, 0x1f, 0xf2, 0xd7, 0x47, 0x6f, 0x5f, 0xcf, 0xea, 0x32, 0xf5, 0x75, 0x18, 0x52, 0x6d, 0xd2, 0x65, 0xfb, 0x90, 0xbf, 0x3e, 0x7a, 0xfb, 0x7a, 0x56, 0x97, 0xa9,
0x71, 0x01, 0x3a, 0xb4, 0xca, 0xc4, 0xb1, 0x83, 0x22, 0xff, 0x69, 0x21, 0x60, 0x3e, 0x73, 0x4d, 0x8f, 0x0b, 0xd0, 0xa1, 0x55, 0x26, 0x8e, 0x1d, 0x14, 0xf9, 0x4f, 0x0a, 0x01, 0xf3, 0x99, 0x6b,
0xf4, 0x11, 0x94, 0x28, 0xd1, 0x48, 0xcb, 0x36, 0x2c, 0x61, 0xfe, 0x5b, 0x19, 0xcd, 0x57, 0x76, 0xa2, 0x8f, 0xa0, 0x44, 0x89, 0x46, 0x5a, 0xb6, 0x61, 0x09, 0xf3, 0xdf, 0xca, 0x68, 0xbe, 0xb2,
0x88, 0xd6, 0x14, 0xa2, 0xf5, 0x31, 0x66, 0xbf, 0xfb, 0x0b, 0x7b, 0x90, 0xe8, 0x7d, 0x28, 0xd9, 0x43, 0xb4, 0xa6, 0x10, 0xad, 0x8f, 0x31, 0xfb, 0xdd, 0x5f, 0xd8, 0x83, 0x44, 0xef, 0x43, 0xc9,
0xa4, 0x6b, 0x6a, 0x8a, 0x4d, 0xc4, 0x39, 0x7a, 0x2d, 0x38, 0x05, 0xe6, 0x39, 0x0c, 0xac, 0x61, 0x26, 0x5d, 0x53, 0x53, 0x6c, 0x22, 0xce, 0xd1, 0x6b, 0xc1, 0x29, 0x30, 0xcf, 0x61, 0x60, 0x0d,
0xb4, 0xb7, 0x04, 0x1b, 0x3f, 0x3e, 0xde, 0x92, 0xb8, 0xa3, 0xd8, 0x83, 0x41, 0x07, 0x30, 0xd1, 0xa3, 0xbd, 0x25, 0xd8, 0xf8, 0xf1, 0xf1, 0x96, 0xc4, 0x1d, 0xc5, 0x1e, 0x0c, 0x3a, 0x80, 0x89,
0x33, 0xdb, 0x8c, 0xd3, 0x66, 0x51, 0xb0, 0xd3, 0x17, 0x9e, 0x74, 0x2f, 0xeb, 0xda, 0x6c, 0x87, 0x9e, 0xd9, 0x66, 0x9c, 0x36, 0x8b, 0x82, 0x9d, 0xbe, 0xf0, 0xa4, 0x7b, 0x59, 0xd7, 0x66, 0x3b,
0xa4, 0xeb, 0x73, 0x42, 0xd7, 0x44, 0x78, 0x1c, 0x47, 0xb4, 0xa0, 0x45, 0x98, 0xec, 0xaa, 0x3a, 0x24, 0x5d, 0x9f, 0x13, 0xba, 0x26, 0xc2, 0xe3, 0x38, 0xa2, 0x05, 0x2d, 0xc2, 0x64, 0x57, 0xd5,
0x8b, 0x4b, 0xfd, 0x26, 0x69, 0x19, 0x7a, 0x9b, 0x72, 0xb7, 0x1a, 0xaa, 0xcf, 0x0b, 0x80, 0xc9, 0x59, 0x5c, 0xea, 0x37, 0x49, 0xcb, 0xd0, 0xdb, 0x94, 0xbb, 0xd5, 0x50, 0x7d, 0x5e, 0x00, 0x4c,
0xf5, 0x30, 0x19, 0x47, 0xf9, 0xd1, 0x7b, 0x80, 0xdc, 0x69, 0x3c, 0x76, 0x82, 0xb8, 0x6a, 0xe8, 0xae, 0x87, 0xc9, 0x38, 0xca, 0x8f, 0xde, 0x03, 0xe4, 0x4e, 0xe3, 0xb1, 0x13, 0xc4, 0x55, 0x43,
0xdc, 0xe7, 0xf2, 0xbe, 0x73, 0x6f, 0xc5, 0x38, 0x70, 0x82, 0x14, 0x5a, 0x83, 0x59, 0x8b, 0x1c, 0xe7, 0x3e, 0x97, 0xf7, 0x9d, 0x7b, 0x2b, 0xc6, 0x81, 0x13, 0xa4, 0xd0, 0x1a, 0xcc, 0x5a, 0xe4,
0xa8, 0x6c, 0x8e, 0x4f, 0x54, 0x6a, 0x1b, 0x56, 0x7f, 0x4d, 0xed, 0xaa, 0x76, 0x79, 0x98, 0xdb, 0x40, 0x65, 0x73, 0x7c, 0xa2, 0x52, 0xdb, 0xb0, 0xfa, 0x6b, 0x6a, 0x57, 0xb5, 0xcb, 0xc3, 0xdc,
0x54, 0x3e, 0x3e, 0xaa, 0xcc, 0xe2, 0x04, 0x3a, 0x4e, 0x94, 0x92, 0xff, 0x6c, 0x18, 0x26, 0x23, 0xa6, 0xf2, 0xf1, 0x51, 0x65, 0x16, 0x27, 0xd0, 0x71, 0xa2, 0x94, 0xfc, 0xa7, 0xc3, 0x30, 0x19,
0xf1, 0x06, 0x3d, 0x85, 0xb9, 0x56, 0xcf, 0xb2, 0x88, 0x6e, 0x6f, 0xf4, 0xba, 0x3b, 0xc4, 0x6a, 0x89, 0x37, 0xe8, 0x29, 0xcc, 0xb5, 0x7a, 0x96, 0x45, 0x74, 0x7b, 0xa3, 0xd7, 0xdd, 0x21, 0x56,
0xb6, 0xf6, 0x48, 0xbb, 0xa7, 0x91, 0x36, 0x77, 0x94, 0xa1, 0xfa, 0x82, 0xb0, 0x78, 0x6e, 0x29, 0xb3, 0xb5, 0x47, 0xda, 0x3d, 0x8d, 0xb4, 0xb9, 0xa3, 0x0c, 0xd5, 0x17, 0x84, 0xc5, 0x73, 0x4b,
0x91, 0x0b, 0xa7, 0x48, 0xb3, 0x55, 0xd0, 0xf9, 0xd0, 0xba, 0x4a, 0xa9, 0x87, 0x99, 0xe3, 0x98, 0x89, 0x5c, 0x38, 0x45, 0x9a, 0xad, 0x82, 0xce, 0x87, 0xd6, 0x55, 0x4a, 0x3d, 0xcc, 0x1c, 0xc7,
0xde, 0x2a, 0x6c, 0xc4, 0x38, 0x70, 0x82, 0x14, 0xb3, 0xb1, 0x4d, 0xa8, 0x6a, 0x91, 0x76, 0xd4, 0xf4, 0x56, 0x61, 0x23, 0xc6, 0x81, 0x13, 0xa4, 0x98, 0x8d, 0x6d, 0x42, 0x55, 0x8b, 0xb4, 0xa3,
0xc6, 0x7c, 0xd8, 0xc6, 0xe5, 0x44, 0x2e, 0x9c, 0x22, 0x8d, 0xee, 0xc2, 0xa8, 0xa3, 0x8d, 0xef, 0x36, 0xe6, 0xc3, 0x36, 0x2e, 0x27, 0x72, 0xe1, 0x14, 0x69, 0x74, 0x17, 0x46, 0x1d, 0x6d, 0x7c,
0x9f, 0xd8, 0xe8, 0x19, 0x01, 0x36, 0xba, 0xe1, 0x93, 0x70, 0x90, 0x8f, 0x4d, 0xcd, 0xd8, 0xa1, 0xff, 0xc4, 0x46, 0xcf, 0x08, 0xb0, 0xd1, 0x0d, 0x9f, 0x84, 0x83, 0x7c, 0x6c, 0x6a, 0xc6, 0x0e,
0xc4, 0x3a, 0x20, 0xed, 0xf4, 0x0d, 0xde, 0x8c, 0x71, 0xe0, 0x04, 0x29, 0x36, 0x35, 0xc7, 0x03, 0x25, 0xd6, 0x01, 0x69, 0xa7, 0x6f, 0xf0, 0x66, 0x8c, 0x03, 0x27, 0x48, 0xb1, 0xa9, 0x39, 0x1e,
0x63, 0x53, 0x1b, 0x0e, 0x4f, 0x6d, 0x3b, 0x91, 0x0b, 0xa7, 0x48, 0x33, 0x3f, 0x76, 0x4c, 0x5e, 0x18, 0x9b, 0xda, 0x70, 0x78, 0x6a, 0xdb, 0x89, 0x5c, 0x38, 0x45, 0x9a, 0xf9, 0xb1, 0x63, 0xf2,
0x3c, 0x50, 0x54, 0x4d, 0xd9, 0xd1, 0x48, 0xb9, 0x18, 0xf6, 0xe3, 0x8d, 0x30, 0x19, 0x47, 0xf9, 0xe2, 0x81, 0xa2, 0x6a, 0xca, 0x8e, 0x46, 0xca, 0xc5, 0xb0, 0x1f, 0x6f, 0x84, 0xc9, 0x38, 0xca,
0xd1, 0x63, 0x98, 0x76, 0x86, 0xb6, 0x75, 0xc5, 0x03, 0x29, 0x71, 0x90, 0x9f, 0x09, 0x90, 0xe9, 0x8f, 0x1e, 0xc3, 0xb4, 0x33, 0xb4, 0xad, 0x2b, 0x1e, 0x48, 0x89, 0x83, 0xfc, 0x4c, 0x80, 0x4c,
0x8d, 0x28, 0x03, 0x8e, 0xcb, 0xa0, 0x07, 0x30, 0xd1, 0x32, 0x34, 0x8d, 0xfb, 0xe3, 0x92, 0xd1, 0x6f, 0x44, 0x19, 0x70, 0x5c, 0x06, 0x3d, 0x80, 0x89, 0x96, 0xa1, 0x69, 0xdc, 0x1f, 0x97, 0x8c,
0xd3, 0xed, 0xf2, 0x08, 0x47, 0x41, 0xec, 0x3c, 0x2e, 0x85, 0x28, 0x38, 0xc2, 0x89, 0x08, 0x40, 0x9e, 0x6e, 0x97, 0x47, 0x38, 0x0a, 0x62, 0xe7, 0x71, 0x29, 0x44, 0xc1, 0x11, 0x4e, 0x44, 0x00,
0xcb, 0x4d, 0x38, 0xb4, 0x0c, 0x3c, 0x3e, 0xde, 0xca, 0x1a, 0x03, 0xbc, 0x54, 0xe5, 0xd7, 0x00, 0x5a, 0x6e, 0xc2, 0xa1, 0x65, 0xe0, 0xf1, 0xf1, 0x56, 0xd6, 0x18, 0xe0, 0xa5, 0x2a, 0xbf, 0x06,
0xde, 0x10, 0xc5, 0x01, 0x60, 0xf9, 0x5f, 0x24, 0x98, 0x4f, 0x09, 0x1d, 0xe8, 0x9d, 0x50, 0x8a, 0xf0, 0x86, 0x28, 0x0e, 0x00, 0xcb, 0xff, 0x22, 0xc1, 0x7c, 0x4a, 0xe8, 0x40, 0xef, 0x84, 0x52,
0xfd, 0xd5, 0x48, 0x8a, 0xbd, 0x9c, 0x22, 0x16, 0xc8, 0xb3, 0x3a, 0x8c, 0x5b, 0x6c, 0x56, 0x7a, 0xec, 0xaf, 0x46, 0x52, 0xec, 0xe5, 0x14, 0xb1, 0x40, 0x9e, 0xd5, 0x61, 0xdc, 0x62, 0xb3, 0xd2,
0xc7, 0x61, 0x11, 0x31, 0xf2, 0xee, 0x80, 0x69, 0xe0, 0xa0, 0x8c, 0x1f, 0xf3, 0xa7, 0x8f, 0x8f, 0x3b, 0x0e, 0x8b, 0x88, 0x91, 0x77, 0x07, 0x4c, 0x03, 0x07, 0x65, 0xfc, 0x98, 0x3f, 0x7d, 0x7c,
0x2a, 0xe3, 0x21, 0x1a, 0x0e, 0xc3, 0xcb, 0x7f, 0x9e, 0x03, 0x58, 0x26, 0xa6, 0x66, 0xf4, 0xbb, 0x54, 0x19, 0x0f, 0xd1, 0x70, 0x18, 0x5e, 0xfe, 0xb3, 0x1c, 0xc0, 0x32, 0x31, 0x35, 0xa3, 0xdf,
0x44, 0x3f, 0x8f, 0x1a, 0x6a, 0x33, 0x54, 0x43, 0xdd, 0x1c, 0xb4, 0x3d, 0x9e, 0x69, 0xa9, 0x45, 0x25, 0xfa, 0x79, 0xd4, 0x50, 0x9b, 0xa1, 0x1a, 0xea, 0xe6, 0xa0, 0xed, 0xf1, 0x4c, 0x4b, 0x2d,
0xd4, 0x6f, 0x46, 0x8a, 0xa8, 0x5a, 0x76, 0xc8, 0x93, 0xab, 0xa8, 0x7f, 0xcf, 0xc3, 0x8c, 0xcf, 0xa2, 0x7e, 0x33, 0x52, 0x44, 0xd5, 0xb2, 0x43, 0x9e, 0x5c, 0x45, 0xfd, 0x7b, 0x1e, 0x66, 0x7c,
0xec, 0x97, 0x51, 0x0f, 0x43, 0x7b, 0xfc, 0x2b, 0x91, 0x3d, 0x9e, 0x4f, 0x10, 0x79, 0x65, 0x75, 0x66, 0xbf, 0x8c, 0x7a, 0x18, 0xda, 0xe3, 0x5f, 0x89, 0xec, 0xf1, 0x7c, 0x82, 0xc8, 0x2b, 0xab,
0xd4, 0x33, 0x98, 0x60, 0x55, 0x8e, 0xb3, 0x97, 0xbc, 0x86, 0x1a, 0x3e, 0x75, 0x0d, 0xe5, 0x65, 0xa3, 0x9e, 0xc1, 0x04, 0xab, 0x72, 0x9c, 0xbd, 0xe4, 0x35, 0xd4, 0xf0, 0xa9, 0x6b, 0x28, 0x2f,
0xbb, 0xb5, 0x10, 0x12, 0x8e, 0x20, 0xa7, 0xd4, 0x6c, 0xc5, 0x9f, 0x62, 0xcd, 0xf6, 0x95, 0x04, 0xdb, 0xad, 0x85, 0x90, 0x70, 0x04, 0x39, 0xa5, 0x66, 0x2b, 0xfe, 0x14, 0x6b, 0xb6, 0xaf, 0x24,
0x13, 0xfe, 0x36, 0x9d, 0x43, 0xd1, 0xb6, 0x11, 0x2e, 0xda, 0x5e, 0xcf, 0xec, 0xa2, 0x29, 0x55, 0x98, 0xf0, 0xb7, 0xe9, 0x1c, 0x8a, 0xb6, 0x8d, 0x70, 0xd1, 0xf6, 0x7a, 0x66, 0x17, 0x4d, 0xa9,
0xdb, 0xff, 0xb0, 0x02, 0xdf, 0x63, 0x62, 0x07, 0x7c, 0x47, 0x69, 0xed, 0x0f, 0xbe, 0xe3, 0xa1, 0xda, 0xfe, 0x87, 0x15, 0xf8, 0x1e, 0x13, 0x3b, 0xe0, 0x3b, 0x4a, 0x6b, 0x7f, 0xf0, 0x1d, 0x0f,
0xcf, 0x25, 0x40, 0x22, 0x0b, 0x2c, 0xea, 0xba, 0x61, 0x2b, 0x4e, 0xac, 0x74, 0xcc, 0x5a, 0xcd, 0x7d, 0x2e, 0x01, 0x12, 0x59, 0x60, 0x51, 0xd7, 0x0d, 0x5b, 0x71, 0x62, 0xa5, 0x63, 0xd6, 0x6a,
0x6c, 0x96, 0xab, 0xb1, 0xba, 0x1d, 0xc3, 0x7a, 0xa4, 0xdb, 0x56, 0xdf, 0xdf, 0xe4, 0x38, 0x03, 0x66, 0xb3, 0x5c, 0x8d, 0xd5, 0xed, 0x18, 0xd6, 0x23, 0xdd, 0xb6, 0xfa, 0xfe, 0x26, 0xc7, 0x19,
0x4e, 0x30, 0x00, 0x29, 0x00, 0x96, 0xc0, 0xdc, 0x32, 0xc4, 0x41, 0xbe, 0x99, 0x21, 0xe6, 0x31, 0x70, 0x82, 0x01, 0x48, 0x01, 0xb0, 0x04, 0xe6, 0x96, 0x21, 0x0e, 0xf2, 0xcd, 0x0c, 0x31, 0x8f,
0x81, 0x25, 0x43, 0xdf, 0x55, 0x3b, 0x7e, 0xd8, 0xc1, 0x1e, 0x10, 0x0e, 0x80, 0x5e, 0x7a, 0x04, 0x09, 0x2c, 0x19, 0xfa, 0xae, 0xda, 0xf1, 0xc3, 0x0e, 0xf6, 0x80, 0x70, 0x00, 0xf4, 0xd2, 0x23,
0xf3, 0x29, 0xd6, 0xa2, 0x29, 0xc8, 0xef, 0x93, 0xbe, 0xb3, 0x6c, 0x98, 0xfd, 0x89, 0x66, 0x61, 0x98, 0x4f, 0xb1, 0x16, 0x4d, 0x41, 0x7e, 0x9f, 0xf4, 0x9d, 0x65, 0xc3, 0xec, 0x4f, 0x34, 0x0b,
0xe8, 0x40, 0xd1, 0x7a, 0x4e, 0xf8, 0x1d, 0xc1, 0xce, 0x8f, 0x07, 0xb9, 0xfb, 0x92, 0xfc, 0xe5, 0x43, 0x07, 0x8a, 0xd6, 0x73, 0xc2, 0xef, 0x08, 0x76, 0x7e, 0x3c, 0xc8, 0xdd, 0x97, 0xe4, 0x2f,
0x50, 0xd0, 0x77, 0x78, 0xc5, 0x7c, 0x9d, 0x5d, 0x5a, 0x4d, 0x4d, 0x6d, 0x29, 0x54, 0x14, 0x42, 0x87, 0x82, 0xbe, 0xc3, 0x2b, 0xe6, 0xeb, 0xec, 0xd2, 0x6a, 0x6a, 0x6a, 0x4b, 0xa1, 0xa2, 0x10,
0x63, 0xce, 0x85, 0xd5, 0x19, 0xc3, 0x1e, 0x35, 0x54, 0x5b, 0xe7, 0x5e, 0x6d, 0x6d, 0x9d, 0x7f, 0x1a, 0x73, 0x2e, 0xac, 0xce, 0x18, 0xf6, 0xa8, 0xa1, 0xda, 0x3a, 0xf7, 0x6a, 0x6b, 0xeb, 0xfc,
0x39, 0xb5, 0xf5, 0x6f, 0x43, 0x89, 0xba, 0x55, 0x75, 0x81, 0x43, 0xde, 0x3a, 0x45, 0x7c, 0x15, 0xcb, 0xa9, 0xad, 0x7f, 0x1b, 0x4a, 0xd4, 0xad, 0xaa, 0x0b, 0x1c, 0xf2, 0xd6, 0x29, 0xe2, 0xab,
0x05, 0xb5, 0xa7, 0xc0, 0x2b, 0xa5, 0x3d, 0xd0, 0xa4, 0x22, 0x7a, 0xe8, 0x94, 0x45, 0xf4, 0x4b, 0x28, 0xa8, 0x3d, 0x05, 0x5e, 0x29, 0xed, 0x81, 0x26, 0x15, 0xd1, 0x43, 0xa7, 0x2c, 0xa2, 0x5f,
0x2d, 0x7c, 0x59, 0xbc, 0x31, 0x95, 0x1e, 0x25, 0x6d, 0x1e, 0xdb, 0x4a, 0x7e, 0xbc, 0x69, 0xf0, 0x6a, 0xe1, 0xcb, 0xe2, 0x8d, 0xa9, 0xf4, 0x28, 0x69, 0xf3, 0xd8, 0x56, 0xf2, 0xe3, 0x4d, 0x83,
0x51, 0x2c, 0xa8, 0xe8, 0xa3, 0x90, 0xcb, 0x96, 0xce, 0xe2, 0xb2, 0x13, 0xe9, 0xee, 0x8a, 0xb6, 0x8f, 0x62, 0x41, 0x45, 0x1f, 0x85, 0x5c, 0xb6, 0x74, 0x16, 0x97, 0x9d, 0x48, 0x77, 0x57, 0xb4,
0x61, 0xde, 0xb4, 0x8c, 0x8e, 0x45, 0x28, 0x5d, 0x26, 0x4a, 0x5b, 0x53, 0x75, 0xe2, 0xae, 0x8f, 0x0d, 0xf3, 0xa6, 0x65, 0x74, 0x2c, 0x42, 0xe9, 0x32, 0x51, 0xda, 0x9a, 0xaa, 0x13, 0x77, 0x7d,
0x53, 0x11, 0x5d, 0x3e, 0x3e, 0xaa, 0xcc, 0x37, 0x92, 0x59, 0x70, 0x9a, 0xac, 0xfc, 0xbc, 0x00, 0x9c, 0x8a, 0xe8, 0xf2, 0xf1, 0x51, 0x65, 0xbe, 0x91, 0xcc, 0x82, 0xd3, 0x64, 0xe5, 0xe7, 0x05,
0x53, 0xd1, 0x0c, 0x98, 0x52, 0xa4, 0x4a, 0x67, 0x2a, 0x52, 0x6f, 0x04, 0x0e, 0x83, 0x53, 0xc1, 0x98, 0x8a, 0x66, 0xc0, 0x94, 0x22, 0x55, 0x3a, 0x53, 0x91, 0x7a, 0x23, 0x70, 0x18, 0x9c, 0x0a,
0x07, 0x5e, 0x70, 0x62, 0x07, 0x62, 0x11, 0x26, 0x45, 0x34, 0x70, 0x89, 0xa2, 0x4c, 0xf7, 0x76, 0x3e, 0xf0, 0x82, 0x13, 0x3b, 0x10, 0x8b, 0x30, 0x29, 0xa2, 0x81, 0x4b, 0x14, 0x65, 0xba, 0xb7,
0x7f, 0x3b, 0x4c, 0xc6, 0x51, 0x7e, 0xf4, 0x10, 0xc6, 0x2d, 0x5e, 0x77, 0xbb, 0x00, 0x4e, 0xed, 0xfb, 0xdb, 0x61, 0x32, 0x8e, 0xf2, 0xa3, 0x87, 0x30, 0x6e, 0xf1, 0xba, 0xdb, 0x05, 0x70, 0x6a,
0x7a, 0x51, 0x00, 0x8c, 0xe3, 0x20, 0x11, 0x87, 0x79, 0x59, 0xdd, 0xea, 0x97, 0xa3, 0x2e, 0x40, 0xd7, 0x8b, 0x02, 0x60, 0x1c, 0x07, 0x89, 0x38, 0xcc, 0xcb, 0xea, 0x56, 0xbf, 0x1c, 0x75, 0x01,
0x21, 0x5c, 0xb7, 0x2e, 0x46, 0x19, 0x70, 0x5c, 0x06, 0xad, 0xc3, 0x4c, 0x4f, 0x8f, 0x43, 0x39, 0x0a, 0xe1, 0xba, 0x75, 0x31, 0xca, 0x80, 0xe3, 0x32, 0x68, 0x1d, 0x66, 0x7a, 0x7a, 0x1c, 0xca,
0xae, 0x7c, 0x59, 0x40, 0xcd, 0x6c, 0xc7, 0x59, 0x70, 0x92, 0x1c, 0xda, 0x0d, 0x95, 0xb2, 0xc3, 0x71, 0xe5, 0xcb, 0x02, 0x6a, 0x66, 0x3b, 0xce, 0x82, 0x93, 0xe4, 0xd0, 0x6e, 0xa8, 0x94, 0x1d,
0x3c, 0x3c, 0xdf, 0xce, 0x7c, 0xf0, 0x32, 0xd7, 0xb2, 0x09, 0xe5, 0x76, 0x29, 0x6b, 0xb9, 0x2d, 0xe6, 0xe1, 0xf9, 0x76, 0xe6, 0x83, 0x97, 0xb9, 0x96, 0x4d, 0x28, 0xb7, 0x4b, 0x59, 0xcb, 0x6d,
0xff, 0x93, 0x14, 0x4c, 0x42, 0x5e, 0x09, 0x3c, 0xe8, 0x95, 0x29, 0x26, 0x11, 0xa8, 0x8e, 0x8c, 0xf9, 0x1f, 0xa5, 0x60, 0x12, 0xf2, 0x4a, 0xe0, 0x41, 0xaf, 0x4c, 0x31, 0x89, 0x40, 0x75, 0x64,
0xe4, 0xea, 0xf7, 0xde, 0xa9, 0xaa, 0x5f, 0x3f, 0x79, 0x0e, 0x2e, 0x7f, 0xbf, 0x90, 0x60, 0x6e, 0x24, 0x57, 0xbf, 0xf7, 0x4e, 0x55, 0xfd, 0xfa, 0xc9, 0x73, 0x70, 0xf9, 0xfb, 0x85, 0x04, 0x73,
0xa5, 0xf9, 0xd8, 0x32, 0x7a, 0xa6, 0x6b, 0xce, 0xa6, 0xe9, 0x2c, 0xcd, 0x2f, 0xa1, 0x60, 0xf5, 0x2b, 0xcd, 0xc7, 0x96, 0xd1, 0x33, 0x5d, 0x73, 0x36, 0x4d, 0x67, 0x69, 0x7e, 0x09, 0x05, 0xab,
0x34, 0x77, 0x1e, 0xaf, 0xb9, 0xf3, 0xc0, 0x3d, 0x8d, 0xcd, 0x63, 0x26, 0x22, 0xe5, 0x4c, 0x82, 0xa7, 0xb9, 0xf3, 0x78, 0xcd, 0x9d, 0x07, 0xee, 0x69, 0x6c, 0x1e, 0x33, 0x11, 0x29, 0x67, 0x12,
0x09, 0xa0, 0x0d, 0x18, 0xb6, 0x14, 0xbd, 0x43, 0xdc, 0xb4, 0x7a, 0x6d, 0x80, 0xf5, 0xab, 0xcb, 0x4c, 0x00, 0x6d, 0xc0, 0xb0, 0xa5, 0xe8, 0x1d, 0xe2, 0xa6, 0xd5, 0x6b, 0x03, 0xac, 0x5f, 0x5d,
0x98, 0xb1, 0x07, 0x0a, 0x1b, 0x2e, 0x8d, 0x05, 0x8a, 0xfc, 0x47, 0x12, 0x4c, 0x3e, 0xd9, 0xda, 0xc6, 0x8c, 0x3d, 0x50, 0xd8, 0x70, 0x69, 0x2c, 0x50, 0xe4, 0x7f, 0x92, 0x60, 0xf2, 0xc9, 0xd6,
0x6a, 0xac, 0xea, 0xfc, 0x44, 0xf3, 0xb7, 0xd5, 0xab, 0x50, 0x30, 0x15, 0x7b, 0x2f, 0x9a, 0xe9, 0x56, 0x63, 0x55, 0xe7, 0x27, 0x9a, 0xbf, 0xad, 0x5e, 0x85, 0x82, 0xa9, 0xd8, 0x7b, 0xd1, 0x4c,
0x19, 0x0d, 0x73, 0x0a, 0xfa, 0x00, 0x8a, 0x2c, 0x92, 0x10, 0xbd, 0x9d, 0xb1, 0xd4, 0x16, 0xf0, 0xcf, 0x68, 0x98, 0x53, 0xd0, 0x1d, 0x28, 0xb1, 0x7f, 0x99, 0x5d, 0xfc, 0x48, 0x8d, 0xf0, 0x40,
0x75, 0x47, 0xc8, 0xaf, 0x9e, 0xc4, 0x00, 0x76, 0xe1, 0xe4, 0x7d, 0x98, 0x0d, 0x98, 0xc3, 0xd6, 0x58, 0x6a, 0x88, 0xb1, 0x17, 0x81, 0xbf, 0xb1, 0xc7, 0x89, 0x3e, 0x80, 0x22, 0x8b, 0x3f, 0x44,
0xe3, 0x29, 0xcb, 0x8e, 0xa8, 0x09, 0x43, 0x4c, 0x33, 0xcb, 0x81, 0xf9, 0x0c, 0x8f, 0x99, 0x91, 0x6f, 0x67, 0x2c, 0xd0, 0x85, 0x51, 0x75, 0x47, 0xc8, 0xaf, 0xb9, 0xc4, 0x00, 0x76, 0xe1, 0xe4,
0x29, 0xf9, 0x95, 0x0e, 0xfb, 0x45, 0xb1, 0x83, 0x25, 0xaf, 0xc3, 0x38, 0x7f, 0x50, 0x36, 0x2c, 0x7d, 0x98, 0x0d, 0x4c, 0x82, 0xad, 0xe2, 0x53, 0x96, 0x53, 0x51, 0x13, 0x86, 0x98, 0x76, 0x96,
0x9b, 0x2f, 0x0b, 0xba, 0x02, 0xf9, 0xae, 0xaa, 0x8b, 0x3c, 0x3b, 0x2a, 0x64, 0xf2, 0x2c, 0x47, 0x39, 0xf3, 0x19, 0x9e, 0x40, 0x23, 0x0b, 0xe1, 0xd7, 0x47, 0xec, 0x17, 0xc5, 0x0e, 0x96, 0xbc,
0xb0, 0x71, 0x4e, 0x56, 0x0e, 0x45, 0xe4, 0xf1, 0xc9, 0xca, 0x21, 0x66, 0xe3, 0xf2, 0x63, 0x28, 0x0e, 0xe3, 0xfc, 0x19, 0xda, 0xb0, 0x6c, 0xbe, 0x98, 0xe8, 0x0a, 0xe4, 0xbb, 0xaa, 0x2e, 0xb2,
0x8a, 0xe5, 0x0e, 0x02, 0xe5, 0x4f, 0x06, 0xca, 0x27, 0x00, 0x6d, 0x42, 0x71, 0xb5, 0x51, 0xd7, 0xf3, 0xa8, 0x90, 0xc9, 0xb3, 0xcc, 0xc2, 0xc6, 0x39, 0x59, 0x39, 0x14, 0xf1, 0xca, 0x27, 0x2b,
0x0c, 0xa7, 0xea, 0x6a, 0xa9, 0x6d, 0x2b, 0xba, 0x17, 0x4b, 0xab, 0xcb, 0x18, 0x73, 0x0a, 0x92, 0x87, 0x98, 0x8d, 0xcb, 0x8f, 0xa1, 0x28, 0x36, 0x29, 0x08, 0x94, 0x3f, 0x19, 0x28, 0x9f, 0x00,
0x61, 0x98, 0x1c, 0xb6, 0x88, 0x69, 0x73, 0x8f, 0x18, 0xa9, 0x03, 0xdb, 0xe5, 0x47, 0x7c, 0x04, 0xb4, 0x09, 0xc5, 0xd5, 0x46, 0x5d, 0x33, 0x9c, 0x5a, 0xad, 0xa5, 0xb6, 0xad, 0xe8, 0x0e, 0x2e,
0x0b, 0x8a, 0xfc, 0xc7, 0x39, 0x28, 0x8a, 0xe5, 0x38, 0x87, 0x5b, 0xd8, 0x5a, 0xe8, 0x16, 0xf6, 0xad, 0x2e, 0x63, 0xcc, 0x29, 0x48, 0x86, 0x61, 0x72, 0xd8, 0x22, 0xa6, 0xcd, 0xfd, 0x68, 0xa4,
0x46, 0x36, 0xd7, 0x48, 0xbd, 0x82, 0x6d, 0x45, 0xae, 0x60, 0x37, 0x32, 0xe2, 0x9d, 0x7c, 0xff, 0x0e, 0xcc, 0x37, 0x1e, 0xf1, 0x11, 0x2c, 0x28, 0xf2, 0x1f, 0xe5, 0xa0, 0x28, 0x96, 0xe3, 0x1c,
0xfa, 0x3b, 0x09, 0x26, 0xc2, 0x4e, 0x89, 0xee, 0xc2, 0x28, 0x4b, 0x38, 0x6a, 0x8b, 0x6c, 0xf8, 0xee, 0x6e, 0x6b, 0xa1, 0xbb, 0xdb, 0x1b, 0xd9, 0x5c, 0x23, 0xf5, 0xe2, 0xb6, 0x15, 0xb9, 0xb8,
0x75, 0xae, 0xf7, 0x08, 0xd3, 0xf4, 0x49, 0x38, 0xc8, 0x87, 0x3a, 0x9e, 0x18, 0xf3, 0x23, 0x31, 0xdd, 0xc8, 0x88, 0x77, 0xf2, 0xad, 0xed, 0x6f, 0x25, 0x98, 0x08, 0x3b, 0x25, 0xba, 0x0b, 0xa3,
0xe9, 0xf4, 0x25, 0xed, 0xd9, 0xaa, 0x56, 0x75, 0x3e, 0xad, 0x54, 0x57, 0x75, 0x7b, 0xd3, 0x6a, 0x2c, 0x4d, 0xa9, 0x2d, 0xb2, 0xe1, 0x57, 0xc7, 0xde, 0xd3, 0x4d, 0xd3, 0x27, 0xe1, 0x20, 0x1f,
0xda, 0x96, 0xaa, 0x77, 0x62, 0x8a, 0xb8, 0x53, 0x06, 0x91, 0xe5, 0x7f, 0x90, 0x60, 0x54, 0x98, 0xea, 0x78, 0x62, 0xcc, 0x8f, 0xc4, 0xa4, 0xd3, 0x97, 0xb4, 0x67, 0xab, 0x5a, 0xd5, 0xf9, 0x20,
0x7c, 0x0e, 0xb7, 0x8a, 0xdf, 0x08, 0xdf, 0x2a, 0xae, 0x65, 0x3c, 0xe0, 0xc9, 0x57, 0x8a, 0xbf, 0x53, 0x5d, 0xd5, 0xed, 0x4d, 0xab, 0x69, 0x5b, 0xaa, 0xde, 0x89, 0x29, 0xe2, 0x4e, 0x19, 0x44,
0xf2, 0x4d, 0x67, 0x47, 0x9a, 0x79, 0xf5, 0x9e, 0x41, 0xed, 0xa8, 0x57, 0xb3, 0xc3, 0x88, 0x39, 0x96, 0xff, 0x5e, 0x82, 0x51, 0x61, 0xf2, 0x39, 0xdc, 0x45, 0x7e, 0x23, 0x7c, 0x17, 0xb9, 0x96,
0x05, 0xf5, 0x60, 0x4a, 0x8d, 0xc4, 0x00, 0xb1, 0xb4, 0xb5, 0x6c, 0x96, 0x78, 0x62, 0xf5, 0xb2, 0xf1, 0x80, 0x27, 0x5f, 0x44, 0xfe, 0xd2, 0x37, 0x9d, 0x1d, 0x69, 0xe6, 0xd5, 0x7b, 0x06, 0xb5,
0x80, 0x9f, 0x8a, 0x52, 0x70, 0x4c, 0x85, 0x4c, 0x20, 0xc6, 0x85, 0xde, 0x87, 0xc2, 0x9e, 0x6d, 0xa3, 0x5e, 0xcd, 0x0e, 0x23, 0xe6, 0x14, 0xd4, 0x83, 0x29, 0x35, 0x12, 0x03, 0xc4, 0xd2, 0xd6,
0x9b, 0x09, 0xef, 0xd5, 0x03, 0x22, 0x8f, 0x6f, 0x42, 0x89, 0xcf, 0x6e, 0x6b, 0xab, 0x81, 0x39, 0xb2, 0x59, 0xe2, 0x89, 0xd5, 0xcb, 0x02, 0x7e, 0x2a, 0x4a, 0xc1, 0x31, 0x15, 0x32, 0x81, 0x18,
0x94, 0xfc, 0x8f, 0x39, 0x6f, 0x3d, 0x78, 0x91, 0xff, 0xae, 0x37, 0xdb, 0x25, 0x4d, 0xa1, 0x94, 0x17, 0x7a, 0x1f, 0x0a, 0x7b, 0xb6, 0x6d, 0x26, 0xbc, 0x72, 0x0f, 0x88, 0x3c, 0xbe, 0x09, 0x25,
0xfb, 0x9f, 0x73, 0x21, 0x9d, 0x0d, 0x18, 0xee, 0xd1, 0x70, 0x8c, 0x1b, 0x6d, 0xf9, 0x11, 0x59, 0x3e, 0xbb, 0xad, 0xad, 0x06, 0xe6, 0x50, 0xf2, 0x3f, 0xe4, 0xbc, 0xf5, 0xe0, 0x57, 0x83, 0x77,
0x3a, 0x4b, 0x44, 0x1e, 0x4d, 0x8a, 0xc6, 0xe8, 0x09, 0xe4, 0x6d, 0x2d, 0xeb, 0xc5, 0x52, 0x20, 0xbd, 0xd9, 0x2e, 0x69, 0x0a, 0xa5, 0xdc, 0xff, 0x9c, 0x6b, 0xec, 0x6c, 0xc0, 0x70, 0x8f, 0x86,
0x6e, 0xad, 0x35, 0xfd, 0x90, 0xb6, 0xb5, 0xd6, 0xc4, 0x0c, 0x02, 0x6d, 0xc2, 0x10, 0xcb, 0x5f, 0x63, 0xdc, 0x68, 0xcb, 0x8f, 0xc8, 0xd2, 0x59, 0x22, 0xf2, 0x68, 0x52, 0x34, 0x46, 0x4f, 0x20,
0xec, 0x10, 0xe7, 0xb3, 0x07, 0x05, 0xb6, 0x82, 0xbe, 0x4b, 0xb1, 0x5f, 0x14, 0x3b, 0x38, 0xf2, 0x6f, 0x6b, 0x59, 0xaf, 0xa3, 0x02, 0x71, 0x6b, 0xad, 0xe9, 0x87, 0xb4, 0xad, 0xb5, 0x26, 0x66,
0xa7, 0x30, 0x1e, 0x3a, 0xe9, 0xe8, 0x13, 0x18, 0xd3, 0x0c, 0xa5, 0x5d, 0x57, 0x34, 0x45, 0x6f, 0x10, 0x68, 0x13, 0x86, 0x58, 0xd6, 0x63, 0x87, 0x38, 0x9f, 0x3d, 0x28, 0xb0, 0x15, 0xf4, 0x5d,
0x11, 0xf7, 0xf3, 0xc2, 0xb5, 0xa4, 0x3b, 0xca, 0x5a, 0x80, 0x4f, 0xc4, 0x89, 0x59, 0xa1, 0x64, 0x8a, 0xfd, 0xa2, 0xd8, 0xc1, 0x91, 0x3f, 0x85, 0xf1, 0xd0, 0x49, 0x47, 0x9f, 0xc0, 0x98, 0x66,
0x2c, 0x48, 0xc3, 0x21, 0x44, 0x59, 0x01, 0xf0, 0xe7, 0x88, 0x2a, 0x30, 0xc4, 0x3c, 0xd5, 0xc9, 0x28, 0xed, 0xba, 0xa2, 0x29, 0x7a, 0x8b, 0xb8, 0x1f, 0x25, 0xae, 0x25, 0xdd, 0x6c, 0xd6, 0x02,
0x48, 0x23, 0xf5, 0x11, 0x66, 0x21, 0x73, 0x60, 0x8a, 0x9d, 0x71, 0x74, 0x1b, 0x80, 0x92, 0x96, 0x7c, 0x22, 0x4e, 0xcc, 0x0a, 0x25, 0x63, 0x41, 0x1a, 0x0e, 0x21, 0xca, 0x0a, 0x80, 0x3f, 0x47,
0x45, 0x6c, 0xbe, 0x9d, 0xb9, 0xf0, 0x27, 0xca, 0xa6, 0x47, 0xc1, 0x01, 0x2e, 0xf9, 0x9f, 0x25, 0x54, 0x81, 0x21, 0xe6, 0xa9, 0x4e, 0x46, 0x1a, 0xa9, 0x8f, 0x30, 0x0b, 0x99, 0x03, 0x53, 0xec,
0x18, 0xdf, 0x20, 0xf6, 0x67, 0x86, 0xb5, 0xdf, 0x30, 0x34, 0xb5, 0xd5, 0x3f, 0x87, 0x70, 0x8d, 0x8c, 0xa3, 0xdb, 0x00, 0x94, 0xb4, 0x2c, 0x62, 0xf3, 0xed, 0xcc, 0x85, 0x3f, 0x6c, 0x36, 0x3d,
0x43, 0xe1, 0xfa, 0xcd, 0x01, 0x3b, 0x13, 0xb2, 0x2e, 0x2d, 0x68, 0xcb, 0x5f, 0x49, 0x30, 0x1f, 0x0a, 0x0e, 0x70, 0xc9, 0xff, 0x2c, 0xc1, 0xf8, 0x06, 0xb1, 0x3f, 0x33, 0xac, 0xfd, 0x86, 0xa1,
0xe2, 0x7c, 0xe4, 0x1f, 0xfe, 0x6d, 0x18, 0x32, 0x0d, 0xcb, 0x76, 0x53, 0xf9, 0xa9, 0x14, 0xb2, 0xa9, 0xad, 0xfe, 0x39, 0x84, 0x6b, 0x1c, 0x0a, 0xd7, 0x6f, 0x0e, 0xd8, 0x99, 0x90, 0x75, 0x69,
0x40, 0x18, 0x48, 0xe6, 0x0c, 0x06, 0x3b, 0x68, 0x68, 0x0d, 0x72, 0xb6, 0x21, 0x5c, 0xf5, 0x74, 0x41, 0x5b, 0xfe, 0x4a, 0x82, 0xf9, 0x10, 0xe7, 0x23, 0xff, 0xf0, 0x6f, 0xc3, 0x90, 0x69, 0x58,
0x98, 0x84, 0x58, 0x75, 0x10, 0x98, 0xb9, 0x2d, 0x03, 0xe7, 0x6c, 0x83, 0x6d, 0x44, 0x39, 0xc4, 0xb6, 0x9b, 0xca, 0x4f, 0xa5, 0x90, 0x05, 0xc2, 0x40, 0x32, 0x67, 0x30, 0xd8, 0x41, 0x43, 0x6b,
0x15, 0x0c, 0x5f, 0xaf, 0x68, 0x06, 0x18, 0x0a, 0xbb, 0x96, 0xd1, 0x3d, 0xf3, 0x1c, 0xbc, 0x8d, 0x90, 0xb3, 0x0d, 0xe1, 0xaa, 0xa7, 0xc3, 0x24, 0xc4, 0xaa, 0x83, 0xc0, 0xcc, 0x6d, 0x19, 0x38,
0x58, 0xb1, 0x8c, 0x2e, 0xe6, 0x58, 0xf2, 0xd7, 0x12, 0x4c, 0x87, 0x38, 0xcf, 0x21, 0x75, 0xbc, 0x67, 0x1b, 0x6c, 0x23, 0xca, 0x21, 0xae, 0x60, 0xf8, 0x7a, 0x45, 0x33, 0xc0, 0x50, 0xd8, 0xb5,
0x1f, 0x4e, 0x1d, 0x37, 0x4e, 0x33, 0x91, 0x94, 0x04, 0xf2, 0x75, 0x2e, 0x32, 0x0d, 0x36, 0x61, 0x8c, 0xee, 0x99, 0xe7, 0xe0, 0x6d, 0xc4, 0x8a, 0x65, 0x74, 0x31, 0xc7, 0x92, 0xbf, 0x96, 0x60,
0xb4, 0x0b, 0xa3, 0xa6, 0xd1, 0x6e, 0xbe, 0x84, 0x0f, 0x8a, 0x93, 0x2c, 0xf3, 0x36, 0x7c, 0x2c, 0x3a, 0xc4, 0x79, 0x0e, 0xa9, 0xe3, 0xfd, 0x70, 0xea, 0xb8, 0x71, 0x9a, 0x89, 0xa4, 0x24, 0x90,
0x1c, 0x04, 0x46, 0x87, 0x30, 0xad, 0x2b, 0x5d, 0x42, 0x4d, 0xa5, 0x45, 0x9a, 0x2f, 0xe1, 0x89, 0xaf, 0x73, 0x91, 0x69, 0xb0, 0x09, 0xa3, 0x5d, 0x18, 0x35, 0x8d, 0x76, 0xf3, 0x25, 0x7c, 0x86,
0xe5, 0x22, 0xff, 0x62, 0x11, 0x45, 0xc4, 0x71, 0x25, 0x68, 0x1d, 0x8a, 0xaa, 0xc9, 0x2b, 0x41, 0x9c, 0x64, 0x99, 0xb7, 0xe1, 0x63, 0xe1, 0x20, 0x30, 0x3a, 0x84, 0x69, 0x5d, 0xe9, 0x12, 0x6a,
0x51, 0xfd, 0x0c, 0xcc, 0xc3, 0x4e, 0xdd, 0xe8, 0xc4, 0x73, 0xf1, 0x03, 0xbb, 0x18, 0xf2, 0x5f, 0x2a, 0x2d, 0xd2, 0x7c, 0x09, 0x0f, 0x33, 0x17, 0xf9, 0x77, 0x8e, 0x28, 0x22, 0x8e, 0x2b, 0x41,
0x47, 0xbd, 0x81, 0xf9, 0x1f, 0x7a, 0x0c, 0x25, 0xde, 0xda, 0xd1, 0x32, 0x34, 0xf7, 0xdb, 0x02, 0xeb, 0x50, 0x54, 0x4d, 0x5e, 0x09, 0x8a, 0xea, 0x67, 0x60, 0x1e, 0x76, 0xea, 0x46, 0x27, 0x9e,
0xdb, 0xd9, 0x86, 0x18, 0x7b, 0x71, 0x54, 0xb9, 0x9c, 0xf0, 0x6c, 0xec, 0x92, 0xb1, 0x27, 0x8c, 0x8b, 0x1f, 0xd8, 0xc5, 0x90, 0xff, 0x2a, 0xea, 0x0d, 0xcc, 0xff, 0xd0, 0x63, 0x28, 0xf1, 0x86,
0x36, 0xa0, 0x60, 0xfe, 0x98, 0x1a, 0x88, 0xa7, 0x49, 0x5e, 0xf8, 0x70, 0x1c, 0xf9, 0xf7, 0xf2, 0x90, 0x96, 0xa1, 0xb9, 0x5f, 0x24, 0xf8, 0x1d, 0x40, 0x8c, 0xbd, 0x38, 0xaa, 0x5c, 0x4e, 0x78,
0x11, 0x73, 0x79, 0xb2, 0x7c, 0xf6, 0xd2, 0x76, 0xdd, 0xab, 0xb9, 0x52, 0x77, 0x7e, 0x07, 0x8a, 0x6c, 0x76, 0xc9, 0xd8, 0x13, 0x46, 0x1b, 0x50, 0x30, 0x7f, 0x4c, 0x0d, 0xc4, 0xd3, 0x24, 0x2f,
0x22, 0xd5, 0x0a, 0x67, 0xfe, 0xe5, 0x69, 0x9c, 0x39, 0x98, 0xc5, 0xbc, 0x2b, 0x8f, 0x3b, 0xe8, 0x7c, 0x38, 0x8e, 0xfc, 0x7b, 0xf9, 0x88, 0xb9, 0x3c, 0x59, 0x3e, 0x7b, 0x69, 0xbb, 0xee, 0xd5,
0x02, 0xa3, 0x8f, 0x61, 0x98, 0x38, 0x2a, 0x9c, 0xdc, 0x78, 0xef, 0x34, 0x2a, 0xfc, 0xb8, 0xea, 0x5c, 0xa9, 0x3b, 0xbf, 0x03, 0x45, 0x91, 0x6a, 0x85, 0x33, 0xff, 0xf2, 0x34, 0xce, 0x1c, 0xcc,
0x97, 0xba, 0x62, 0x4c, 0xa0, 0xa2, 0x77, 0xd8, 0x7a, 0x31, 0x5e, 0x76, 0x8d, 0xa4, 0xe5, 0x02, 0x62, 0xde, 0x95, 0xc7, 0x1d, 0x74, 0x81, 0xd1, 0xc7, 0x30, 0x4c, 0x1c, 0x15, 0x4e, 0x6e, 0xbc,
0x4f, 0x57, 0x57, 0x9c, 0x69, 0x7b, 0xc3, 0x2f, 0x8e, 0x2a, 0xe0, 0xff, 0xc4, 0x41, 0x09, 0xf9, 0x77, 0x1a, 0x15, 0x7e, 0x5c, 0xf5, 0x4b, 0x5d, 0x31, 0x26, 0x50, 0xd1, 0x3b, 0x6c, 0xbd, 0x18,
0x5f, 0x25, 0x98, 0xe6, 0x2b, 0xd4, 0xea, 0x59, 0xaa, 0xdd, 0x3f, 0xb7, 0xc4, 0xf4, 0x34, 0x94, 0x2f, 0xbb, 0xba, 0xd1, 0x72, 0x81, 0xa7, 0xab, 0x2b, 0xce, 0xb4, 0xbd, 0xe1, 0x17, 0x47, 0x15,
0x98, 0xee, 0x0c, 0x58, 0x96, 0x98, 0x85, 0xa9, 0xc9, 0xe9, 0x1b, 0x09, 0x2e, 0xc6, 0xb8, 0xcf, 0xf0, 0x7f, 0xe2, 0xa0, 0x84, 0xfc, 0xaf, 0x12, 0x4c, 0xf3, 0x15, 0x6a, 0xf5, 0x2c, 0xd5, 0xee,
0x21, 0x2e, 0x6e, 0x87, 0xe3, 0xe2, 0x9b, 0xa7, 0x9d, 0x50, 0x4a, 0x6c, 0xfc, 0xef, 0xe9, 0x84, 0x9f, 0x5b, 0x62, 0x7a, 0x1a, 0x4a, 0x4c, 0x77, 0x06, 0x2c, 0x4b, 0xcc, 0xc2, 0xd4, 0xe4, 0xf4,
0xe9, 0xf0, 0x93, 0x72, 0x1b, 0xc0, 0xb4, 0xd4, 0x03, 0x55, 0x23, 0x1d, 0xf1, 0x19, 0xbd, 0x14, 0x8d, 0x04, 0x17, 0x63, 0xdc, 0xe7, 0x10, 0x17, 0xb7, 0xc3, 0x71, 0xf1, 0xcd, 0xd3, 0x4e, 0x28,
0x68, 0x92, 0xf2, 0x28, 0x38, 0xc0, 0x85, 0x28, 0xcc, 0xb5, 0xc9, 0xae, 0xd2, 0xd3, 0xec, 0xc5, 0x25, 0x36, 0xfe, 0xf7, 0x74, 0xc2, 0x74, 0xf8, 0x49, 0xb9, 0x0d, 0x60, 0x5a, 0xea, 0x81, 0xaa,
0x76, 0x7b, 0x49, 0x31, 0x95, 0x1d, 0x55, 0x53, 0x6d, 0x55, 0x3c, 0x38, 0x8c, 0xd4, 0x1f, 0x3a, 0x91, 0x8e, 0xf8, 0xf8, 0x5e, 0x0a, 0xb4, 0x56, 0x79, 0x14, 0x1c, 0xe0, 0x42, 0x14, 0xe6, 0xda,
0x9f, 0xb7, 0x93, 0x38, 0x5e, 0x1c, 0x55, 0xae, 0x24, 0x7d, 0x5f, 0x72, 0x59, 0xfa, 0x38, 0x05, 0x64, 0x57, 0xe9, 0x69, 0xf6, 0x62, 0xbb, 0xbd, 0xa4, 0x98, 0xca, 0x8e, 0xaa, 0xa9, 0xb6, 0x2a,
0x1a, 0xf5, 0xa1, 0x6c, 0x91, 0x4f, 0x7b, 0xaa, 0x45, 0xda, 0xcb, 0x96, 0x61, 0x86, 0xd4, 0xe6, 0x9e, 0x29, 0x46, 0xea, 0x0f, 0x9d, 0x8f, 0xe2, 0x49, 0x1c, 0x2f, 0x8e, 0x2a, 0x57, 0x92, 0xbe,
0xb9, 0xda, 0x5f, 0x3f, 0x3e, 0xaa, 0x94, 0x71, 0x0a, 0xcf, 0x60, 0xc5, 0xa9, 0xf0, 0xe8, 0x19, 0x4a, 0xb9, 0x2c, 0x7d, 0x9c, 0x02, 0x8d, 0xfa, 0x50, 0xb6, 0xc8, 0xa7, 0x3d, 0xd5, 0x22, 0xed,
0xcc, 0x28, 0xa2, 0x9d, 0x2d, 0xa8, 0xd5, 0x39, 0x25, 0xf7, 0x8f, 0x8f, 0x2a, 0x33, 0x8b, 0x71, 0x65, 0xcb, 0x30, 0x43, 0x6a, 0xf3, 0x5c, 0xed, 0xaf, 0x1f, 0x1f, 0x55, 0xca, 0x38, 0x85, 0x67,
0xf2, 0x60, 0x85, 0x49, 0xa0, 0xa8, 0x06, 0xc5, 0x03, 0xde, 0xf9, 0x46, 0xcb, 0x43, 0x1c, 0x9f, 0xb0, 0xe2, 0x54, 0x78, 0xf4, 0x0c, 0x66, 0x14, 0xd1, 0x04, 0x17, 0xd4, 0xea, 0x9c, 0x92, 0xfb,
0x25, 0x82, 0xa2, 0xd3, 0x0c, 0xc7, 0x30, 0x87, 0x57, 0x9a, 0xfc, 0xf4, 0xb9, 0x5c, 0xec, 0x4a, 0xc7, 0x47, 0x95, 0x99, 0xc5, 0x38, 0x79, 0xb0, 0xc2, 0x24, 0x50, 0x54, 0x83, 0xe2, 0x01, 0xef,
0xca, 0x6a, 0x49, 0x71, 0xe2, 0xf9, 0x9b, 0x73, 0xc9, 0x8f, 0x5a, 0x4f, 0x7c, 0x12, 0x0e, 0xf2, 0x97, 0xa3, 0xe5, 0x21, 0x8e, 0xcf, 0x12, 0x41, 0xd1, 0x69, 0xa1, 0x63, 0x98, 0xc3, 0x2b, 0x4d,
0xa1, 0x8f, 0x60, 0x64, 0x4f, 0xbc, 0x6b, 0xd0, 0x72, 0x31, 0x53, 0x12, 0x0e, 0xbd, 0x83, 0xd4, 0x7e, 0xfa, 0x5c, 0x2e, 0x76, 0x25, 0x65, 0xb5, 0xa4, 0x38, 0xf1, 0xfc, 0xa5, 0xba, 0xe4, 0x47,
0xa7, 0x85, 0x8a, 0x11, 0x77, 0x98, 0x62, 0x1f, 0x11, 0xbd, 0x0e, 0x45, 0xfe, 0x63, 0x75, 0x99, 0xad, 0x27, 0x3e, 0x09, 0x07, 0xf9, 0xd0, 0x47, 0x30, 0xb2, 0x27, 0xde, 0x35, 0x68, 0xb9, 0x98,
0x3f, 0xe8, 0x95, 0xfc, 0xd8, 0xf6, 0xc4, 0x19, 0xc6, 0x2e, 0xdd, 0x65, 0x5d, 0x6d, 0x2c, 0xf1, 0x29, 0x09, 0x87, 0xde, 0x41, 0xea, 0xd3, 0x42, 0xc5, 0x88, 0x3b, 0x4c, 0xb1, 0x8f, 0x88, 0x5e,
0x87, 0xe5, 0x08, 0xeb, 0x6a, 0x63, 0x09, 0xbb, 0x74, 0xf4, 0x09, 0x14, 0x29, 0x59, 0x53, 0xf5, 0x87, 0x22, 0xff, 0xb1, 0xba, 0xcc, 0x9f, 0x01, 0x4b, 0x7e, 0x6c, 0x7b, 0xe2, 0x0c, 0x63, 0x97,
0xde, 0x61, 0x19, 0x32, 0x7d, 0x96, 0x6e, 0x3e, 0xe2, 0xdc, 0x91, 0xa7, 0x35, 0x5f, 0x83, 0xa0, 0xee, 0xb2, 0xae, 0x36, 0x96, 0xf8, 0x73, 0x74, 0x84, 0x75, 0xb5, 0xb1, 0x84, 0x5d, 0x3a, 0xfa,
0x63, 0x17, 0x16, 0xed, 0xc1, 0x88, 0xd5, 0xd3, 0x17, 0xe9, 0x36, 0x25, 0x56, 0x79, 0x94, 0xeb, 0x04, 0x8a, 0x94, 0xac, 0xa9, 0x7a, 0xef, 0xb0, 0x0c, 0x99, 0x3e, 0x66, 0x37, 0x1f, 0x71, 0xee,
0x18, 0x14, 0xce, 0xb1, 0xcb, 0x1f, 0xd5, 0xe2, 0xad, 0x90, 0xc7, 0x81, 0x7d, 0x70, 0xb4, 0x07, 0xc8, 0x83, 0x9c, 0xaf, 0x41, 0xd0, 0xb1, 0x0b, 0x8b, 0xf6, 0x60, 0xc4, 0xea, 0xe9, 0x8b, 0x74,
0xc0, 0x7f, 0xf0, 0x57, 0xbc, 0xf2, 0x1c, 0x57, 0x75, 0x3f, 0x8b, 0xaa, 0xa4, 0xc7, 0x42, 0xf1, 0x9b, 0x12, 0xab, 0x3c, 0xca, 0x75, 0x0c, 0x0a, 0xe7, 0xd8, 0xe5, 0x8f, 0x6a, 0xf1, 0x56, 0xc8,
0x92, 0xef, 0x91, 0x71, 0x00, 0x1b, 0xfd, 0xa1, 0x04, 0x88, 0xf6, 0x4c, 0x53, 0x23, 0x5d, 0xa2, 0xe3, 0xc0, 0x3e, 0x38, 0xda, 0x03, 0xe0, 0x3f, 0xf8, 0xdb, 0x5f, 0x79, 0x8e, 0xab, 0xba, 0x9f,
0xdb, 0x8a, 0xc6, 0x47, 0x69, 0x79, 0x8c, 0xab, 0x7c, 0x77, 0xd0, 0x0a, 0xc6, 0x04, 0xa3, 0xaa, 0x45, 0x55, 0xd2, 0x13, 0xa3, 0x78, 0xff, 0xf7, 0xc8, 0x38, 0x80, 0x8d, 0xfe, 0x50, 0x02, 0x44,
0xbd, 0x07, 0xfa, 0x38, 0x2b, 0x4e, 0xd0, 0xcb, 0x36, 0x71, 0x57, 0xcc, 0x7a, 0x3c, 0xd3, 0x26, 0x7b, 0xa6, 0xa9, 0x91, 0x2e, 0xd1, 0x6d, 0x45, 0xe3, 0xa3, 0xb4, 0x3c, 0xc6, 0x55, 0xbe, 0x3b,
0x26, 0xbf, 0x8f, 0xfa, 0x9b, 0x28, 0xe8, 0xd8, 0x85, 0x45, 0x4f, 0x61, 0xce, 0x6d, 0xd1, 0xc4, 0x68, 0x05, 0x63, 0x82, 0x51, 0xd5, 0xde, 0xb3, 0x7e, 0x9c, 0x15, 0x27, 0xe8, 0x65, 0x9b, 0xb8,
0x86, 0x61, 0xaf, 0xa8, 0x1a, 0xa1, 0x7d, 0x6a, 0x93, 0x6e, 0x79, 0x82, 0x3b, 0x98, 0xd7, 0xa7, 0x2b, 0x66, 0x3d, 0x9e, 0x69, 0x13, 0x93, 0x5f, 0x55, 0xfd, 0x4d, 0x14, 0x74, 0xec, 0xc2, 0xa2,
0x82, 0x13, 0xb9, 0x70, 0x8a, 0x34, 0xea, 0x42, 0xc5, 0x0d, 0x4e, 0xec, 0xe4, 0x7a, 0xd1, 0xf1, 0xa7, 0x30, 0xe7, 0x36, 0x76, 0x62, 0xc3, 0xb0, 0x57, 0x54, 0x8d, 0xd0, 0x3e, 0xb5, 0x49, 0xb7,
0x11, 0x6d, 0x29, 0x9a, 0xf3, 0xcd, 0x62, 0x92, 0x2b, 0x78, 0xed, 0xf8, 0xa8, 0x52, 0x59, 0x3e, 0x3c, 0xc1, 0x1d, 0xcc, 0xeb, 0x6e, 0xc1, 0x89, 0x5c, 0x38, 0x45, 0x1a, 0x75, 0xa1, 0xe2, 0x06,
0x99, 0x15, 0x0f, 0xc2, 0x42, 0x1f, 0x40, 0x59, 0x49, 0xd3, 0x33, 0xc5, 0xf5, 0xfc, 0x9c, 0x45, 0x27, 0x76, 0x72, 0xbd, 0xe8, 0xf8, 0x88, 0xb6, 0x14, 0xcd, 0xf9, 0xd2, 0x31, 0xc9, 0x15, 0xbc,
0xbc, 0x54, 0x05, 0xa9, 0xd2, 0xc8, 0x86, 0x29, 0x25, 0xdc, 0x2c, 0x4b, 0xcb, 0xd3, 0x99, 0x1e, 0x76, 0x7c, 0x54, 0xa9, 0x2c, 0x9f, 0xcc, 0x8a, 0x07, 0x61, 0xa1, 0x0f, 0xa0, 0xac, 0xa4, 0xe9,
0x4d, 0x23, 0x3d, 0xb6, 0xfe, 0xc3, 0x49, 0x84, 0x40, 0x71, 0x4c, 0x03, 0xfa, 0x1d, 0x40, 0x4a, 0x99, 0xe2, 0x7a, 0x7e, 0xce, 0x22, 0x5e, 0xaa, 0x82, 0x54, 0x69, 0x64, 0xc3, 0x94, 0x12, 0x6e,
0xb4, 0xbf, 0x97, 0x96, 0x51, 0xa6, 0x44, 0x17, 0x6b, 0x0c, 0xf6, 0xdd, 0x2e, 0x46, 0xa2, 0x38, 0xb1, 0xa5, 0xe5, 0xe9, 0x4c, 0x8f, 0xa6, 0x91, 0xce, 0x5c, 0xff, 0xe1, 0x24, 0x42, 0xa0, 0x38,
0x41, 0x0f, 0x2b, 0xd0, 0x95, 0x48, 0x4f, 0x32, 0x2d, 0xcf, 0x73, 0xe5, 0xb5, 0x6c, 0xca, 0x3d, 0xa6, 0x01, 0xfd, 0x0e, 0x20, 0x25, 0xda, 0x15, 0x4c, 0xcb, 0x28, 0x53, 0xa2, 0x8b, 0xb5, 0x13,
0xb9, 0xc0, 0xa7, 0x99, 0x28, 0x22, 0x8e, 0x2b, 0x41, 0x6b, 0x30, 0x2b, 0x06, 0xb7, 0x75, 0xaa, 0xfb, 0x6e, 0x17, 0x23, 0x51, 0x9c, 0xa0, 0x87, 0x15, 0xe8, 0x4a, 0xa4, 0x93, 0x99, 0x96, 0xe7,
0xec, 0x92, 0x66, 0x9f, 0xb6, 0x6c, 0x8d, 0x96, 0x67, 0x78, 0x7c, 0xe7, 0x9f, 0x07, 0x17, 0x13, 0xb9, 0xf2, 0x5a, 0x36, 0xe5, 0x9e, 0x5c, 0xe0, 0x83, 0x4e, 0x14, 0x11, 0xc7, 0x95, 0xa0, 0x35,
0xe8, 0x38, 0x51, 0x0a, 0xbd, 0x0b, 0x53, 0xbb, 0x86, 0xb5, 0xa3, 0xb6, 0xdb, 0x44, 0x77, 0x91, 0x98, 0x15, 0x83, 0xdb, 0x3a, 0x55, 0x76, 0x49, 0xb3, 0x4f, 0x5b, 0xb6, 0x46, 0xcb, 0x33, 0x3c,
0x66, 0x39, 0x12, 0x7f, 0x07, 0x5a, 0x89, 0xd0, 0x70, 0x8c, 0x1b, 0x51, 0xb8, 0x28, 0x90, 0x1b, 0xbe, 0xf3, 0x8f, 0x8a, 0x8b, 0x09, 0x74, 0x9c, 0x28, 0x85, 0xde, 0x85, 0xa9, 0x5d, 0xc3, 0xda,
0x96, 0xd1, 0x5a, 0x37, 0x7a, 0xba, 0xed, 0x94, 0x7d, 0x17, 0xbd, 0x34, 0x7a, 0x71, 0x31, 0x89, 0x51, 0xdb, 0x6d, 0xa2, 0xbb, 0x48, 0xb3, 0x1c, 0x89, 0xbf, 0x03, 0xad, 0x44, 0x68, 0x38, 0xc6,
0xe1, 0xc5, 0x51, 0xe5, 0x6a, 0x72, 0x95, 0xef, 0x33, 0xe1, 0x64, 0x6c, 0x64, 0xc2, 0x98, 0xe8, 0x8d, 0x28, 0x5c, 0x14, 0xc8, 0x0d, 0xcb, 0x68, 0xad, 0x1b, 0x3d, 0xdd, 0x76, 0xca, 0xbe, 0x8b,
0x34, 0xe7, 0x0f, 0x52, 0xe5, 0x32, 0x3f, 0xfa, 0x0f, 0x06, 0x07, 0x3c, 0x4f, 0x24, 0x7a, 0xfe, 0x5e, 0x1a, 0xbd, 0xb8, 0x98, 0xc4, 0xf0, 0xe2, 0xa8, 0x72, 0x35, 0xb9, 0xca, 0xf7, 0x99, 0x70,
0xa7, 0x8e, 0x8f, 0x2a, 0x63, 0x41, 0x06, 0x1c, 0xd2, 0xc0, 0x3b, 0x8b, 0xc4, 0xf7, 0xac, 0xf3, 0x32, 0x36, 0x32, 0x61, 0x4c, 0xf4, 0xa7, 0xf3, 0x07, 0xa9, 0x72, 0x99, 0x1f, 0xfd, 0x07, 0x83,
0xe9, 0xce, 0x3e, 0x5d, 0x67, 0x91, 0x6f, 0xda, 0x4b, 0xeb, 0x2c, 0x0a, 0x40, 0x9e, 0xfc, 0xb2, 0x03, 0x9e, 0x27, 0x12, 0x3d, 0xff, 0x53, 0xc7, 0x47, 0x95, 0xb1, 0x20, 0x03, 0x0e, 0x69, 0xe0,
0xfd, 0x5f, 0x39, 0x98, 0xf1, 0x99, 0x33, 0x77, 0x16, 0x25, 0x88, 0xfc, 0x7f, 0x87, 0x76, 0xb6, 0xfd, 0x48, 0xe2, 0x2b, 0xd8, 0xf9, 0xf4, 0x74, 0x9f, 0xae, 0x1f, 0xc9, 0x37, 0xed, 0xa5, 0xf5,
0x6e, 0x1f, 0x7f, 0xe9, 0xfe, 0xef, 0x75, 0xfb, 0xf8, 0xb6, 0xa5, 0xdc, 0x1e, 0xfe, 0x36, 0x17, 0x23, 0x05, 0x20, 0x4f, 0x7e, 0xd9, 0xfe, 0xaf, 0x1c, 0xcc, 0xf8, 0xcc, 0x99, 0xfb, 0x91, 0x12,
0x9c, 0xc0, 0x29, 0x5b, 0x4e, 0x5e, 0x42, 0x93, 0xf2, 0x4f, 0xae, 0x6b, 0x45, 0xfe, 0x26, 0x0f, 0x44, 0xfe, 0xbf, 0xaf, 0x3b, 0x5b, 0x8f, 0x90, 0xbf, 0x74, 0xff, 0xf7, 0x7a, 0x84, 0x7c, 0xdb,
0x53, 0xd1, 0xd3, 0x18, 0xea, 0x4c, 0x90, 0x06, 0x76, 0x26, 0x34, 0x60, 0x76, 0xb7, 0xa7, 0x69, 0x52, 0x6e, 0x0f, 0x7f, 0x93, 0x0b, 0x4e, 0xe0, 0x94, 0x8d, 0x2a, 0x2f, 0xa1, 0xb5, 0xf9, 0x27,
0x7d, 0x3e, 0x87, 0x40, 0x7b, 0x82, 0xf3, 0x65, 0xf1, 0xe7, 0x42, 0x72, 0x76, 0x25, 0x81, 0x07, 0xd7, 0xeb, 0x22, 0x7f, 0x93, 0x87, 0xa9, 0xe8, 0x69, 0x0c, 0xf5, 0x33, 0x48, 0x03, 0xfb, 0x19,
0x27, 0x4a, 0xc6, 0x1b, 0x15, 0x0a, 0x3f, 0xb6, 0x51, 0x61, 0xe8, 0x0c, 0x8d, 0x0a, 0xc9, 0xbd, 0x1a, 0x30, 0xbb, 0xdb, 0xd3, 0xb4, 0x3e, 0x9f, 0x43, 0xa0, 0xa9, 0xc1, 0xf9, 0xb2, 0xf8, 0x73,
0x1e, 0xf9, 0x33, 0xf5, 0x7a, 0x9c, 0xa5, 0x4b, 0x21, 0x21, 0x88, 0x0d, 0xec, 0xb8, 0x7d, 0x1b, 0x21, 0x39, 0xbb, 0x92, 0xc0, 0x83, 0x13, 0x25, 0xe3, 0xed, 0x0d, 0x85, 0x1f, 0xdb, 0xde, 0x30,
0x26, 0xc2, 0x9d, 0x33, 0xce, 0x5e, 0x3a, 0xcd, 0x3b, 0xe2, 0x0b, 0x6e, 0x60, 0x2f, 0x9d, 0x71, 0x74, 0x86, 0xf6, 0x86, 0xe4, 0x0e, 0x91, 0xfc, 0x99, 0x3a, 0x44, 0xce, 0xd2, 0xdb, 0x90, 0x10,
0xec, 0x71, 0xc8, 0xbf, 0x2f, 0xc1, 0x5c, 0x72, 0x87, 0x2c, 0xd2, 0x60, 0xa2, 0xab, 0x1c, 0x06, 0xc4, 0x06, 0xf6, 0xe9, 0xbe, 0x0d, 0x13, 0xe1, 0x7e, 0x1b, 0x67, 0x2f, 0x9d, 0x96, 0x1f, 0xf1,
0xbb, 0x96, 0xa5, 0x33, 0xbe, 0x8c, 0xf1, 0x96, 0x89, 0xf5, 0x10, 0x16, 0x8e, 0x60, 0xcb, 0x3f, 0x05, 0x37, 0xb0, 0x97, 0xce, 0x38, 0xf6, 0x38, 0xe4, 0xdf, 0x97, 0x60, 0x2e, 0xb9, 0xaf, 0x16,
0x48, 0x30, 0x9f, 0xd2, 0xac, 0x70, 0xbe, 0x96, 0xa0, 0x0f, 0xa1, 0xd4, 0x55, 0x0e, 0x9b, 0x3d, 0x69, 0x30, 0xd1, 0x55, 0x0e, 0x83, 0xbd, 0xce, 0xd2, 0x19, 0x5f, 0xc6, 0x78, 0xa3, 0xc5, 0x7a,
0xab, 0x43, 0xce, 0xfc, 0x16, 0xc8, 0x0f, 0xf4, 0xba, 0x40, 0xc1, 0x1e, 0x9e, 0xfc, 0x97, 0x12, 0x08, 0x0b, 0x47, 0xb0, 0xe5, 0x1f, 0x24, 0x98, 0x4f, 0x69, 0x71, 0x38, 0x5f, 0x4b, 0xd0, 0x87,
0xfc, 0x2c, 0xf5, 0xaa, 0x84, 0xee, 0x85, 0xfa, 0x2a, 0xe4, 0x48, 0x5f, 0x05, 0x8a, 0x0b, 0xbe, 0x50, 0xea, 0x2a, 0x87, 0xcd, 0x9e, 0xd5, 0x21, 0x67, 0x7e, 0x0b, 0xe4, 0x07, 0x7a, 0x5d, 0xa0,
0xa2, 0xb6, 0x8a, 0x2f, 0x24, 0x28, 0xa7, 0xdd, 0x1d, 0xd1, 0xdd, 0x90, 0x91, 0xbf, 0x88, 0x18, 0x60, 0x0f, 0x4f, 0xfe, 0x0b, 0x09, 0x7e, 0x96, 0x7a, 0x55, 0x42, 0xf7, 0x42, 0xdd, 0x18, 0x72,
0x39, 0x1d, 0x93, 0x7b, 0x45, 0x36, 0xfe, 0x9b, 0x04, 0x97, 0x4f, 0xa8, 0xc1, 0xbc, 0x2b, 0x0a, 0xa4, 0x1b, 0x03, 0xc5, 0x05, 0x5f, 0x51, 0x33, 0xc6, 0x17, 0x12, 0x94, 0xd3, 0xee, 0x8e, 0xe8,
0x69, 0x07, 0xb9, 0xf8, 0xb3, 0xb5, 0xf8, 0xe6, 0xe5, 0x5f, 0x51, 0x12, 0x78, 0x70, 0xaa, 0x34, 0x6e, 0xc8, 0xc8, 0x5f, 0x44, 0x8c, 0x9c, 0x8e, 0xc9, 0xbd, 0x22, 0x1b, 0xff, 0x4d, 0x82, 0xcb,
0xda, 0x86, 0x79, 0x71, 0x3f, 0x8a, 0xd2, 0x44, 0x79, 0xc1, 0xdb, 0xcf, 0x96, 0x93, 0x59, 0x70, 0x27, 0xd4, 0x60, 0xde, 0x15, 0x85, 0xb4, 0x83, 0x5c, 0xfc, 0xd9, 0x5a, 0x7c, 0xf3, 0xf2, 0xaf,
0x9a, 0xac, 0xfc, 0x37, 0x12, 0xcc, 0x25, 0x3f, 0x0a, 0xa0, 0xb7, 0x42, 0x4b, 0x5e, 0x89, 0x2c, 0x28, 0x09, 0x3c, 0x38, 0x55, 0x1a, 0x6d, 0xc3, 0xbc, 0xb8, 0x1f, 0x45, 0x69, 0xa2, 0xbc, 0xe0,
0xf9, 0x64, 0x44, 0x4a, 0x2c, 0xf8, 0xc7, 0x30, 0x21, 0x9e, 0x0e, 0x04, 0x8c, 0x70, 0x66, 0x39, 0x4d, 0x6b, 0xcb, 0xc9, 0x2c, 0x38, 0x4d, 0x56, 0xfe, 0x6b, 0x09, 0xe6, 0x92, 0x1f, 0x05, 0xd0,
0x29, 0x83, 0x08, 0x08, 0xb7, 0x80, 0xe5, 0xc7, 0x24, 0x3c, 0x86, 0x23, 0x68, 0xf2, 0x1f, 0xe4, 0x5b, 0xa1, 0x25, 0xaf, 0x44, 0x96, 0x7c, 0x32, 0x22, 0x25, 0x16, 0xfc, 0x63, 0x98, 0x10, 0x4f,
0x60, 0xa8, 0xd9, 0x52, 0x34, 0x72, 0x0e, 0xf5, 0xeb, 0x7b, 0xa1, 0xfa, 0x75, 0xd0, 0x3f, 0x76, 0x07, 0x02, 0x46, 0x38, 0xb3, 0x9c, 0x94, 0x41, 0x04, 0x84, 0x5b, 0xc0, 0xf2, 0x63, 0x12, 0x1e,
0x71, 0xab, 0x52, 0x4b, 0x57, 0x1c, 0x29, 0x5d, 0xdf, 0xc8, 0x84, 0x76, 0x72, 0xd5, 0xfa, 0x6b, 0xc3, 0x11, 0x34, 0xf9, 0x0f, 0x72, 0x30, 0xd4, 0x6c, 0x29, 0x1a, 0x39, 0x87, 0xfa, 0xf5, 0xbd,
0x30, 0xe2, 0x29, 0x3d, 0x5d, 0x32, 0x95, 0xff, 0x22, 0x07, 0xa3, 0x01, 0x15, 0xa7, 0x4c, 0xc5, 0x50, 0xfd, 0x3a, 0xe8, 0xbf, 0x83, 0x71, 0xab, 0x52, 0x4b, 0x57, 0x1c, 0x29, 0x5d, 0xdf, 0xc8,
0xbb, 0xa1, 0xfa, 0x23, 0x9f, 0xe1, 0xa1, 0x26, 0xa0, 0xab, 0xea, 0x56, 0x1c, 0x4e, 0x63, 0xb2, 0x84, 0x76, 0x72, 0xd5, 0xfa, 0x6b, 0x30, 0xe2, 0x29, 0x3d, 0x5d, 0x32, 0x95, 0xff, 0x3c, 0x07,
0xdf, 0x8a, 0x1a, 0x2f, 0x44, 0xde, 0x86, 0x09, 0x5b, 0xb1, 0x3a, 0xc4, 0xf6, 0x3e, 0x5c, 0xe4, 0xa3, 0x01, 0x15, 0xa7, 0x4c, 0xc5, 0xbb, 0xa1, 0xfa, 0x23, 0x9f, 0xe1, 0xa1, 0x26, 0xa0, 0xab,
0xb9, 0x2f, 0x7a, 0x1d, 0xf2, 0x5b, 0x21, 0x2a, 0x8e, 0x70, 0x5f, 0x7a, 0x08, 0xe3, 0x21, 0x65, 0xea, 0x56, 0x1c, 0x4e, 0x3b, 0xb3, 0xdf, 0xc0, 0x1a, 0x2f, 0x44, 0xde, 0x86, 0x09, 0x5b, 0xb1,
0xa7, 0xea, 0x2b, 0xfe, 0x7b, 0x09, 0x7e, 0x31, 0xf0, 0xb1, 0x07, 0xd5, 0x43, 0x87, 0xa4, 0x1a, 0x3a, 0xc4, 0xf6, 0x3e, 0x5c, 0x38, 0xed, 0x56, 0x5e, 0x5f, 0xfd, 0x56, 0x88, 0x8a, 0x23, 0xdc,
0x39, 0x24, 0x0b, 0xe9, 0x00, 0xaf, 0xae, 0x3f, 0xad, 0x7e, 0xf3, 0xf9, 0xf7, 0x0b, 0x17, 0xbe, 0x97, 0x1e, 0xc2, 0x78, 0x48, 0xd9, 0xa9, 0xba, 0x91, 0xff, 0x4e, 0x82, 0x5f, 0x0c, 0x7c, 0xec,
0xfd, 0x7e, 0xe1, 0xc2, 0x77, 0xdf, 0x2f, 0x5c, 0xf8, 0xdd, 0xe3, 0x05, 0xe9, 0xf9, 0xf1, 0x82, 0x41, 0xf5, 0xd0, 0x21, 0xa9, 0x46, 0x0e, 0xc9, 0x42, 0x3a, 0xc0, 0xab, 0xeb, 0x6a, 0xab, 0xdf,
0xf4, 0xed, 0xf1, 0x82, 0xf4, 0xdd, 0xf1, 0x82, 0xf4, 0x1f, 0xc7, 0x0b, 0xd2, 0x9f, 0xfc, 0xb0, 0x7c, 0xfe, 0xfd, 0xc2, 0x85, 0x6f, 0xbf, 0x5f, 0xb8, 0xf0, 0xdd, 0xf7, 0x0b, 0x17, 0x7e, 0xf7,
0x70, 0xe1, 0xc3, 0xa2, 0x80, 0xfb, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x27, 0x4b, 0x93, 0x78, 0x41, 0x7a, 0x7e, 0xbc, 0x20, 0x7d, 0x7b, 0xbc, 0x20, 0x7d, 0x77, 0xbc, 0x20, 0xfd, 0xc7,
0x2b, 0x3e, 0x00, 0x00, 0xf1, 0x82, 0xf4, 0xc7, 0x3f, 0x2c, 0x5c, 0xf8, 0xb0, 0x28, 0xe0, 0xfe, 0x37, 0x00, 0x00, 0xff,
0xff, 0xb6, 0xd9, 0x2e, 0xa8, 0x61, 0x3e, 0x00, 0x00,
} }
func (m *AllowedCSIDriver) Marshal() (dAtA []byte, err error) { func (m *AllowedCSIDriver) Marshal() (dAtA []byte, err error) {
@ -2814,6 +2815,13 @@ func (m *HTTPIngressPath) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.PathType != nil {
i -= len(*m.PathType)
copy(dAtA[i:], *m.PathType)
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PathType)))
i--
dAtA[i] = 0x1a
}
{ {
size, err := m.Backend.MarshalToSizedBuffer(dAtA[:i]) size, err := m.Backend.MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
@ -5088,6 +5096,10 @@ func (m *HTTPIngressPath) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
l = m.Backend.Size() l = m.Backend.Size()
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
if m.PathType != nil {
l = len(*m.PathType)
n += 1 + l + sovGenerated(uint64(l))
}
return n return n
} }
@ -6072,6 +6084,7 @@ func (this *HTTPIngressPath) String() string {
s := strings.Join([]string{`&HTTPIngressPath{`, s := strings.Join([]string{`&HTTPIngressPath{`,
`Path:` + fmt.Sprintf("%v", this.Path) + `,`, `Path:` + fmt.Sprintf("%v", this.Path) + `,`,
`Backend:` + strings.Replace(strings.Replace(this.Backend.String(), "IngressBackend", "IngressBackend", 1), `&`, ``, 1) + `,`, `Backend:` + strings.Replace(strings.Replace(this.Backend.String(), "IngressBackend", "IngressBackend", 1), `&`, ``, 1) + `,`,
`PathType:` + valueToStringGenerated(this.PathType) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -9614,6 +9627,39 @@ func (m *HTTPIngressPath) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PathType", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
s := PathType(dAtA[iNdEx:postIndex])
m.PathType = &s
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:]) skippy, err := skipGenerated(dAtA[iNdEx:])

View File

@ -408,19 +408,33 @@ message FSGroupStrategyOptions {
repeated IDRange ranges = 2; repeated IDRange ranges = 2;
} }
// HTTPIngressPath associates a path regex with a backend. Incoming urls matching // HTTPIngressPath associates a path with a backend. Incoming urls matching the
// the path are forwarded to the backend. // path are forwarded to the backend.
message HTTPIngressPath { message HTTPIngressPath {
// Path is an extended POSIX regex as defined by IEEE Std 1003.1, // Path is matched against the path of an incoming request. Currently it can
// (i.e this follows the egrep/unix syntax, not the perl syntax) // contain characters disallowed from the conventional "path" part of a URL
// matched against the path of an incoming request. Currently it can // as defined by RFC 3986. Paths must begin with a '/'. When unspecified,
// contain characters disallowed from the conventional "path" // all paths from incoming requests are matched.
// part of a URL as defined by RFC 3986. Paths must begin with
// a '/'. If unspecified, the path defaults to a catch all sending
// traffic to the backend.
// +optional // +optional
optional string path = 1; optional string path = 1;
// PathType determines the interpretation of the Path matching. PathType can
// be one of the following values:
// * Exact: Matches the URL path exactly.
// * Prefix: Matches based on a URL path prefix split by '/'. Matching is
// done on a path element by element basis. A path element refers is the
// list of labels in the path split by the '/' separator. A request is a
// match for path p if every p is an element-wise prefix of p of the
// request path. Note that if the last element of the path is a substring
// of the last element in request path, it is not a match (e.g. /foo/bar
// matches /foo/bar/baz, but does not match /foo/barbaz).
// * ImplementationSpecific: Interpretation of the Path matching is up to
// the IngressClass. Implementations can treat this as a separate PathType
// or treat it identically to Prefix or Exact path types.
// Implementations are required to support all path types.
// Defaults to ImplementationSpecific.
optional string pathType = 3;
// Backend defines the referenced service endpoint to which the traffic // Backend defines the referenced service endpoint to which the traffic
// will be forwarded to. // will be forwarded to.
optional IngressBackend backend = 2; optional IngressBackend backend = 2;

View File

@ -683,19 +683,63 @@ type HTTPIngressRuleValue struct {
// options usable by a loadbalancer, like http keep-alive. // options usable by a loadbalancer, like http keep-alive.
} }
// HTTPIngressPath associates a path regex with a backend. Incoming urls matching // PathType represents the type of path referred to by a HTTPIngressPath.
// the path are forwarded to the backend. type PathType string
const (
// PathTypeExact matches the URL path exactly and with case sensitivity.
PathTypeExact = PathType("Exact")
// PathTypePrefix matches based on a URL path prefix split by '/'. Matching
// is case sensitive and done on a path element by element basis. A path
// element refers to the list of labels in the path split by the '/'
// separator. A request is a match for path p if every p is an element-wise
// prefix of p of the request path. Note that if the last element of the
// path is a substring of the last element in request path, it is not a
// match (e.g. /foo/bar matches /foo/bar/baz, but does not match
// /foo/barbaz). If multiple matching paths exist in an Ingress spec, the
// longest matching path is given priority.
// Examples:
// - /foo/bar does not match requests to /foo/barbaz
// - /foo/bar matches request to /foo/bar and /foo/bar/baz
// - /foo and /foo/ both match requests to /foo and /foo/. If both paths are
// present in an Ingress spec, the longest matching path (/foo/) is given
// priority.
PathTypePrefix = PathType("Prefix")
// PathTypeImplementationSpecific matching is up to the IngressClass.
// Implementations can treat this as a separate PathType or treat it
// identically to Prefix or Exact path types.
PathTypeImplementationSpecific = PathType("ImplementationSpecific")
)
// HTTPIngressPath associates a path with a backend. Incoming urls matching the
// path are forwarded to the backend.
type HTTPIngressPath struct { type HTTPIngressPath struct {
// Path is an extended POSIX regex as defined by IEEE Std 1003.1, // Path is matched against the path of an incoming request. Currently it can
// (i.e this follows the egrep/unix syntax, not the perl syntax) // contain characters disallowed from the conventional "path" part of a URL
// matched against the path of an incoming request. Currently it can // as defined by RFC 3986. Paths must begin with a '/'. When unspecified,
// contain characters disallowed from the conventional "path" // all paths from incoming requests are matched.
// part of a URL as defined by RFC 3986. Paths must begin with
// a '/'. If unspecified, the path defaults to a catch all sending
// traffic to the backend.
// +optional // +optional
Path string `json:"path,omitempty" protobuf:"bytes,1,opt,name=path"` Path string `json:"path,omitempty" protobuf:"bytes,1,opt,name=path"`
// PathType determines the interpretation of the Path matching. PathType can
// be one of the following values:
// * Exact: Matches the URL path exactly.
// * Prefix: Matches based on a URL path prefix split by '/'. Matching is
// done on a path element by element basis. A path element refers is the
// list of labels in the path split by the '/' separator. A request is a
// match for path p if every p is an element-wise prefix of p of the
// request path. Note that if the last element of the path is a substring
// of the last element in request path, it is not a match (e.g. /foo/bar
// matches /foo/bar/baz, but does not match /foo/barbaz).
// * ImplementationSpecific: Interpretation of the Path matching is up to
// the IngressClass. Implementations can treat this as a separate PathType
// or treat it identically to Prefix or Exact path types.
// Implementations are required to support all path types.
// Defaults to ImplementationSpecific.
PathType *PathType `json:"pathType,omitempty" protobuf:"bytes,3,opt,name=pathType"`
// Backend defines the referenced service endpoint to which the traffic // Backend defines the referenced service endpoint to which the traffic
// will be forwarded to. // will be forwarded to.
Backend IngressBackend `json:"backend" protobuf:"bytes,2,opt,name=backend"` Backend IngressBackend `json:"backend" protobuf:"bytes,2,opt,name=backend"`

View File

@ -230,9 +230,10 @@ func (FSGroupStrategyOptions) SwaggerDoc() map[string]string {
} }
var map_HTTPIngressPath = map[string]string{ var map_HTTPIngressPath = map[string]string{
"": "HTTPIngressPath associates a path regex with a backend. Incoming urls matching the path are forwarded to the backend.", "": "HTTPIngressPath associates a path with a backend. Incoming urls matching the path are forwarded to the backend.",
"path": "Path is an extended POSIX regex as defined by IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. If unspecified, the path defaults to a catch all sending traffic to the backend.", "path": "Path is matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. When unspecified, all paths from incoming requests are matched.",
"backend": "Backend defines the referenced service endpoint to which the traffic will be forwarded to.", "pathType": "PathType determines the interpretation of the Path matching. PathType can be one of the following values: * Exact: Matches the URL path exactly. * Prefix: Matches based on a URL path prefix split by '/'. Matching is\n done on a path element by element basis. A path element refers is the\n list of labels in the path split by the '/' separator. A request is a\n match for path p if every p is an element-wise prefix of p of the\n request path. Note that if the last element of the path is a substring\n of the last element in request path, it is not a match (e.g. /foo/bar\n matches /foo/bar/baz, but does not match /foo/barbaz).\n* ImplementationSpecific: Interpretation of the Path matching is up to\n the IngressClass. Implementations can treat this as a separate PathType\n or treat it identically to Prefix or Exact path types.\nImplementations are required to support all path types. Defaults to ImplementationSpecific.",
"backend": "Backend defines the referenced service endpoint to which the traffic will be forwarded to.",
} }
func (HTTPIngressPath) SwaggerDoc() map[string]string { func (HTTPIngressPath) SwaggerDoc() map[string]string {

View File

@ -458,6 +458,11 @@ func (in *FSGroupStrategyOptions) DeepCopy() *FSGroupStrategyOptions {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) { func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) {
*out = *in *out = *in
if in.PathType != nil {
in, out := &in.PathType, &out.PathType
*out = new(PathType)
**out = **in
}
out.Backend = in.Backend out.Backend = in.Backend
return return
} }
@ -478,7 +483,9 @@ func (in *HTTPIngressRuleValue) DeepCopyInto(out *HTTPIngressRuleValue) {
if in.Paths != nil { if in.Paths != nil {
in, out := &in.Paths, &out.Paths in, out := &in.Paths, &out.Paths
*out = make([]HTTPIngressPath, len(*in)) *out = make([]HTTPIngressPath, len(*in))
copy(*out, *in) for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
} }
return return
} }

View File

@ -429,66 +429,68 @@ func init() {
} }
var fileDescriptor_5bea11de0ceb8f53 = []byte{ var fileDescriptor_5bea11de0ceb8f53 = []byte{
// 941 bytes of a gzipped FileDescriptorProto // 965 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4f, 0x6f, 0xe3, 0x44, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4f, 0x6f, 0xe3, 0x44,
0x14, 0x8f, 0x93, 0x66, 0xdb, 0x4e, 0xba, 0xdd, 0x6a, 0xe8, 0x21, 0xaa, 0x84, 0x5b, 0xf9, 0x80, 0x14, 0x8f, 0x93, 0x66, 0x9b, 0x4e, 0xba, 0xdd, 0x6a, 0xe8, 0x21, 0xaa, 0x84, 0x5b, 0xf9, 0x80,
0xca, 0x9f, 0xda, 0xb4, 0x0b, 0x88, 0x23, 0xf2, 0x4a, 0xa8, 0x15, 0x81, 0x86, 0x89, 0x85, 0x10, 0xca, 0x9f, 0xda, 0x34, 0xbb, 0x20, 0x8e, 0xc8, 0x2b, 0xa1, 0x56, 0x04, 0x1a, 0x26, 0x16, 0x42,
0x02, 0x69, 0x27, 0xce, 0x5b, 0xc7, 0xc4, 0xb1, 0xcd, 0xcc, 0x38, 0x68, 0x6f, 0x7c, 0x01, 0x04, 0x08, 0xa4, 0x9d, 0x38, 0x6f, 0x1d, 0x13, 0xc7, 0x36, 0x33, 0xe3, 0xa0, 0xbd, 0xf1, 0x0d, 0xe0,
0x5f, 0x02, 0xce, 0x1c, 0x39, 0x22, 0xb8, 0xf4, 0xb8, 0xc7, 0x3d, 0xad, 0x68, 0xf8, 0x22, 0x68, 0x4b, 0xc0, 0x99, 0x23, 0x47, 0x04, 0x97, 0x1e, 0xf7, 0xb8, 0xa7, 0x8a, 0x86, 0x6f, 0xc1, 0x09,
0xc6, 0x53, 0xdb, 0x49, 0x1a, 0xd6, 0xcb, 0xa1, 0x37, 0xcf, 0xbc, 0xf7, 0x7e, 0xef, 0xfd, 0x7e, 0xcd, 0x78, 0x6a, 0x3b, 0x49, 0xcb, 0x66, 0xf7, 0xd0, 0x53, 0x32, 0xf3, 0x7e, 0xef, 0xf7, 0xde,
0xef, 0xf9, 0x0d, 0xfa, 0x78, 0xf2, 0x21, 0xb7, 0xc3, 0xc4, 0x99, 0x64, 0x43, 0x60, 0x31, 0x08, 0xfb, 0xbd, 0xe7, 0x37, 0xe8, 0x93, 0xc9, 0x47, 0xdc, 0x0e, 0x13, 0x67, 0x92, 0x0d, 0x81, 0xc5,
0xe0, 0xce, 0x0c, 0xe2, 0x51, 0xc2, 0x1c, 0x6d, 0xa0, 0x69, 0xe8, 0xc4, 0x20, 0xbe, 0x4f, 0xd8, 0x20, 0x80, 0x3b, 0x33, 0x88, 0x47, 0x09, 0x73, 0xb4, 0x81, 0xa6, 0xa1, 0x13, 0x83, 0xf8, 0x21,
0x24, 0x8c, 0x03, 0x67, 0x76, 0x3a, 0x04, 0x41, 0x4f, 0x9d, 0x00, 0x62, 0x60, 0x54, 0xc0, 0xc8, 0x61, 0x93, 0x30, 0x0e, 0x9c, 0xd9, 0xc9, 0x10, 0x04, 0x3d, 0x71, 0x02, 0x88, 0x81, 0x51, 0x01,
0x4e, 0x59, 0x22, 0x12, 0xfc, 0x7a, 0xee, 0x6e, 0xd3, 0x34, 0xb4, 0x4b, 0x77, 0x5b, 0xbb, 0x1f, 0x23, 0x3b, 0x65, 0x89, 0x48, 0xf0, 0x9b, 0x39, 0xdc, 0xa6, 0x69, 0x68, 0x97, 0x70, 0x5b, 0xc3,
0x9c, 0x04, 0xa1, 0x18, 0x67, 0x43, 0xdb, 0x4f, 0xa6, 0x4e, 0x90, 0x04, 0x89, 0xa3, 0xa2, 0x86, 0xf7, 0x8f, 0x83, 0x50, 0x8c, 0xb3, 0xa1, 0xed, 0x27, 0x53, 0x27, 0x48, 0x82, 0xc4, 0x51, 0x5e,
0xd9, 0x13, 0x75, 0x52, 0x07, 0xf5, 0x95, 0xa3, 0x1d, 0x58, 0x95, 0xe4, 0x7e, 0xc2, 0xc0, 0x99, 0xc3, 0xec, 0xa9, 0x3a, 0xa9, 0x83, 0xfa, 0x97, 0xb3, 0xed, 0x5b, 0x95, 0xe0, 0x7e, 0xc2, 0xc0,
0xad, 0x64, 0x3c, 0x78, 0xaf, 0xf4, 0x99, 0x52, 0x7f, 0x1c, 0xc6, 0xc0, 0x9e, 0x3a, 0xe9, 0x24, 0x99, 0xad, 0x44, 0xdc, 0x7f, 0x54, 0x62, 0xa6, 0xd4, 0x1f, 0x87, 0x31, 0xb0, 0x67, 0x4e, 0x3a,
0x90, 0x17, 0xdc, 0x99, 0x82, 0xa0, 0xb7, 0x45, 0x39, 0xeb, 0xa2, 0x58, 0x16, 0x8b, 0x70, 0x0a, 0x09, 0xe4, 0x05, 0x77, 0xa6, 0x20, 0xe8, 0x4d, 0x5e, 0xce, 0x6d, 0x5e, 0x2c, 0x8b, 0x45, 0x38,
0x2b, 0x01, 0x1f, 0xbc, 0x2c, 0x80, 0xfb, 0x63, 0x98, 0xd2, 0x95, 0xb8, 0x87, 0xeb, 0xe2, 0x32, 0x85, 0x15, 0x87, 0x0f, 0x5f, 0xe6, 0xc0, 0xfd, 0x31, 0x4c, 0xe9, 0x8a, 0xdf, 0xc3, 0xdb, 0xfc,
0x11, 0x46, 0x4e, 0x18, 0x0b, 0x2e, 0xd8, 0x72, 0x90, 0xf5, 0xa3, 0x81, 0x1e, 0x9c, 0x7b, 0x5e, 0x32, 0x11, 0x46, 0x4e, 0x18, 0x0b, 0x2e, 0xd8, 0xb2, 0x93, 0xf5, 0x97, 0x81, 0x1e, 0x9c, 0x7a,
0xff, 0x22, 0x0e, 0x18, 0x70, 0xde, 0xa7, 0x62, 0x8c, 0x8f, 0xd0, 0x46, 0x4a, 0xc5, 0xb8, 0x6b, 0x5e, 0xff, 0x2c, 0x0e, 0x18, 0x70, 0xde, 0xa7, 0x62, 0x8c, 0x0f, 0xd1, 0x46, 0x4a, 0xc5, 0xb8,
0x1c, 0x19, 0xc7, 0xdb, 0xee, 0xce, 0xd5, 0x8b, 0xc3, 0xc6, 0xfc, 0xc5, 0xe1, 0x86, 0xb4, 0x11, 0x63, 0x1c, 0x1a, 0x47, 0x5b, 0xee, 0xf6, 0xc5, 0xe5, 0x41, 0x6d, 0x7e, 0x79, 0xb0, 0x21, 0x6d,
0x65, 0xc1, 0x5f, 0xa2, 0xcd, 0x21, 0xf5, 0x27, 0x10, 0x8f, 0xba, 0xcd, 0x23, 0xe3, 0xb8, 0x73, 0x44, 0x59, 0xf0, 0x23, 0xd4, 0x92, 0xbf, 0xde, 0xb3, 0x14, 0x3a, 0x0d, 0x85, 0xea, 0xcc, 0x2f,
0x76, 0x62, 0xff, 0x67, 0x37, 0x6c, 0x0d, 0xef, 0xe6, 0x41, 0xee, 0x03, 0x8d, 0xb9, 0xa9, 0x2f, 0x0f, 0x5a, 0x7d, 0x7d, 0xf7, 0x6f, 0xe5, 0x3f, 0x29, 0x90, 0xf8, 0x2b, 0xb4, 0x39, 0xa4, 0xfe,
0xc8, 0x0d, 0x9c, 0x35, 0x41, 0xfb, 0x95, 0x72, 0x48, 0x16, 0xc1, 0x17, 0x34, 0xca, 0x00, 0x0f, 0x04, 0xe2, 0x51, 0xa7, 0x7e, 0x68, 0x1c, 0xb5, 0xbb, 0xc7, 0xf6, 0xff, 0xf6, 0xd0, 0xd6, 0x49,
0x50, 0x5b, 0x66, 0xe6, 0x5d, 0xe3, 0xa8, 0x75, 0xdc, 0x39, 0xb3, 0x5f, 0x92, 0x6f, 0x89, 0x92, 0xb9, 0xb9, 0x93, 0xfb, 0x40, 0x67, 0xb2, 0xa9, 0x2f, 0xc8, 0x35, 0x9d, 0x35, 0x41, 0x7b, 0x95,
0x7b, 0x5f, 0x27, 0x6c, 0xcb, 0x13, 0x27, 0x39, 0x96, 0xf5, 0x53, 0x13, 0x6d, 0x6a, 0x2f, 0xfc, 0x22, 0x48, 0x16, 0xc1, 0x97, 0x34, 0xca, 0x00, 0x0f, 0x50, 0x53, 0x46, 0xe7, 0x1d, 0xe3, 0xb0,
0x18, 0x6d, 0xc9, 0x0e, 0x8e, 0xa8, 0xa0, 0x8a, 0x78, 0xe7, 0xec, 0xdd, 0x4a, 0x8e, 0x42, 0x50, 0x71, 0xd4, 0xee, 0xda, 0x2f, 0x89, 0xb7, 0x24, 0x84, 0x7b, 0x5f, 0x07, 0x6c, 0xca, 0x13, 0x27,
0x3b, 0x9d, 0x04, 0xf2, 0x82, 0xdb, 0xd2, 0xdb, 0x9e, 0x9d, 0xda, 0x97, 0xc3, 0x6f, 0xc1, 0x17, 0x39, 0x97, 0xf5, 0x53, 0x1d, 0x6d, 0x6a, 0x14, 0x7e, 0x82, 0x5a, 0xb2, 0xef, 0x23, 0x2a, 0xa8,
0x9f, 0x82, 0xa0, 0x2e, 0xd6, 0x59, 0x50, 0x79, 0x47, 0x0a, 0x54, 0xdc, 0x43, 0x1b, 0x3c, 0x05, 0x92, 0xab, 0xdd, 0x7d, 0xbf, 0x12, 0xa3, 0x68, 0x83, 0x9d, 0x4e, 0x02, 0x79, 0xc1, 0x6d, 0x89,
0x5f, 0x2b, 0xf6, 0x56, 0x3d, 0xc5, 0x06, 0x29, 0xf8, 0x65, 0x0b, 0xe4, 0x89, 0x28, 0x14, 0xec, 0xb6, 0x67, 0x27, 0xf6, 0xf9, 0xf0, 0x3b, 0xf0, 0xc5, 0x67, 0x20, 0xa8, 0x8b, 0x75, 0x14, 0x54,
0xa1, 0x7b, 0x5c, 0x50, 0x91, 0xf1, 0x6e, 0x4b, 0xe1, 0xbd, 0x53, 0x13, 0x4f, 0xc5, 0xb8, 0xbb, 0xde, 0x91, 0x82, 0x15, 0xf7, 0xd0, 0x06, 0x4f, 0xc1, 0xd7, 0x8a, 0xbd, 0xb3, 0x9e, 0x62, 0x83,
0x1a, 0xf1, 0x5e, 0x7e, 0x26, 0x1a, 0xcb, 0xfa, 0xcd, 0x40, 0xbb, 0x8b, 0xbd, 0xc2, 0xef, 0xa3, 0x14, 0xfc, 0xb2, 0x71, 0xf2, 0x44, 0x14, 0x0b, 0xf6, 0xd0, 0x3d, 0x2e, 0xa8, 0xc8, 0xb8, 0x6a,
0x0e, 0x07, 0x36, 0x0b, 0x7d, 0xf8, 0x8c, 0x4e, 0x41, 0x0f, 0xc5, 0x6b, 0x3a, 0xbe, 0x33, 0x28, 0x5b, 0xbb, 0xfb, 0xde, 0x9a, 0x7c, 0xca, 0xc7, 0xdd, 0xd1, 0x8c, 0xf7, 0xf2, 0x33, 0xd1, 0x5c,
0x4d, 0xa4, 0xea, 0x87, 0x83, 0x22, 0xac, 0x9f, 0x30, 0xa1, 0x49, 0xaf, 0x97, 0x54, 0xce, 0xa8, 0xd6, 0x6f, 0x06, 0xda, 0x59, 0xec, 0x15, 0xfe, 0x00, 0xb5, 0x39, 0xb0, 0x59, 0xe8, 0xc3, 0xe7,
0x9d, 0xcf, 0xa8, 0x7d, 0x11, 0x8b, 0x4b, 0x36, 0x10, 0x2c, 0x8c, 0x83, 0x95, 0x44, 0x12, 0x8c, 0x74, 0x0a, 0x7a, 0x94, 0xde, 0xd0, 0xfe, 0xed, 0x41, 0x69, 0x22, 0x55, 0x1c, 0x0e, 0x0a, 0xb7,
0x54, 0x91, 0xad, 0xbf, 0x0c, 0xb4, 0xa3, 0x4b, 0x7e, 0x14, 0xd1, 0x3b, 0xe9, 0xe4, 0xe7, 0x0b, 0x7e, 0xc2, 0x84, 0x2e, 0xfa, 0x76, 0x49, 0xe5, 0x64, 0xdb, 0xf9, 0x64, 0xdb, 0x67, 0xb1, 0x38,
0x9d, 0x74, 0xea, 0x29, 0xaf, 0x8a, 0x5b, 0xd7, 0x4e, 0xeb, 0x4f, 0x03, 0xed, 0x55, 0x1d, 0x7b, 0x67, 0x03, 0xc1, 0xc2, 0x38, 0x58, 0x09, 0x24, 0xc9, 0x48, 0x95, 0x59, 0xce, 0xfd, 0xb6, 0x4e,
0x21, 0x17, 0xf8, 0xeb, 0x15, 0x26, 0x76, 0x3d, 0x26, 0x32, 0x5a, 0xf1, 0xd8, 0xd3, 0xa9, 0xb6, 0xf9, 0x71, 0x44, 0xef, 0xa4, 0x93, 0x5f, 0x2c, 0x74, 0xd2, 0x59, 0x4f, 0x79, 0x95, 0xdc, 0x6d,
0x6e, 0x6e, 0x2a, 0x2c, 0xfa, 0xa8, 0x1d, 0x0a, 0x98, 0xf2, 0x6e, 0x53, 0xfd, 0x52, 0x6f, 0xbf, 0xed, 0xb4, 0xfe, 0x34, 0xd0, 0x6e, 0x15, 0xd8, 0x0b, 0xb9, 0xc0, 0xdf, 0xac, 0x54, 0x62, 0xaf,
0x02, 0x8d, 0xf2, 0x7f, 0xba, 0x90, 0x08, 0x24, 0x07, 0xb2, 0x7e, 0x59, 0x22, 0x21, 0xf9, 0xe1, 0x57, 0x89, 0xf4, 0x56, 0x75, 0xec, 0xea, 0x50, 0xad, 0xeb, 0x9b, 0x4a, 0x15, 0x7d, 0xd4, 0x0c,
0x33, 0x84, 0xfc, 0x24, 0x16, 0x2c, 0x89, 0x22, 0x60, 0x7a, 0x7c, 0x0a, 0x79, 0x1f, 0x15, 0x16, 0x05, 0x4c, 0x79, 0xa7, 0xae, 0x3e, 0xa9, 0x77, 0x5f, 0xa1, 0x8c, 0xf2, 0x7b, 0x3a, 0x93, 0x0c,
0x52, 0xf1, 0xc2, 0xdf, 0x20, 0x94, 0x52, 0x46, 0xa7, 0x20, 0x80, 0xf1, 0xdb, 0x56, 0x8c, 0x5c, 0x24, 0x27, 0xb2, 0x7e, 0x59, 0x2a, 0x42, 0xd6, 0x87, 0xbb, 0x08, 0xf9, 0x49, 0x2c, 0x58, 0x12,
0xd1, 0x92, 0xa8, 0xf7, 0x34, 0x85, 0x51, 0x2f, 0xf1, 0x69, 0x94, 0x37, 0x8a, 0xc0, 0x13, 0x60, 0x45, 0xc0, 0xf4, 0xf8, 0x14, 0xf2, 0x3e, 0x2e, 0x2c, 0xa4, 0x82, 0xc2, 0xdf, 0x22, 0x94, 0x52,
0x10, 0xfb, 0xe0, 0xee, 0x4a, 0xf8, 0x7e, 0x01, 0x42, 0x2a, 0x80, 0xd6, 0xef, 0x06, 0xea, 0xe8, 0x46, 0xa7, 0x20, 0x80, 0xf1, 0x9b, 0x56, 0x8c, 0x5c, 0xec, 0xb2, 0x50, 0xb9, 0x8d, 0x46, 0xbd,
0x3a, 0xef, 0x40, 0xe7, 0x4f, 0x16, 0x75, 0x7e, 0xa3, 0xe6, 0xaa, 0xbc, 0x5d, 0xe2, 0x5f, 0xcb, 0xc4, 0xa7, 0x51, 0xde, 0x28, 0x02, 0x4f, 0x81, 0x41, 0xec, 0x83, 0xbb, 0x23, 0xe9, 0xfb, 0x05,
0xd2, 0xe5, 0x72, 0x94, 0xbb, 0x7a, 0x9c, 0x70, 0xb1, 0xbc, 0xab, 0xcf, 0x13, 0x2e, 0x88, 0xb2, 0x09, 0xa9, 0x10, 0x5a, 0xbf, 0x1b, 0xa8, 0xad, 0xf3, 0xbc, 0x03, 0x9d, 0x3f, 0x5d, 0xd4, 0xf9,
0xe0, 0x0c, 0xed, 0x85, 0x4b, 0xdb, 0xf4, 0xd5, 0x06, 0xb7, 0x08, 0x73, 0xbb, 0x1a, 0x7e, 0x6f, 0xad, 0x35, 0x57, 0xe5, 0xcd, 0x12, 0xff, 0x5a, 0xa6, 0x2e, 0x97, 0xa3, 0xdc, 0xf0, 0xe3, 0x84,
0xd9, 0x42, 0x56, 0x52, 0x58, 0x80, 0x56, 0xbc, 0xe4, 0x7f, 0x33, 0x16, 0x22, 0xd5, 0x1a, 0x3f, 0x8b, 0xe5, 0x0d, 0x7f, 0x9a, 0x70, 0x41, 0x94, 0x05, 0x67, 0x68, 0x37, 0x5c, 0xda, 0xa6, 0xaf,
0xac, 0xbf, 0xc3, 0xcb, 0x12, 0xb6, 0x14, 0x3b, 0xcf, 0xeb, 0x13, 0x05, 0x65, 0xfd, 0xd1, 0x2c, 0x36, 0xb8, 0x85, 0x9b, 0xdb, 0xd1, 0xf4, 0xbb, 0xcb, 0x16, 0xb2, 0x12, 0xc2, 0x02, 0xb4, 0x82,
0xf4, 0x50, 0xd3, 0xf6, 0x51, 0xc1, 0x56, 0x4d, 0xa0, 0x5a, 0x59, 0x1b, 0x4a, 0x9b, 0xfd, 0x4a, 0x92, 0xdf, 0xcd, 0x58, 0x88, 0x54, 0x6b, 0xfc, 0x70, 0xfd, 0x1d, 0x5e, 0xa6, 0xd0, 0x52, 0xd5,
0xe1, 0x85, 0x8d, 0xac, 0x78, 0x63, 0xaf, 0x7c, 0xdb, 0x8c, 0xff, 0xf3, 0xb6, 0x75, 0x6e, 0x7b, 0x79, 0x5e, 0x9f, 0x28, 0x2a, 0xeb, 0x8f, 0x7a, 0xa1, 0x87, 0x9a, 0xb6, 0x8f, 0x8b, 0x6a, 0xd5,
0xd7, 0xf0, 0x39, 0x6a, 0x89, 0xe8, 0x66, 0x04, 0xde, 0xac, 0x87, 0xe8, 0xf5, 0x06, 0x6e, 0x47, 0x04, 0xaa, 0x95, 0xb5, 0xa1, 0xb4, 0xd9, 0xab, 0x24, 0x5e, 0xd8, 0xc8, 0x0a, 0x1a, 0x7b, 0xe5,
0x4b, 0xde, 0xf2, 0x7a, 0x03, 0x22, 0x21, 0xf0, 0x25, 0x6a, 0xb3, 0x2c, 0x02, 0xb9, 0xf7, 0x5b, 0xdb, 0x66, 0xbc, 0xce, 0xdb, 0xd6, 0xbe, 0xe9, 0x5d, 0xc3, 0xa7, 0xa8, 0x21, 0xa2, 0xeb, 0x11,
0xf5, 0xdf, 0x11, 0xa9, 0x60, 0x39, 0x52, 0xf2, 0xc4, 0x49, 0x8e, 0x63, 0x7d, 0x87, 0xee, 0x2f, 0x78, 0x7b, 0x3d, 0x46, 0xaf, 0x37, 0x70, 0xdb, 0x5a, 0xf2, 0x86, 0xd7, 0x1b, 0x10, 0x49, 0x81,
0x3c, 0x0e, 0xf8, 0x31, 0xda, 0x89, 0x12, 0x3a, 0x72, 0x69, 0x44, 0x63, 0x5f, 0xff, 0xb3, 0x4b, 0xcf, 0x51, 0x93, 0x65, 0x11, 0xc8, 0xbd, 0xdf, 0x58, 0xff, 0x1d, 0x91, 0x0a, 0x96, 0x23, 0x25,
0x73, 0x7b, 0xf3, 0xff, 0xf5, 0x2a, 0x7e, 0xfa, 0x69, 0xd9, 0xd7, 0x49, 0x76, 0xaa, 0x36, 0xb2, 0x4f, 0x9c, 0xe4, 0x3c, 0xd6, 0xf7, 0xe8, 0xfe, 0xc2, 0xe3, 0x80, 0x9f, 0xa0, 0xed, 0x28, 0xa1,
0x80, 0x68, 0x51, 0x84, 0x4a, 0x8e, 0xf8, 0x10, 0xb5, 0xe5, 0xa4, 0xe6, 0x6f, 0xfb, 0xb6, 0xbb, 0x23, 0x97, 0x46, 0x34, 0xf6, 0xf5, 0x37, 0xbb, 0x34, 0xb7, 0xd7, 0xdf, 0x5f, 0xaf, 0x82, 0xd3,
0x2d, 0x2b, 0x94, 0x03, 0xcc, 0x49, 0x7e, 0x2f, 0x57, 0x08, 0x07, 0x9f, 0x81, 0x50, 0xed, 0x6c, 0x4f, 0xcb, 0x9e, 0x0e, 0xb2, 0x5d, 0xb5, 0x91, 0x05, 0x46, 0x8b, 0x22, 0x54, 0xd6, 0x88, 0x0f,
0x2e, 0xae, 0x90, 0x41, 0x61, 0x21, 0x15, 0x2f, 0xf7, 0xe4, 0xea, 0xda, 0x6c, 0x3c, 0xbb, 0x36, 0x50, 0x53, 0x4e, 0x6a, 0xfe, 0xb6, 0x6f, 0xb9, 0x5b, 0x32, 0x43, 0x39, 0xc0, 0x9c, 0xe4, 0xf7,
0x1b, 0xcf, 0xaf, 0xcd, 0xc6, 0x0f, 0x73, 0xd3, 0xb8, 0x9a, 0x9b, 0xc6, 0xb3, 0xb9, 0x69, 0x3c, 0x72, 0x85, 0x70, 0xf0, 0x19, 0x08, 0xd5, 0xce, 0xfa, 0xe2, 0x0a, 0x19, 0x14, 0x16, 0x52, 0x41,
0x9f, 0x9b, 0xc6, 0xdf, 0x73, 0xd3, 0xf8, 0xf9, 0x1f, 0xb3, 0xf1, 0xd5, 0xa6, 0x96, 0xe9, 0xdf, 0xb9, 0xc7, 0x17, 0x57, 0x66, 0xed, 0xf9, 0x95, 0x59, 0x7b, 0x71, 0x65, 0xd6, 0x7e, 0x9c, 0x9b,
0x00, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x2a, 0x50, 0x9d, 0x96, 0x0a, 0x00, 0x00, 0xc6, 0xc5, 0xdc, 0x34, 0x9e, 0xcf, 0x4d, 0xe3, 0xc5, 0xdc, 0x34, 0xfe, 0x9e, 0x9b, 0xc6, 0xcf,
0xff, 0x98, 0xb5, 0xaf, 0x37, 0xb5, 0x4c, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x12, 0x75,
0x26, 0xcc, 0x0a, 0x00, 0x00,
} }
func (m *HTTPIngressPath) Marshal() (dAtA []byte, err error) { func (m *HTTPIngressPath) Marshal() (dAtA []byte, err error) {
@ -511,6 +513,13 @@ func (m *HTTPIngressPath) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.PathType != nil {
i -= len(*m.PathType)
copy(dAtA[i:], *m.PathType)
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.PathType)))
i--
dAtA[i] = 0x1a
}
{ {
size, err := m.Backend.MarshalToSizedBuffer(dAtA[:i]) size, err := m.Backend.MarshalToSizedBuffer(dAtA[:i])
if err != nil { if err != nil {
@ -1068,6 +1077,10 @@ func (m *HTTPIngressPath) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
l = m.Backend.Size() l = m.Backend.Size()
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
if m.PathType != nil {
l = len(*m.PathType)
n += 1 + l + sovGenerated(uint64(l))
}
return n return n
} }
@ -1272,6 +1285,7 @@ func (this *HTTPIngressPath) String() string {
s := strings.Join([]string{`&HTTPIngressPath{`, s := strings.Join([]string{`&HTTPIngressPath{`,
`Path:` + fmt.Sprintf("%v", this.Path) + `,`, `Path:` + fmt.Sprintf("%v", this.Path) + `,`,
`Backend:` + strings.Replace(strings.Replace(this.Backend.String(), "IngressBackend", "IngressBackend", 1), `&`, ``, 1) + `,`, `Backend:` + strings.Replace(strings.Replace(this.Backend.String(), "IngressBackend", "IngressBackend", 1), `&`, ``, 1) + `,`,
`PathType:` + valueToStringGenerated(this.PathType) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -1535,6 +1549,39 @@ func (m *HTTPIngressPath) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PathType", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
s := PathType(dAtA[iNdEx:postIndex])
m.PathType = &s
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:]) skippy, err := skipGenerated(dAtA[iNdEx:])

View File

@ -30,19 +30,33 @@ import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated". // Package-wide variables from generator "generated".
option go_package = "v1beta1"; option go_package = "v1beta1";
// HTTPIngressPath associates a path regex with a backend. Incoming urls matching // HTTPIngressPath associates a path with a backend. Incoming urls matching the
// the path are forwarded to the backend. // path are forwarded to the backend.
message HTTPIngressPath { message HTTPIngressPath {
// Path is an extended POSIX regex as defined by IEEE Std 1003.1, // Path is matched against the path of an incoming request. Currently it can
// (i.e this follows the egrep/unix syntax, not the perl syntax) // contain characters disallowed from the conventional "path" part of a URL
// matched against the path of an incoming request. Currently it can // as defined by RFC 3986. Paths must begin with a '/'. When unspecified,
// contain characters disallowed from the conventional "path" // all paths from incoming requests are matched.
// part of a URL as defined by RFC 3986. Paths must begin with
// a '/'. If unspecified, the path defaults to a catch all sending
// traffic to the backend.
// +optional // +optional
optional string path = 1; optional string path = 1;
// PathType determines the interpretation of the Path matching. PathType can
// be one of the following values:
// * Exact: Matches the URL path exactly.
// * Prefix: Matches based on a URL path prefix split by '/'. Matching is
// done on a path element by element basis. A path element refers is the
// list of labels in the path split by the '/' separator. A request is a
// match for path p if every p is an element-wise prefix of p of the
// request path. Note that if the last element of the path is a substring
// of the last element in request path, it is not a match (e.g. /foo/bar
// matches /foo/bar/baz, but does not match /foo/barbaz).
// * ImplementationSpecific: Interpretation of the Path matching is up to
// the IngressClass. Implementations can treat this as a separate PathType
// or treat it identically to Prefix or Exact path types.
// Implementations are required to support all path types.
// Defaults to ImplementationSpecific.
optional string pathType = 3;
// Backend defines the referenced service endpoint to which the traffic // Backend defines the referenced service endpoint to which the traffic
// will be forwarded to. // will be forwarded to.
optional IngressBackend backend = 2; optional IngressBackend backend = 2;

View File

@ -177,19 +177,63 @@ type HTTPIngressRuleValue struct {
// options usable by a loadbalancer, like http keep-alive. // options usable by a loadbalancer, like http keep-alive.
} }
// HTTPIngressPath associates a path regex with a backend. Incoming urls matching // PathType represents the type of path referred to by a HTTPIngressPath.
// the path are forwarded to the backend. type PathType string
const (
// PathTypeExact matches the URL path exactly and with case sensitivity.
PathTypeExact = PathType("Exact")
// PathTypePrefix matches based on a URL path prefix split by '/'. Matching
// is case sensitive and done on a path element by element basis. A path
// element refers to the list of labels in the path split by the '/'
// separator. A request is a match for path p if every p is an element-wise
// prefix of p of the request path. Note that if the last element of the
// path is a substring of the last element in request path, it is not a
// match (e.g. /foo/bar matches /foo/bar/baz, but does not match
// /foo/barbaz). If multiple matching paths exist in an Ingress spec, the
// longest matching path is given priority.
// Examples:
// - /foo/bar does not match requests to /foo/barbaz
// - /foo/bar matches request to /foo/bar and /foo/bar/baz
// - /foo and /foo/ both match requests to /foo and /foo/. If both paths are
// present in an Ingress spec, the longest matching path (/foo/) is given
// priority.
PathTypePrefix = PathType("Prefix")
// PathTypeImplementationSpecific matching is up to the IngressClass.
// Implementations can treat this as a separate PathType or treat it
// identically to Prefix or Exact path types.
PathTypeImplementationSpecific = PathType("ImplementationSpecific")
)
// HTTPIngressPath associates a path with a backend. Incoming urls matching the
// path are forwarded to the backend.
type HTTPIngressPath struct { type HTTPIngressPath struct {
// Path is an extended POSIX regex as defined by IEEE Std 1003.1, // Path is matched against the path of an incoming request. Currently it can
// (i.e this follows the egrep/unix syntax, not the perl syntax) // contain characters disallowed from the conventional "path" part of a URL
// matched against the path of an incoming request. Currently it can // as defined by RFC 3986. Paths must begin with a '/'. When unspecified,
// contain characters disallowed from the conventional "path" // all paths from incoming requests are matched.
// part of a URL as defined by RFC 3986. Paths must begin with
// a '/'. If unspecified, the path defaults to a catch all sending
// traffic to the backend.
// +optional // +optional
Path string `json:"path,omitempty" protobuf:"bytes,1,opt,name=path"` Path string `json:"path,omitempty" protobuf:"bytes,1,opt,name=path"`
// PathType determines the interpretation of the Path matching. PathType can
// be one of the following values:
// * Exact: Matches the URL path exactly.
// * Prefix: Matches based on a URL path prefix split by '/'. Matching is
// done on a path element by element basis. A path element refers is the
// list of labels in the path split by the '/' separator. A request is a
// match for path p if every p is an element-wise prefix of p of the
// request path. Note that if the last element of the path is a substring
// of the last element in request path, it is not a match (e.g. /foo/bar
// matches /foo/bar/baz, but does not match /foo/barbaz).
// * ImplementationSpecific: Interpretation of the Path matching is up to
// the IngressClass. Implementations can treat this as a separate PathType
// or treat it identically to Prefix or Exact path types.
// Implementations are required to support all path types.
// Defaults to ImplementationSpecific.
PathType *PathType `json:"pathType,omitempty" protobuf:"bytes,3,opt,name=pathType"`
// Backend defines the referenced service endpoint to which the traffic // Backend defines the referenced service endpoint to which the traffic
// will be forwarded to. // will be forwarded to.
Backend IngressBackend `json:"backend" protobuf:"bytes,2,opt,name=backend"` Backend IngressBackend `json:"backend" protobuf:"bytes,2,opt,name=backend"`

View File

@ -28,9 +28,10 @@ package v1beta1
// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. // AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT.
var map_HTTPIngressPath = map[string]string{ var map_HTTPIngressPath = map[string]string{
"": "HTTPIngressPath associates a path regex with a backend. Incoming urls matching the path are forwarded to the backend.", "": "HTTPIngressPath associates a path with a backend. Incoming urls matching the path are forwarded to the backend.",
"path": "Path is an extended POSIX regex as defined by IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. If unspecified, the path defaults to a catch all sending traffic to the backend.", "path": "Path is matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. When unspecified, all paths from incoming requests are matched.",
"backend": "Backend defines the referenced service endpoint to which the traffic will be forwarded to.", "pathType": "PathType determines the interpretation of the Path matching. PathType can be one of the following values: * Exact: Matches the URL path exactly. * Prefix: Matches based on a URL path prefix split by '/'. Matching is\n done on a path element by element basis. A path element refers is the\n list of labels in the path split by the '/' separator. A request is a\n match for path p if every p is an element-wise prefix of p of the\n request path. Note that if the last element of the path is a substring\n of the last element in request path, it is not a match (e.g. /foo/bar\n matches /foo/bar/baz, but does not match /foo/barbaz).\n* ImplementationSpecific: Interpretation of the Path matching is up to\n the IngressClass. Implementations can treat this as a separate PathType\n or treat it identically to Prefix or Exact path types.\nImplementations are required to support all path types. Defaults to ImplementationSpecific.",
"backend": "Backend defines the referenced service endpoint to which the traffic will be forwarded to.",
} }
func (HTTPIngressPath) SwaggerDoc() map[string]string { func (HTTPIngressPath) SwaggerDoc() map[string]string {

View File

@ -28,6 +28,11 @@ import (
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) { func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) {
*out = *in *out = *in
if in.PathType != nil {
in, out := &in.PathType, &out.PathType
*out = new(PathType)
**out = **in
}
out.Backend = in.Backend out.Backend = in.Backend
return return
} }
@ -48,7 +53,9 @@ func (in *HTTPIngressRuleValue) DeepCopyInto(out *HTTPIngressRuleValue) {
if in.Paths != nil { if in.Paths != nil {
in, out := &in.Paths, &out.Paths in, out := &in.Paths, &out.Paths
*out = make([]HTTPIngressPath, len(*in)) *out = make([]HTTPIngressPath, len(*in))
copy(*out, *in) for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
} }
return return
} }

View File

@ -61,9 +61,10 @@
"paths": [ "paths": [
{ {
"path": "25", "path": "25",
"pathType": "",
"backend": { "backend": {
"serviceName": "26", "serviceName": "26",
"servicePort": "27" "servicePort": -783752440
} }
} }
] ]
@ -75,8 +76,8 @@
"loadBalancer": { "loadBalancer": {
"ingress": [ "ingress": [
{ {
"ip": "28", "ip": "27",
"hostname": "29" "hostname": "28"
} }
] ]
} }

View File

@ -40,8 +40,9 @@ spec:
paths: paths:
- backend: - backend:
serviceName: "26" serviceName: "26"
servicePort: "27" servicePort: -783752440
path: "25" path: "25"
pathType: ""
tls: tls:
- hosts: - hosts:
- "22" - "22"
@ -49,5 +50,5 @@ spec:
status: status:
loadBalancer: loadBalancer:
ingress: ingress:
- hostname: "29" - hostname: "28"
ip: "28" ip: "27"

View File

@ -61,9 +61,10 @@
"paths": [ "paths": [
{ {
"path": "25", "path": "25",
"pathType": "",
"backend": { "backend": {
"serviceName": "26", "serviceName": "26",
"servicePort": "27" "servicePort": -783752440
} }
} }
] ]
@ -75,8 +76,8 @@
"loadBalancer": { "loadBalancer": {
"ingress": [ "ingress": [
{ {
"ip": "28", "ip": "27",
"hostname": "29" "hostname": "28"
} }
] ]
} }

View File

@ -40,8 +40,9 @@ spec:
paths: paths:
- backend: - backend:
serviceName: "26" serviceName: "26"
servicePort: "27" servicePort: -783752440
path: "25" path: "25"
pathType: ""
tls: tls:
- hosts: - hosts:
- "22" - "22"
@ -49,5 +50,5 @@ spec:
status: status:
loadBalancer: loadBalancer:
ingress: ingress:
- hostname: "29" - hostname: "28"
ip: "28" ip: "27"