Merge pull request #862 from aledbf/equals
Avoid reloads implementing Equaler interface
This commit is contained in:
commit
e1bdce0aa2
17 changed files with 1246 additions and 27 deletions
|
@ -53,6 +53,29 @@ type BasicDigest struct {
|
||||||
Secured bool `json:"secured"`
|
Secured bool `json:"secured"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bd1 *BasicDigest) Equal(bd2 *BasicDigest) bool {
|
||||||
|
if bd1 == bd2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if bd1 == nil || bd2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bd1.Type != bd2.Type {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bd1.Realm != bd2.Realm {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bd1.File != bd2.File {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bd1.Secured != bd2.Secured {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
type auth struct {
|
type auth struct {
|
||||||
secretResolver resolver.Secret
|
secretResolver resolver.Secret
|
||||||
authDirectory string
|
authDirectory string
|
||||||
|
|
|
@ -44,7 +44,49 @@ type External struct {
|
||||||
SigninURL string `json:"signinUrl"`
|
SigninURL string `json:"signinUrl"`
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
SendBody bool `json:"sendBody"`
|
SendBody bool `json:"sendBody"`
|
||||||
ResponseHeaders []string `json:"responseHeaders"`
|
ResponseHeaders []string `json:"responseHeaders,omitEmpty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e1 *External) Equal(e2 *External) bool {
|
||||||
|
if e1 == e2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if e1 == nil || e2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.URL != e2.URL {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.Host != e2.Host {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.SigninURL != e2.SigninURL {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.Method != e2.Method {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.SendBody != e2.SendBody {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.Method != e2.Method {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ep1 := range e1.ResponseHeaders {
|
||||||
|
found := false
|
||||||
|
for _, ep2 := range e2.ResponseHeaders {
|
||||||
|
if ep1 == ep2 {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -36,10 +36,27 @@ const (
|
||||||
// AuthSSLConfig contains the AuthSSLCert used for muthual autentication
|
// AuthSSLConfig contains the AuthSSLCert used for muthual autentication
|
||||||
// and the configured ValidationDepth
|
// and the configured ValidationDepth
|
||||||
type AuthSSLConfig struct {
|
type AuthSSLConfig struct {
|
||||||
AuthSSLCert resolver.AuthSSLCert
|
AuthSSLCert resolver.AuthSSLCert `json:"authSSLCert"`
|
||||||
ValidationDepth int `json:"validationDepth"`
|
ValidationDepth int `json:"validationDepth"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (assl1 *AuthSSLConfig) Equal(assl2 *AuthSSLConfig) bool {
|
||||||
|
if assl1 == assl2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if assl1 == nil || assl2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&assl1.AuthSSLCert).Equal(&assl2.AuthSSLCert) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if assl1.ValidationDepth != assl2.ValidationDepth {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// NewParser creates a new TLS authentication annotation parser
|
// NewParser creates a new TLS authentication annotation parser
|
||||||
func NewParser(resolver resolver.AuthCertificate) parser.IngressAnnotation {
|
func NewParser(resolver resolver.AuthCertificate) parser.IngressAnnotation {
|
||||||
return authTLS{resolver}
|
return authTLS{resolver}
|
||||||
|
|
|
@ -36,7 +36,35 @@ const (
|
||||||
|
|
||||||
// SourceRange returns the CIDR
|
// SourceRange returns the CIDR
|
||||||
type SourceRange struct {
|
type SourceRange struct {
|
||||||
CIDR []string `json:"cidr"`
|
CIDR []string `json:"cidr,omitEmpty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sr1 *SourceRange) Equal(sr2 *SourceRange) bool {
|
||||||
|
if sr1 == sr2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if sr1 == nil || sr2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sr1.CIDR) != len(sr2.CIDR) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s1l := range sr1.CIDR {
|
||||||
|
found := false
|
||||||
|
for _, sl2 := range sr2.CIDR {
|
||||||
|
if s1l == sl2 {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
type ipwhitelist struct {
|
type ipwhitelist struct {
|
||||||
|
|
|
@ -44,6 +44,38 @@ type Configuration struct {
|
||||||
CookiePath string `json:"cookiePath"`
|
CookiePath string `json:"cookiePath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l1 *Configuration) Equal(l2 *Configuration) bool {
|
||||||
|
if l1 == l2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if l1 == nil || l2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.BodySize != l2.BodySize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.ConnectTimeout != l2.ConnectTimeout {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.SendTimeout != l2.SendTimeout {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.ReadTimeout != l2.ReadTimeout {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.BufferSize != l2.BufferSize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.CookieDomain != l2.CookieDomain {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.CookiePath != l2.CookiePath {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
type proxy struct {
|
type proxy struct {
|
||||||
backendResolver resolver.DefaultBackend
|
backendResolver resolver.DefaultBackend
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,23 @@ type RateLimit struct {
|
||||||
RPS Zone `json:"rps"`
|
RPS Zone `json:"rps"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rt1 *RateLimit) Equal(rt2 *RateLimit) bool {
|
||||||
|
if rt1 == rt2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if rt1 == nil || rt2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&rt1.Connections).Equal(&rt2.Connections) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&rt1.RPS).Equal(&rt2.RPS) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Zone returns information about the NGINX rate limit (limit_req_zone)
|
// Zone returns information about the NGINX rate limit (limit_req_zone)
|
||||||
// http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone
|
// http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone
|
||||||
type Zone struct {
|
type Zone struct {
|
||||||
|
@ -57,6 +74,29 @@ type Zone struct {
|
||||||
SharedSize int `json:"sharedSize"`
|
SharedSize int `json:"sharedSize"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (z1 *Zone) Equal(z2 *Zone) bool {
|
||||||
|
if z1 == z2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if z1 == nil || z2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if z1.Name != z2.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if z1.Limit != z2.Limit {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if z1.Burst != z2.Burst {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if z1.SharedSize != z2.SharedSize {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
type ratelimit struct {
|
type ratelimit struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,32 @@ type Redirect struct {
|
||||||
AppRoot string `json:"appRoot"`
|
AppRoot string `json:"appRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r1 *Redirect) Equal(r2 *Redirect) bool {
|
||||||
|
if r1 == r2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if r1 == nil || r2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.Target != r2.Target {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.AddBaseURL != r2.AddBaseURL {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.SSLRedirect != r2.SSLRedirect {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.ForceSSLRedirect != r2.ForceSSLRedirect {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if r1.AppRoot != r2.AppRoot {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
type rewrite struct {
|
type rewrite struct {
|
||||||
backendResolver resolver.DefaultBackend
|
backendResolver resolver.DefaultBackend
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package secureupstream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
extensions "k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
||||||
|
|
||||||
|
@ -32,8 +33,8 @@ const (
|
||||||
|
|
||||||
// Secure describes SSL backend configuration
|
// Secure describes SSL backend configuration
|
||||||
type Secure struct {
|
type Secure struct {
|
||||||
Secure bool
|
Secure bool `json:"secure"`
|
||||||
CACert resolver.AuthSSLCert
|
CACert resolver.AuthSSLCert `json:"caCert"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type su struct {
|
type su struct {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -108,6 +109,8 @@ type GenericController struct {
|
||||||
stopLock *sync.Mutex
|
stopLock *sync.Mutex
|
||||||
|
|
||||||
stopCh chan struct{}
|
stopCh chan struct{}
|
||||||
|
|
||||||
|
runningConfig *ingress.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration contains all the settings required by an Ingress controller
|
// Configuration contains all the settings required by an Ingress controller
|
||||||
|
@ -400,14 +403,22 @@ func (ic *GenericController) syncIngress(key interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := ic.cfg.Backend.OnUpdate(ingress.Configuration{
|
pcfg := ingress.Configuration{
|
||||||
Backends: upstreams,
|
Backends: upstreams,
|
||||||
Servers: servers,
|
Servers: servers,
|
||||||
TCPEndpoints: ic.getStreamServices(ic.cfg.TCPConfigMapName, api.ProtocolTCP),
|
TCPEndpoints: ic.getStreamServices(ic.cfg.TCPConfigMapName, api.ProtocolTCP),
|
||||||
UDPEndpoints: ic.getStreamServices(ic.cfg.UDPConfigMapName, api.ProtocolUDP),
|
UDPEndpoints: ic.getStreamServices(ic.cfg.UDPConfigMapName, api.ProtocolUDP),
|
||||||
PassthroughBackends: passUpstreams,
|
PassthroughBackends: passUpstreams,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if ic.runningConfig != nil && ic.runningConfig.Equal(&pcfg) {
|
||||||
|
glog.V(3).Infof("skipping backend reload (no changes detected)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Infof("backend reload required")
|
||||||
|
|
||||||
|
err := ic.cfg.Backend.OnUpdate(pcfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
incReloadErrorCount()
|
incReloadErrorCount()
|
||||||
glog.Errorf("unexpected failure restarting the backend: \n%v", err)
|
glog.Errorf("unexpected failure restarting the backend: \n%v", err)
|
||||||
|
@ -418,6 +429,8 @@ func (ic *GenericController) syncIngress(key interface{}) error {
|
||||||
incReloadCount()
|
incReloadCount()
|
||||||
setSSLExpireTime(servers)
|
setSSLExpireTime(servers)
|
||||||
|
|
||||||
|
ic.runningConfig = &pcfg
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,9 +692,6 @@ func (ic *GenericController) getBackendServers() ([]*ingress.Backend, []*ingress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find a way to make this more readable
|
|
||||||
// The structs must be ordered to always generate the same file
|
|
||||||
// if the content does not change.
|
|
||||||
aUpstreams := make([]*ingress.Backend, 0, len(upstreams))
|
aUpstreams := make([]*ingress.Backend, 0, len(upstreams))
|
||||||
for _, value := range upstreams {
|
for _, value := range upstreams {
|
||||||
if len(value.Endpoints) == 0 {
|
if len(value.Endpoints) == 0 {
|
||||||
|
@ -690,7 +700,6 @@ func (ic *GenericController) getBackendServers() ([]*ingress.Backend, []*ingress
|
||||||
}
|
}
|
||||||
aUpstreams = append(aUpstreams, value)
|
aUpstreams = append(aUpstreams, value)
|
||||||
}
|
}
|
||||||
sort.Sort(ingress.BackendByNameServers(aUpstreams))
|
|
||||||
|
|
||||||
aServers := make([]*ingress.Server, 0, len(servers))
|
aServers := make([]*ingress.Server, 0, len(servers))
|
||||||
for _, value := range servers {
|
for _, value := range servers {
|
||||||
|
@ -847,12 +856,17 @@ func (ic *GenericController) serviceEndpoints(svcKey, backendPort string,
|
||||||
glog.Warningf("service %v does not have any active endpoints", svcKey)
|
glog.Warningf("service %v does not have any active endpoints", svcKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Sort(ingress.EndpointByAddrPort(endps))
|
|
||||||
upstreams = append(upstreams, endps...)
|
upstreams = append(upstreams, endps...)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
for i := range upstreams {
|
||||||
|
j := rand.Intn(i + 1)
|
||||||
|
upstreams[i], upstreams[j] = upstreams[j], upstreams[i]
|
||||||
|
}
|
||||||
|
|
||||||
return upstreams, nil
|
return upstreams, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,3 +51,17 @@ type AuthSSLCert struct {
|
||||||
// PemSHA contains the SHA1 hash of the 'tls.crt' value
|
// PemSHA contains the SHA1 hash of the 'tls.crt' value
|
||||||
PemSHA string `json:"pemSha"`
|
PemSHA string `json:"pemSha"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (asslc1 *AuthSSLCert) Equal(assl2 *AuthSSLCert) bool {
|
||||||
|
if asslc1.Secret != assl2.Secret {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if asslc1.CAFileName != assl2.CAFileName {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if asslc1.PemSHA != assl2.PemSHA {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -17,9 +17,10 @@ limitations under the License.
|
||||||
package ingress
|
package ingress
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// BackendByNameServers sorts upstreams by name
|
// BackendByNameServers sorts upstreams by name
|
||||||
|
|
74
core/pkg/ingress/type_equals_test.go
Normal file
74
core/pkg/ingress/type_equals_test.go
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 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 ingress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEqualConfiguration(t *testing.T) {
|
||||||
|
ap, _ := filepath.Abs("../../../tests/manifests/configuration-a.json")
|
||||||
|
a, err := readJSON(ap)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error reading JSON file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bp, _ := filepath.Abs("../../../tests/manifests/configuration-b.json")
|
||||||
|
b, err := readJSON(bp)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error reading JSON file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cp, _ := filepath.Abs("../../../tests/manifests/configuration-c.json")
|
||||||
|
c, err := readJSON(cp)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error reading JSON file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.Equal(b) {
|
||||||
|
t.Errorf("expected equal configurations (configuration-a.json and configuration-b.json)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !b.Equal(a) {
|
||||||
|
t.Errorf("expected equal configurations (configuration-a.json and configuration-b.json)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Equal(c) {
|
||||||
|
t.Errorf("expected equal configurations (configuration-a.json and configuration-c.json)")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func readJSON(p string) (*Configuration, error) {
|
||||||
|
f, err := os.Open(p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var c Configuration
|
||||||
|
|
||||||
|
d := json.NewDecoder(f)
|
||||||
|
err = d.Decode(&c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &c, nil
|
||||||
|
}
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
||||||
package ingress
|
package ingress
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
@ -33,7 +35,6 @@ import (
|
||||||
"k8s.io/ingress/core/pkg/ingress/defaults"
|
"k8s.io/ingress/core/pkg/ingress/defaults"
|
||||||
"k8s.io/ingress/core/pkg/ingress/resolver"
|
"k8s.io/ingress/core/pkg/ingress/resolver"
|
||||||
"k8s.io/ingress/core/pkg/ingress/store"
|
"k8s.io/ingress/core/pkg/ingress/store"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -73,8 +74,6 @@ type Controller interface {
|
||||||
// https://k8s.io/ingress/core/blob/master/pkg/ingress/types.go#L83
|
// https://k8s.io/ingress/core/blob/master/pkg/ingress/types.go#L83
|
||||||
// The backend returns an error if was not possible to update the configuration.
|
// The backend returns an error if was not possible to update the configuration.
|
||||||
//
|
//
|
||||||
// The returned configuration is then passed to test, and then to reload
|
|
||||||
// if there is no errors.
|
|
||||||
OnUpdate(Configuration) error
|
OnUpdate(Configuration) error
|
||||||
// ConfigMap content of --configmap
|
// ConfigMap content of --configmap
|
||||||
SetConfig(*api.ConfigMap)
|
SetConfig(*api.ConfigMap)
|
||||||
|
@ -125,9 +124,9 @@ type BackendInfo struct {
|
||||||
type Configuration struct {
|
type Configuration struct {
|
||||||
// Backends are a list of backends used by all the Ingress rules in the
|
// Backends are a list of backends used by all the Ingress rules in the
|
||||||
// ingress controller. This list includes the default backend
|
// ingress controller. This list includes the default backend
|
||||||
Backends []*Backend `json:"namespace"`
|
Backends []*Backend `json:"backends,omitEmpty"`
|
||||||
// Servers
|
// Servers
|
||||||
Servers []*Server `json:"servers"`
|
Servers []*Server `json:"servers,omitEmpty"`
|
||||||
// TCPEndpoints contain endpoints for tcp streams handled by this backend
|
// TCPEndpoints contain endpoints for tcp streams handled by this backend
|
||||||
// +optional
|
// +optional
|
||||||
TCPEndpoints []L4Service `json:"tcpEndpoints,omitempty"`
|
TCPEndpoints []L4Service `json:"tcpEndpoints,omitempty"`
|
||||||
|
@ -144,7 +143,7 @@ type Configuration struct {
|
||||||
type Backend struct {
|
type Backend struct {
|
||||||
// Name represents an unique api.Service name formatted as <namespace>-<name>-<port>
|
// Name represents an unique api.Service name formatted as <namespace>-<name>-<port>
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Service *api.Service `json:"service"`
|
Service *api.Service `json:"service,omitempty"`
|
||||||
Port intstr.IntOrString `json:"port"`
|
Port intstr.IntOrString `json:"port"`
|
||||||
// This indicates if the communication protocol between the backend and the endpoint is HTTP or HTTPS
|
// This indicates if the communication protocol between the backend and the endpoint is HTTP or HTTPS
|
||||||
// Allowing the use of HTTPS
|
// Allowing the use of HTTPS
|
||||||
|
@ -157,9 +156,9 @@ type Backend struct {
|
||||||
// SSLPassthrough indicates that Ingress controller will delegate TLS termination to the endpoints.
|
// SSLPassthrough indicates that Ingress controller will delegate TLS termination to the endpoints.
|
||||||
SSLPassthrough bool `json:"sslPassthrough"`
|
SSLPassthrough bool `json:"sslPassthrough"`
|
||||||
// Endpoints contains the list of endpoints currently running
|
// Endpoints contains the list of endpoints currently running
|
||||||
Endpoints []Endpoint `json:"endpoints"`
|
Endpoints []Endpoint `json:"endpoints,omitempty"`
|
||||||
// StickySessionAffinitySession contains the StickyConfig object with stickness configuration
|
// StickySessionAffinitySession contains the StickyConfig object with stickness configuration
|
||||||
SessionAffinity SessionAffinityConfig
|
SessionAffinity SessionAffinityConfig `json:"sessionAffinityConfig"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionAffinityConfig describes different affinity configurations for new sessions.
|
// SessionAffinityConfig describes different affinity configurations for new sessions.
|
||||||
|
@ -170,7 +169,7 @@ type Backend struct {
|
||||||
// about honoring updates.
|
// about honoring updates.
|
||||||
type SessionAffinityConfig struct {
|
type SessionAffinityConfig struct {
|
||||||
AffinityType string `json:"name"`
|
AffinityType string `json:"name"`
|
||||||
CookieSessionAffinity CookieSessionAffinity
|
CookieSessionAffinity CookieSessionAffinity `json:"cookieSessionAffinity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CookieSessionAffinity defines the structure used in Affinity configured by Cookies.
|
// CookieSessionAffinity defines the structure used in Affinity configured by Cookies.
|
||||||
|
@ -254,7 +253,7 @@ type Location struct {
|
||||||
BasicDigestAuth auth.BasicDigest `json:"basicDigestAuth,omitempty"`
|
BasicDigestAuth auth.BasicDigest `json:"basicDigestAuth,omitempty"`
|
||||||
// Denied returns an error when this location cannot not be allowed
|
// Denied returns an error when this location cannot not be allowed
|
||||||
// Requesting a denied location should return HTTP code 403.
|
// Requesting a denied location should return HTTP code 403.
|
||||||
Denied error
|
Denied error `json:"denied,omitempty"`
|
||||||
// EnableCORS indicates if path must support CORS
|
// EnableCORS indicates if path must support CORS
|
||||||
// +optional
|
// +optional
|
||||||
EnableCORS bool `json:"enableCors,omitempty"`
|
EnableCORS bool `json:"enableCors,omitempty"`
|
||||||
|
@ -295,7 +294,7 @@ type Location struct {
|
||||||
// The endpoints must provide the TLS termination exposing the required SSL certificate.
|
// The endpoints must provide the TLS termination exposing the required SSL certificate.
|
||||||
// The ingress controller only pipes the underlying TCP connection
|
// The ingress controller only pipes the underlying TCP connection
|
||||||
type SSLPassthroughBackend struct {
|
type SSLPassthroughBackend struct {
|
||||||
Service *api.Service `json:"service"`
|
Service *api.Service `json:"service,omitEmpty"`
|
||||||
Port intstr.IntOrString `json:"port"`
|
Port intstr.IntOrString `json:"port"`
|
||||||
// Backend describes the endpoints to use.
|
// Backend describes the endpoints to use.
|
||||||
Backend string `json:"namespace,omitempty"`
|
Backend string `json:"namespace,omitempty"`
|
||||||
|
@ -310,7 +309,7 @@ type L4Service struct {
|
||||||
// Backend of the service
|
// Backend of the service
|
||||||
Backend L4Backend `json:"backend"`
|
Backend L4Backend `json:"backend"`
|
||||||
// Endpoints active endpoints of the service
|
// Endpoints active endpoints of the service
|
||||||
Endpoints []Endpoint `json:"endpoins"`
|
Endpoints []Endpoint `json:"endpoins,omitEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// L4Backend describes the kubernetes service behind L4 Ingress service
|
// L4Backend describes the kubernetes service behind L4 Ingress service
|
||||||
|
|
460
core/pkg/ingress/types_equals.go
Normal file
460
core/pkg/ingress/types_equals.go
Normal file
|
@ -0,0 +1,460 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 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 ingress
|
||||||
|
|
||||||
|
func (bi1 *BackendInfo) Equal(bi2 *BackendInfo) bool {
|
||||||
|
if bi1 == bi2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if bi1 == nil || bi2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bi1.Name != bi2.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bi1.Release != bi2.Release {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bi1.Build != bi2.Build {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if bi1.Repository != bi2.Repository {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c1 *Configuration) Equal(c2 *Configuration) bool {
|
||||||
|
if c1 == c2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if c1 == nil || c2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c1.Backends) != len(c2.Backends) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c1b := range c1.Backends {
|
||||||
|
found := false
|
||||||
|
for _, c2b := range c2.Backends {
|
||||||
|
if c1b.Equal(c2b) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c1s := range c1.Servers {
|
||||||
|
found := false
|
||||||
|
for _, c2s := range c2.Servers {
|
||||||
|
if c1s.Equal(c2s) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c1.TCPEndpoints) != len(c2.TCPEndpoints) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tcp1 := range c1.TCPEndpoints {
|
||||||
|
found := false
|
||||||
|
for _, tcp2 := range c2.TCPEndpoints {
|
||||||
|
if (&tcp1).Equal(&tcp2) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c1.UDPEndpoints) != len(c2.UDPEndpoints) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, udp1 := range c1.UDPEndpoints {
|
||||||
|
found := false
|
||||||
|
for _, udp2 := range c2.UDPEndpoints {
|
||||||
|
if (&udp1).Equal(&udp2) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(c1.PassthroughBackends) != len(c2.PassthroughBackends) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ptb1 := range c1.PassthroughBackends {
|
||||||
|
found := false
|
||||||
|
for _, ptb2 := range c2.PassthroughBackends {
|
||||||
|
if ptb1.Equal(ptb2) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b1 *Backend) Equal(b2 *Backend) bool {
|
||||||
|
if b1 == b2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if b1 == nil || b2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b1.Name != b2.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b1.Service == nil && b2.Service != nil) ||
|
||||||
|
(b1.Service != nil && b2.Service == nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if b1.Service != nil && b2.Service != nil {
|
||||||
|
if b1.Service.GetNamespace() != b2.Service.GetNamespace() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b1.Service.GetName() != b2.Service.GetName() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b1.Service.GetResourceVersion() != b2.Service.GetResourceVersion() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if b1.Port != b2.Port {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b1.Secure != b2.Secure {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&b1.SecureCACert).Equal(&b2.SecureCACert) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b1.SSLPassthrough != b2.SSLPassthrough {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&b1.SessionAffinity).Equal(&b2.SessionAffinity) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b1.Endpoints) != len(b2.Endpoints) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, udp1 := range b1.Endpoints {
|
||||||
|
found := false
|
||||||
|
for _, udp2 := range b2.Endpoints {
|
||||||
|
if (&udp1).Equal(&udp2) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sac1 *SessionAffinityConfig) Equal(sac2 *SessionAffinityConfig) bool {
|
||||||
|
if sac1 == sac2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if sac1 == nil || sac2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if sac1.AffinityType != sac2.AffinityType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&sac1.CookieSessionAffinity).Equal(&sac2.CookieSessionAffinity) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (csa1 *CookieSessionAffinity) Equal(csa2 *CookieSessionAffinity) bool {
|
||||||
|
if csa1 == csa2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if csa1 == nil || csa2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if csa1.Name != csa2.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if csa1.Hash != csa2.Hash {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal checks the equality against an Endpoint
|
||||||
|
func (e1 *Endpoint) Equal(e2 *Endpoint) bool {
|
||||||
|
if e1 == e2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if e1 == nil || e2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.Address != e2.Address {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.Port != e2.Port {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.MaxFails != e2.MaxFails {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.FailTimeout != e2.FailTimeout {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s1 *Server) Equal(s2 *Server) bool {
|
||||||
|
if s1 == s2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if s1 == nil || s2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s1.Hostname != s2.Hostname {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s1.SSLPassthrough != s2.SSLPassthrough {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s1.SSLCertificate != s2.SSLCertificate {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s1.SSLPemChecksum != s2.SSLPemChecksum {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s1.Locations) != len(s2.Locations) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s1l := range s1.Locations {
|
||||||
|
found := false
|
||||||
|
for _, sl2 := range s2.Locations {
|
||||||
|
if s1l.Equal(sl2) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l1 *Location) Equal(l2 *Location) bool {
|
||||||
|
if l1 == l2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if l1 == nil || l2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.Path != l2.Path {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.IsDefBackend != l2.IsDefBackend {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.Backend != l2.Backend {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l1.Service == nil && l2.Service != nil) ||
|
||||||
|
(l1.Service != nil && l2.Service == nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if l1.Service != nil && l2.Service != nil {
|
||||||
|
if l1.Service.GetNamespace() != l2.Service.GetNamespace() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.Service.GetName() != l2.Service.GetName() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.Service.GetResourceVersion() != l2.Service.GetResourceVersion() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if l1.Port.StrVal != l2.Port.StrVal {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&l1.BasicDigestAuth).Equal(&l2.BasicDigestAuth) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.Denied != l2.Denied {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.EnableCORS != l2.EnableCORS {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&l1.ExternalAuth).Equal(&l2.ExternalAuth) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&l1.RateLimit).Equal(&l2.RateLimit) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&l1.Redirect).Equal(&l2.Redirect) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&l1.Whitelist).Equal(&l2.Whitelist) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&l1.Proxy).Equal(&l2.Proxy) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&l1.CertificateAuth).Equal(&l2.CertificateAuth) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.UsePortInRedirects != l2.UsePortInRedirects {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l1.ConfigurationSnippet != l2.ConfigurationSnippet {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ptb1 *SSLPassthroughBackend) Equal(ptb2 *SSLPassthroughBackend) bool {
|
||||||
|
if ptb1 == ptb2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ptb1 == nil || ptb2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ptb1.Backend != ptb2.Backend {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ptb1.Hostname != ptb2.Hostname {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ptb1.Port != ptb2.Port {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (ptb1.Service == nil && ptb2.Service != nil) ||
|
||||||
|
(ptb1.Service != nil && ptb2.Service == nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ptb1.Service != nil && ptb2.Service != nil {
|
||||||
|
if ptb1.Service.GetNamespace() != ptb2.Service.GetNamespace() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ptb1.Service.GetName() != ptb2.Service.GetName() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ptb1.Service.GetResourceVersion() != ptb2.Service.GetResourceVersion() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e1 *L4Service) Equal(e2 *L4Service) bool {
|
||||||
|
if e1 == e2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if e1 == nil || e2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if e1.Port != e2.Port {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !(&e1.Backend).Equal(&e2.Backend) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(e1.Endpoints) != len(e2.Endpoints) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ep1 := range e1.Endpoints {
|
||||||
|
found := false
|
||||||
|
for _, ep2 := range e2.Endpoints {
|
||||||
|
if (&ep1).Equal(&ep2) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l4b1 *L4Backend) Equal(l4b2 *L4Backend) bool {
|
||||||
|
if l4b1 == l4b2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if l4b1 == nil || l4b2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l4b1.Port != l4b2.Port {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l4b1.Name != l4b2.Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l4b1.Namespace != l4b2.Namespace {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if l4b1.Protocol != l4b2.Protocol {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
97
tests/manifests/configuration-a.json
Normal file
97
tests/manifests/configuration-a.json
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
{
|
||||||
|
"backends": [{
|
||||||
|
"name": "upstream-default-backend",
|
||||||
|
"port": 0,
|
||||||
|
"secure": false,
|
||||||
|
"secureCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"endpoints": [{
|
||||||
|
"address": "172.17.0.5",
|
||||||
|
"port": "8080",
|
||||||
|
"maxFails": 0,
|
||||||
|
"failTimeout": 0
|
||||||
|
}],
|
||||||
|
"sessionAffinityConfig": {
|
||||||
|
"name": "",
|
||||||
|
"cookieSessionAffinity": {
|
||||||
|
"name": "",
|
||||||
|
"hash": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"servers": [{
|
||||||
|
"hostname": "_",
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"sslCertificate": "/ingress-controller/ssl/default-fake-certificate.pem",
|
||||||
|
"sslExpireTime": "0001-01-01T00:00:00Z",
|
||||||
|
"sslPemChecksum": "4302f26460e2c49c9a69229449efefb30dc42a9a",
|
||||||
|
"locations": [{
|
||||||
|
"path": "/",
|
||||||
|
"isDefBackend": true,
|
||||||
|
"backend": "upstream-default-backend",
|
||||||
|
"service": null,
|
||||||
|
"port": 0,
|
||||||
|
"basicDigestAuth": {
|
||||||
|
"type": "",
|
||||||
|
"realm": "",
|
||||||
|
"file": "",
|
||||||
|
"secured": false
|
||||||
|
},
|
||||||
|
"externalAuth": {
|
||||||
|
"url": "",
|
||||||
|
"host": "",
|
||||||
|
"signinUrl": "",
|
||||||
|
"method": "",
|
||||||
|
"sendBody": false,
|
||||||
|
"responseHeaders": null
|
||||||
|
},
|
||||||
|
"rateLimit": {
|
||||||
|
"connections": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
},
|
||||||
|
"rps": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirect": {
|
||||||
|
"target": "",
|
||||||
|
"addBaseUrl": false,
|
||||||
|
"sslRedirect": false,
|
||||||
|
"forceSSLRedirect": false,
|
||||||
|
"appRoot": ""
|
||||||
|
},
|
||||||
|
"whitelist": {
|
||||||
|
"cidr": null
|
||||||
|
},
|
||||||
|
"proxy": {
|
||||||
|
"bodySize": "1m",
|
||||||
|
"conectTimeout": 5,
|
||||||
|
"sendTimeout": 60,
|
||||||
|
"readTimeout": 60,
|
||||||
|
"bufferSize": "4k",
|
||||||
|
"cookieDomain": "off",
|
||||||
|
"cookiePath": "off"
|
||||||
|
},
|
||||||
|
"certificateAuth": {
|
||||||
|
"authSSLCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"validationDepth": 0
|
||||||
|
},
|
||||||
|
"use-port-in-redirects": false,
|
||||||
|
"configuration-snippet": ""
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
97
tests/manifests/configuration-b.json
Normal file
97
tests/manifests/configuration-b.json
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
{
|
||||||
|
"backends": [{
|
||||||
|
"name": "upstream-default-backend",
|
||||||
|
"port": 0,
|
||||||
|
"secure": false,
|
||||||
|
"secureCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"endpoints": [{
|
||||||
|
"address": "172.17.0.5",
|
||||||
|
"port": "8080",
|
||||||
|
"maxFails": 0,
|
||||||
|
"failTimeout": 0
|
||||||
|
}],
|
||||||
|
"sessionAffinityConfig": {
|
||||||
|
"name": "",
|
||||||
|
"cookieSessionAffinity": {
|
||||||
|
"name": "",
|
||||||
|
"hash": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"servers": [{
|
||||||
|
"hostname": "_",
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"sslCertificate": "/ingress-controller/ssl/default-fake-certificate.pem",
|
||||||
|
"sslExpireTime": "0001-01-01T00:00:00Z",
|
||||||
|
"sslPemChecksum": "4302f26460e2c49c9a69229449efefb30dc42a9a",
|
||||||
|
"locations": [{
|
||||||
|
"path": "/",
|
||||||
|
"isDefBackend": true,
|
||||||
|
"backend": "upstream-default-backend",
|
||||||
|
"service": null,
|
||||||
|
"port": 0,
|
||||||
|
"basicDigestAuth": {
|
||||||
|
"type": "",
|
||||||
|
"realm": "",
|
||||||
|
"file": "",
|
||||||
|
"secured": false
|
||||||
|
},
|
||||||
|
"externalAuth": {
|
||||||
|
"url": "",
|
||||||
|
"host": "",
|
||||||
|
"signinUrl": "",
|
||||||
|
"method": "",
|
||||||
|
"sendBody": false,
|
||||||
|
"responseHeaders": null
|
||||||
|
},
|
||||||
|
"rateLimit": {
|
||||||
|
"connections": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
},
|
||||||
|
"rps": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirect": {
|
||||||
|
"target": "",
|
||||||
|
"addBaseUrl": false,
|
||||||
|
"sslRedirect": false,
|
||||||
|
"forceSSLRedirect": false,
|
||||||
|
"appRoot": ""
|
||||||
|
},
|
||||||
|
"whitelist": {
|
||||||
|
"cidr": null
|
||||||
|
},
|
||||||
|
"proxy": {
|
||||||
|
"bodySize": "1m",
|
||||||
|
"conectTimeout": 5,
|
||||||
|
"sendTimeout": 60,
|
||||||
|
"readTimeout": 60,
|
||||||
|
"bufferSize": "4k",
|
||||||
|
"cookieDomain": "off",
|
||||||
|
"cookiePath": "off"
|
||||||
|
},
|
||||||
|
"certificateAuth": {
|
||||||
|
"authSSLCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"validationDepth": 0
|
||||||
|
},
|
||||||
|
"use-port-in-redirects": false,
|
||||||
|
"configuration-snippet": ""
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
254
tests/manifests/configuration-c.json
Normal file
254
tests/manifests/configuration-c.json
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
{
|
||||||
|
"backends": [{
|
||||||
|
"name": "upstream-default-backend",
|
||||||
|
"service": null,
|
||||||
|
"port": 0,
|
||||||
|
"secure": false,
|
||||||
|
"secureCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"endpoints": [{
|
||||||
|
"address": "172.17.0.8",
|
||||||
|
"port": "8080",
|
||||||
|
"maxFails": 0,
|
||||||
|
"failTimeout": 0
|
||||||
|
}],
|
||||||
|
"SessionAffinity": {
|
||||||
|
"name": "",
|
||||||
|
"CookieSessionAffinity": {
|
||||||
|
"name": "",
|
||||||
|
"hash": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"name": "deis-deis-controller-8000",
|
||||||
|
"service": {
|
||||||
|
"metadata": {
|
||||||
|
"name": "deis-controller",
|
||||||
|
"namespace": "deis",
|
||||||
|
"selfLink": "/api/v1/namespaces/deis/services/deis-controller",
|
||||||
|
"uid": "1cba01a8-50b0-11e7-a384-0800270f5693",
|
||||||
|
"resourceVersion": "532",
|
||||||
|
"creationTimestamp": "2017-06-14T03:18:18Z",
|
||||||
|
"labels": {
|
||||||
|
"heritage": "deis"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"ports": [{
|
||||||
|
"name": "http",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"port": 8000,
|
||||||
|
"targetPort": 8000,
|
||||||
|
"nodePort": 30171
|
||||||
|
}],
|
||||||
|
"selector": {
|
||||||
|
"app": "deis-controller"
|
||||||
|
},
|
||||||
|
"clusterIP": "10.0.0.198",
|
||||||
|
"type": "NodePort",
|
||||||
|
"sessionAffinity": "None"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"loadBalancer": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"port": 8000,
|
||||||
|
"secure": false,
|
||||||
|
"secureCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"endpoints": [{
|
||||||
|
"address": "172.17.0.7",
|
||||||
|
"port": "8000",
|
||||||
|
"maxFails": 0,
|
||||||
|
"failTimeout": 0
|
||||||
|
}],
|
||||||
|
"SessionAffinity": {
|
||||||
|
"name": "",
|
||||||
|
"CookieSessionAffinity": {
|
||||||
|
"name": "",
|
||||||
|
"hash": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"servers": [{
|
||||||
|
"hostname": "_",
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"sslCertificate": "/ingress-controller/ssl/default-fake-certificate.pem",
|
||||||
|
"sslExpireTime": "0001-01-01T00:00:00Z",
|
||||||
|
"sslPemChecksum": "123b44425920a2e4825ae779fba0e6e07fbac03d",
|
||||||
|
"locations": [{
|
||||||
|
"path": "/",
|
||||||
|
"isDefBackend": true,
|
||||||
|
"backend": "upstream-default-backend",
|
||||||
|
"service": null,
|
||||||
|
"port": 0,
|
||||||
|
"basicDigestAuth": {
|
||||||
|
"type": "",
|
||||||
|
"realm": "",
|
||||||
|
"file": "",
|
||||||
|
"secured": false
|
||||||
|
},
|
||||||
|
"Denied": null,
|
||||||
|
"externalAuth": {
|
||||||
|
"url": "",
|
||||||
|
"host": "",
|
||||||
|
"signinUrl": "",
|
||||||
|
"method": "",
|
||||||
|
"sendBody": false,
|
||||||
|
"responseHeaders": null
|
||||||
|
},
|
||||||
|
"rateLimit": {
|
||||||
|
"connections": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
},
|
||||||
|
"rps": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirect": {
|
||||||
|
"target": "",
|
||||||
|
"addBaseUrl": false,
|
||||||
|
"sslRedirect": false,
|
||||||
|
"forceSSLRedirect": false,
|
||||||
|
"appRoot": ""
|
||||||
|
},
|
||||||
|
"whitelist": {
|
||||||
|
"cidr": null
|
||||||
|
},
|
||||||
|
"proxy": {
|
||||||
|
"bodySize": "1g",
|
||||||
|
"conectTimeout": 5,
|
||||||
|
"sendTimeout": 60,
|
||||||
|
"readTimeout": 60,
|
||||||
|
"bufferSize": "4k",
|
||||||
|
"cookieDomain": "off",
|
||||||
|
"cookiePath": "off"
|
||||||
|
},
|
||||||
|
"certificateAuth": {
|
||||||
|
"AuthSSLCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"validationDepth": 0
|
||||||
|
},
|
||||||
|
"use-port-in-redirects": false,
|
||||||
|
"configuration-snippet": ""
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"hostname": "deis.minikube",
|
||||||
|
"sslPassthrough": false,
|
||||||
|
"sslCertificate": "",
|
||||||
|
"sslExpireTime": "0001-01-01T00:00:00Z",
|
||||||
|
"sslPemChecksum": "",
|
||||||
|
"locations": [{
|
||||||
|
"path": "/",
|
||||||
|
"isDefBackend": false,
|
||||||
|
"backend": "deis-deis-controller-8000",
|
||||||
|
"service": {
|
||||||
|
"metadata": {
|
||||||
|
"name": "deis-controller",
|
||||||
|
"namespace": "deis",
|
||||||
|
"selfLink": "/api/v1/namespaces/deis/services/deis-controller",
|
||||||
|
"uid": "1cba01a8-50b0-11e7-a384-0800270f5693",
|
||||||
|
"resourceVersion": "532",
|
||||||
|
"creationTimestamp": "2017-06-14T03:18:18Z",
|
||||||
|
"labels": {
|
||||||
|
"heritage": "deis"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"ports": [{
|
||||||
|
"name": "http",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"port": 8000,
|
||||||
|
"targetPort": 8000,
|
||||||
|
"nodePort": 30171
|
||||||
|
}],
|
||||||
|
"selector": {
|
||||||
|
"app": "deis-controller"
|
||||||
|
},
|
||||||
|
"clusterIP": "10.0.0.198",
|
||||||
|
"type": "NodePort",
|
||||||
|
"sessionAffinity": "None"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"loadBalancer": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"port": 8000,
|
||||||
|
"basicDigestAuth": {
|
||||||
|
"type": "",
|
||||||
|
"realm": "",
|
||||||
|
"file": "",
|
||||||
|
"secured": false
|
||||||
|
},
|
||||||
|
"Denied": null,
|
||||||
|
"externalAuth": {
|
||||||
|
"url": "",
|
||||||
|
"host": "",
|
||||||
|
"signinUrl": "",
|
||||||
|
"method": "",
|
||||||
|
"sendBody": false,
|
||||||
|
"responseHeaders": null
|
||||||
|
},
|
||||||
|
"rateLimit": {
|
||||||
|
"connections": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
},
|
||||||
|
"rps": {
|
||||||
|
"name": "",
|
||||||
|
"limit": 0,
|
||||||
|
"burst": 0,
|
||||||
|
"sharedSize": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"redirect": {
|
||||||
|
"target": "",
|
||||||
|
"addBaseUrl": false,
|
||||||
|
"sslRedirect": true,
|
||||||
|
"forceSSLRedirect": false,
|
||||||
|
"appRoot": ""
|
||||||
|
},
|
||||||
|
"whitelist": {
|
||||||
|
"cidr": null
|
||||||
|
},
|
||||||
|
"proxy": {
|
||||||
|
"bodySize": "1g",
|
||||||
|
"conectTimeout": 5,
|
||||||
|
"sendTimeout": 60,
|
||||||
|
"readTimeout": 60,
|
||||||
|
"bufferSize": "4k",
|
||||||
|
"cookieDomain": "off",
|
||||||
|
"cookiePath": "off"
|
||||||
|
},
|
||||||
|
"certificateAuth": {
|
||||||
|
"AuthSSLCert": {
|
||||||
|
"secret": "",
|
||||||
|
"caFilename": "",
|
||||||
|
"pemSha": ""
|
||||||
|
},
|
||||||
|
"validationDepth": 0
|
||||||
|
},
|
||||||
|
"use-port-in-redirects": false,
|
||||||
|
"configuration-snippet": ""
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
Loading…
Reference in a new issue