Merge branch 'kubernetes:main' into main
This commit is contained in:
commit
9e79a36020
664 changed files with 19886 additions and 10226 deletions
|
|
@ -66,12 +66,12 @@ type SSLCert struct {
|
|||
}
|
||||
|
||||
// GetObjectKind implements the ObjectKind interface as a noop
|
||||
func (s SSLCert) GetObjectKind() schema.ObjectKind {
|
||||
func (s *SSLCert) GetObjectKind() schema.ObjectKind {
|
||||
return schema.EmptyObjectKind
|
||||
}
|
||||
|
||||
// Identifier returns a the couple issuer / serial number if they both exist, an empty string otherwise
|
||||
func (s SSLCert) Identifier() string {
|
||||
func (s *SSLCert) Identifier() string {
|
||||
if s.Certificate != nil {
|
||||
if s.Certificate.SerialNumber != nil {
|
||||
return fmt.Sprintf("%s-%s", s.Certificate.Issuer.SerialNumber, s.Certificate.SerialNumber.String())
|
||||
|
|
@ -81,7 +81,7 @@ func (s SSLCert) Identifier() string {
|
|||
}
|
||||
|
||||
// HashInclude defines if a field should be used or not to calculate the hash
|
||||
func (s SSLCert) HashInclude(field string, v interface{}) (bool, error) {
|
||||
func (s *SSLCert) HashInclude(field string, _ interface{}) (bool, error) {
|
||||
switch field {
|
||||
case "PemSHA", "CASHA", "ExpireTime":
|
||||
return true, nil
|
||||
|
|
|
|||
|
|
@ -27,15 +27,15 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/annotations/authtls"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/connection"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/customheaders"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/fastcgi"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/globalratelimit"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ipallowlist"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ipdenylist"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/log"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/mirror"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/opentelemetry"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/opentracing"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/proxy"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/proxyssl"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/ratelimit"
|
||||
|
|
@ -73,7 +73,7 @@ type Configuration struct {
|
|||
|
||||
DefaultSSLCertificate *SSLCert `json:"-"`
|
||||
|
||||
StreamSnippets []string
|
||||
StreamSnippets []string `json:"StreamSnippets"`
|
||||
}
|
||||
|
||||
// Backend describes one or more remote server/s (endpoints) associated with a service
|
||||
|
|
@ -129,7 +129,7 @@ type TrafficShapingPolicy struct {
|
|||
}
|
||||
|
||||
// HashInclude defines if a field should be used or not to calculate the hash
|
||||
func (s Backend) HashInclude(field string, v interface{}) (bool, error) {
|
||||
func (b *Backend) HashInclude(field string, _ interface{}) (bool, error) {
|
||||
switch field {
|
||||
case "Endpoints":
|
||||
return false, nil
|
||||
|
|
@ -224,7 +224,7 @@ type Server struct {
|
|||
// is required.
|
||||
// The chain in the execution order of annotations should be:
|
||||
// - Denylist
|
||||
// - Whitelist
|
||||
// - Allowlist
|
||||
// - RateLimit
|
||||
// - BasicDigestAuth
|
||||
// - ExternalAuth
|
||||
|
|
@ -264,7 +264,8 @@ type Location struct {
|
|||
BasicDigestAuth auth.Config `json:"basicDigestAuth,omitempty"`
|
||||
// Denied returns an error when this location cannot not be allowed
|
||||
// Requesting a denied location should return HTTP code 403.
|
||||
Denied *string `json:"denied,omitempty"`
|
||||
Denied *string `json:"denied,omitempty"`
|
||||
CustomHeaders customheaders.Config `json:"customHeaders,omitempty"`
|
||||
// CorsConfig returns the Cors Configuration for the ingress rule
|
||||
// +optional
|
||||
CorsConfig cors.Config `json:"corsConfig,omitempty"`
|
||||
|
|
@ -298,10 +299,10 @@ type Location struct {
|
|||
// addresses or networks are allowed.
|
||||
// +optional
|
||||
Denylist ipdenylist.SourceRange `json:"denylist,omitempty"`
|
||||
// Whitelist indicates only connections from certain client
|
||||
// Allowlist indicates only connections from certain client
|
||||
// addresses or networks are allowed.
|
||||
// +optional
|
||||
Whitelist ipwhitelist.SourceRange `json:"whitelist,omitempty"`
|
||||
Allowlist ipallowlist.SourceRange `json:"allowlist,omitempty"`
|
||||
// Proxy contains information about timeouts and buffer sizes
|
||||
// to be used in connections against endpoints
|
||||
// +optional
|
||||
|
|
@ -346,6 +347,11 @@ type Location struct {
|
|||
// CustomHTTPErrors specifies the error codes that should be intercepted.
|
||||
// +optional
|
||||
CustomHTTPErrors []int `json:"custom-http-errors"`
|
||||
// ProxyInterceptErrors disables error intecepting when using CustomHTTPErrors
|
||||
// e.g. custom 404 and 503 when service-a does not exist or is not available
|
||||
// but service-a can return 404 and 503 error codes without intercept
|
||||
// +optional
|
||||
DisableProxyInterceptErrors bool `json:"disable-proxy-intercept-errors"`
|
||||
// ModSecurity allows to enable and configure modsecurity
|
||||
// +optional
|
||||
ModSecurity modsecurity.Config `json:"modsecurity"`
|
||||
|
|
@ -354,9 +360,6 @@ type Location struct {
|
|||
// Mirror allows you to mirror traffic to a "test" backend
|
||||
// +optional
|
||||
Mirror mirror.Config `json:"mirror,omitempty"`
|
||||
// Opentracing allows the global opentracing setting to be overridden for a location
|
||||
// +optional
|
||||
Opentracing opentracing.Config `json:"opentracing"`
|
||||
// Opentelemetry allows the global opentelemetry setting to be overridden for a location
|
||||
// +optional
|
||||
Opentelemetry opentelemetry.Config `json:"opentelemetry"`
|
||||
|
|
@ -410,5 +413,4 @@ type Ingress struct {
|
|||
}
|
||||
|
||||
// GeneralConfig holds the definition of lua general configuration data
|
||||
type GeneralConfig struct {
|
||||
}
|
||||
type GeneralConfig struct{}
|
||||
|
|
|
|||
|
|
@ -80,58 +80,58 @@ func (c1 *Configuration) Equal(c2 *Configuration) bool {
|
|||
}
|
||||
|
||||
// Equal tests for equality between two Backend types
|
||||
func (b1 *Backend) Equal(b2 *Backend) bool {
|
||||
if b1 == b2 {
|
||||
func (b *Backend) Equal(newB *Backend) bool {
|
||||
if b == newB {
|
||||
return true
|
||||
}
|
||||
if b1 == nil || b2 == nil {
|
||||
if b == nil || newB == nil {
|
||||
return false
|
||||
}
|
||||
if b1.Name != b2.Name {
|
||||
if b.Name != newB.Name {
|
||||
return false
|
||||
}
|
||||
if b1.NoServer != b2.NoServer {
|
||||
if b.NoServer != newB.NoServer {
|
||||
return false
|
||||
}
|
||||
|
||||
if b1.Service != b2.Service {
|
||||
if b1.Service == nil || b2.Service == nil {
|
||||
if b.Service != newB.Service {
|
||||
if b.Service == nil || newB.Service == nil {
|
||||
return false
|
||||
}
|
||||
if b1.Service.GetNamespace() != b2.Service.GetNamespace() {
|
||||
if b.Service.GetNamespace() != newB.Service.GetNamespace() {
|
||||
return false
|
||||
}
|
||||
if b1.Service.GetName() != b2.Service.GetName() {
|
||||
if b.Service.GetName() != newB.Service.GetName() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if b1.Port != b2.Port {
|
||||
if b.Port != newB.Port {
|
||||
return false
|
||||
}
|
||||
if b1.SSLPassthrough != b2.SSLPassthrough {
|
||||
if b.SSLPassthrough != newB.SSLPassthrough {
|
||||
return false
|
||||
}
|
||||
if !(&b1.SessionAffinity).Equal(&b2.SessionAffinity) {
|
||||
if !(&b.SessionAffinity).Equal(&newB.SessionAffinity) {
|
||||
return false
|
||||
}
|
||||
if b1.UpstreamHashBy != b2.UpstreamHashBy {
|
||||
if b.UpstreamHashBy != newB.UpstreamHashBy {
|
||||
return false
|
||||
}
|
||||
if b1.LoadBalancing != b2.LoadBalancing {
|
||||
if b.LoadBalancing != newB.LoadBalancing {
|
||||
return false
|
||||
}
|
||||
|
||||
match := compareEndpoints(b1.Endpoints, b2.Endpoints)
|
||||
match := compareEndpoints(b.Endpoints, newB.Endpoints)
|
||||
if !match {
|
||||
return false
|
||||
}
|
||||
|
||||
if !b1.TrafficShapingPolicy.Equal(b2.TrafficShapingPolicy) {
|
||||
if !b.TrafficShapingPolicy.Equal(&newB.TrafficShapingPolicy) {
|
||||
return false
|
||||
}
|
||||
|
||||
return sets.StringElementsMatch(b1.AlternativeBackends, b2.AlternativeBackends)
|
||||
return sets.StringElementsMatch(b.AlternativeBackends, newB.AlternativeBackends)
|
||||
}
|
||||
|
||||
// Equal tests for equality between two SessionAffinityConfig types
|
||||
|
|
@ -243,7 +243,7 @@ func (e1 *Endpoint) Equal(e2 *Endpoint) bool {
|
|||
}
|
||||
|
||||
// Equal checks for equality between two TrafficShapingPolicies
|
||||
func (tsp1 TrafficShapingPolicy) Equal(tsp2 TrafficShapingPolicy) bool {
|
||||
func (tsp1 *TrafficShapingPolicy) Equal(tsp2 *TrafficShapingPolicy) bool {
|
||||
if tsp1.Weight != tsp2.Weight {
|
||||
return false
|
||||
}
|
||||
|
|
@ -335,6 +335,8 @@ func (s1 *Server) Equal(s2 *Server) bool {
|
|||
}
|
||||
|
||||
// Equal tests for equality between two Location types
|
||||
//
|
||||
//nolint:gocyclo // Ignore function complexity error
|
||||
func (l1 *Location) Equal(l2 *Location) bool {
|
||||
if l1 == l2 {
|
||||
return true
|
||||
|
|
@ -400,7 +402,7 @@ func (l1 *Location) Equal(l2 *Location) bool {
|
|||
if !(&l1.Denylist).Equal(&l2.Denylist) {
|
||||
return false
|
||||
}
|
||||
if !(&l1.Whitelist).Equal(&l2.Whitelist) {
|
||||
if !(&l1.Allowlist).Equal(&l2.Allowlist) {
|
||||
return false
|
||||
}
|
||||
if !(&l1.Proxy).Equal(&l2.Proxy) {
|
||||
|
|
@ -456,10 +458,6 @@ func (l1 *Location) Equal(l2 *Location) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if !l1.Opentracing.Equal(&l2.Opentracing) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !l1.Opentelemetry.Equal(&l2.Opentelemetry) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -468,6 +466,10 @@ func (l1 *Location) Equal(l2 *Location) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if l1.DisableProxyInterceptErrors != l2.DisableProxyInterceptErrors {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -550,39 +552,39 @@ func (l4b1 *L4Backend) Equal(l4b2 *L4Backend) bool {
|
|||
}
|
||||
|
||||
// Equal tests for equality between two SSLCert types
|
||||
func (s1 *SSLCert) Equal(s2 *SSLCert) bool {
|
||||
if s1 == s2 {
|
||||
func (s *SSLCert) Equal(newS *SSLCert) bool {
|
||||
if s == newS {
|
||||
return true
|
||||
}
|
||||
if s1 == nil || s2 == nil {
|
||||
if s == nil || newS == nil {
|
||||
return false
|
||||
}
|
||||
if s1.CASHA != s2.CASHA {
|
||||
if s.CASHA != newS.CASHA {
|
||||
return false
|
||||
}
|
||||
if s1.CRLSHA != s2.CRLSHA {
|
||||
if s.CRLSHA != newS.CRLSHA {
|
||||
return false
|
||||
}
|
||||
if s1.PemSHA != s2.PemSHA {
|
||||
if s.PemSHA != newS.PemSHA {
|
||||
return false
|
||||
}
|
||||
if s1.CAFileName != s2.CAFileName {
|
||||
if s.CAFileName != newS.CAFileName {
|
||||
return false
|
||||
}
|
||||
if s1.CRLFileName != s2.CRLFileName {
|
||||
if s.CRLFileName != newS.CRLFileName {
|
||||
return false
|
||||
}
|
||||
if !s1.ExpireTime.Equal(s2.ExpireTime) {
|
||||
if !s.ExpireTime.Equal(newS.ExpireTime) {
|
||||
return false
|
||||
}
|
||||
if s1.PemCertKey != s2.PemCertKey {
|
||||
if s.PemCertKey != newS.PemCertKey {
|
||||
return false
|
||||
}
|
||||
if s1.UID != s2.UID {
|
||||
if s.UID != newS.UID {
|
||||
return false
|
||||
}
|
||||
|
||||
return sets.StringElementsMatch(s1.CN, s2.CN)
|
||||
return sets.StringElementsMatch(s.CN, newS.CN)
|
||||
}
|
||||
|
||||
var compareEndpointsFunc = func(e1, e2 interface{}) bool {
|
||||
|
|
|
|||
|
|
@ -25,19 +25,29 @@ import (
|
|||
)
|
||||
|
||||
func TestEqualConfiguration(t *testing.T) {
|
||||
ap, _ := filepath.Abs("../../../test/manifests/configuration-a.json")
|
||||
ap, err := filepath.Abs("../../../test/manifests/configuration-a.json")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
a, err := readJSON(ap)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error reading JSON file: %v", err)
|
||||
}
|
||||
|
||||
bp, _ := filepath.Abs("../../../test/manifests/configuration-b.json")
|
||||
bp, err := filepath.Abs("../../../test/manifests/configuration-b.json")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
b, err := readJSON(bp)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error reading JSON file: %v", err)
|
||||
}
|
||||
|
||||
cp, _ := filepath.Abs("../../../test/manifests/configuration-c.json")
|
||||
cp, err := filepath.Abs("../../../test/manifests/configuration-c.json")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
c, err := readJSON(cp)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error reading JSON file: %v", err)
|
||||
|
|
@ -84,15 +94,18 @@ func TestL4ServiceElementsMatch(t *testing.T) {
|
|||
{[]L4Service{{Port: 80}}, []L4Service{{Port: 80}}, true},
|
||||
{
|
||||
[]L4Service{
|
||||
{Port: 80, Endpoints: []Endpoint{{Address: "1.1.1.1"}}}},
|
||||
{Port: 80, Endpoints: []Endpoint{{Address: "1.1.1.1"}}},
|
||||
},
|
||||
[]L4Service{{Port: 80}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
[]L4Service{
|
||||
{Port: 80, Endpoints: []Endpoint{{Address: "1.1.1.1"}, {Address: "1.1.1.2"}}}},
|
||||
{Port: 80, Endpoints: []Endpoint{{Address: "1.1.1.1"}, {Address: "1.1.1.2"}}},
|
||||
},
|
||||
[]L4Service{
|
||||
{Port: 80, Endpoints: []Endpoint{{Address: "1.1.1.2"}, {Address: "1.1.1.1"}}}},
|
||||
{Port: 80, Endpoints: []Endpoint{{Address: "1.1.1.2"}, {Address: "1.1.1.1"}}},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -132,6 +132,9 @@ Requires setting the publish-service parameter to a valid Service reference.`)
|
|||
electionID = flags.String("election-id", "ingress-controller-leader",
|
||||
`Election id to use for Ingress status updates.`)
|
||||
|
||||
electionTTL = flags.Duration("election-ttl", 30*time.Second,
|
||||
`Duration a leader election is valid before it's getting re-elected`)
|
||||
|
||||
updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true,
|
||||
`Update the load-balancer status of Ingress objects when the controller shuts down.
|
||||
Requires the update-status parameter.`)
|
||||
|
|
@ -146,12 +149,18 @@ Requires the update-status parameter.`)
|
|||
enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false,
|
||||
`Enable SSL Passthrough.`)
|
||||
|
||||
disableLeaderElection = flags.Bool("disable-leader-election", false,
|
||||
`Disable Leader Election on NGINX Controller.`)
|
||||
|
||||
disableServiceExternalName = flags.Bool("disable-svc-external-name", false,
|
||||
`Disable support for Services of type ExternalName.`)
|
||||
|
||||
annotationsPrefix = flags.String("annotations-prefix", parser.DefaultAnnotationsPrefix,
|
||||
`Prefix of the Ingress annotations specific to the NGINX controller.`)
|
||||
|
||||
enableAnnotationValidation = flags.Bool("enable-annotation-validation", false,
|
||||
`If true, will enable the annotation validation feature. This value will be defaulted to true on a future release`)
|
||||
|
||||
enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", false,
|
||||
`Autocomplete SSL certificate chains with missing intermediate CA certificates.
|
||||
Certificates uploaded to Kubernetes must have the "Authority Information Access" X.509 v3
|
||||
|
|
@ -218,7 +227,7 @@ Takes the form "<host>:port". If not provided, no admission controller is starte
|
|||
|
||||
disableSyncEvents = flags.Bool("disable-sync-events", false, "Disables the creation of 'Sync' event resources")
|
||||
|
||||
enableTopologyAwareRouting = flags.Bool("enable-topology-aware-routing", false, "Enable topology aware hints feature, needs service object annotation service.kubernetes.io/topology-aware-hints sets to auto.")
|
||||
enableTopologyAwareRouting = flags.Bool("enable-topology-aware-routing", false, "Enable topology aware routing feature, needs service object annotation service.kubernetes.io/topology-mode sets to auto.")
|
||||
)
|
||||
|
||||
flags.StringVar(&nginx.MaxmindMirror, "maxmind-mirror", "", `Maxmind mirror url (example: http://geoip.local/databases.`)
|
||||
|
|
@ -249,6 +258,7 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
|||
}
|
||||
|
||||
parser.AnnotationsPrefix = *annotationsPrefix
|
||||
parser.EnableAnnotationValidation = *enableAnnotationValidation
|
||||
|
||||
// check port collisions
|
||||
if !ing_net.IsPortAvailable(*httpPort) {
|
||||
|
|
@ -294,12 +304,12 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
|||
nginx.HealthCheckTimeout = time.Duration(*defHealthCheckTimeout) * time.Second
|
||||
}
|
||||
|
||||
if len(*watchNamespace) != 0 && len(*watchNamespaceSelector) != 0 {
|
||||
if *watchNamespace != "" && *watchNamespaceSelector != "" {
|
||||
return false, nil, fmt.Errorf("flags --watch-namespace and --watch-namespace-selector are mutually exclusive")
|
||||
}
|
||||
|
||||
var namespaceSelector labels.Selector
|
||||
if len(*watchNamespaceSelector) != 0 {
|
||||
if *watchNamespaceSelector != "" {
|
||||
var err error
|
||||
namespaceSelector, err = labels.Parse(*watchNamespaceSelector)
|
||||
if err != nil {
|
||||
|
|
@ -307,7 +317,11 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
|||
}
|
||||
}
|
||||
|
||||
var histogramBuckets = &collectors.HistogramBuckets{
|
||||
if *electionTTL <= 0 {
|
||||
*electionTTL = 30 * time.Second
|
||||
}
|
||||
|
||||
histogramBuckets := &collectors.HistogramBuckets{
|
||||
TimeBuckets: *timeBuckets,
|
||||
LengthBuckets: *lengthBuckets,
|
||||
SizeBuckets: *sizeBuckets,
|
||||
|
|
@ -320,6 +334,7 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
|||
KubeConfigFile: *kubeConfigFile,
|
||||
UpdateStatus: *updateStatus,
|
||||
ElectionID: *electionID,
|
||||
ElectionTTL: *electionTTL,
|
||||
EnableProfiling: *profiling,
|
||||
EnableMetrics: *enableMetrics,
|
||||
MetricsPerHost: *metricsPerHost,
|
||||
|
|
@ -329,6 +344,7 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
|||
MonitorMaxBatchSize: *monitorMaxBatchSize,
|
||||
DisableServiceExternalName: *disableServiceExternalName,
|
||||
EnableSSLPassthrough: *enableSSLPassthrough,
|
||||
DisableLeaderElection: *disableLeaderElection,
|
||||
ResyncPeriod: *resyncPeriod,
|
||||
DefaultService: *defaultSvc,
|
||||
Namespace: *watchNamespace,
|
||||
|
|
@ -356,7 +372,7 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
|||
HTTPS: *httpsPort,
|
||||
SSLProxy: *sslProxyPort,
|
||||
},
|
||||
IngressClassConfiguration: &ingressclass.IngressClassConfiguration{
|
||||
IngressClassConfiguration: &ingressclass.Configuration{
|
||||
Controller: *ingressClassController,
|
||||
AnnotationValue: *ingressClassAnnotation,
|
||||
WatchWithoutClass: *watchWithoutClass,
|
||||
|
|
@ -376,7 +392,7 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
|||
|
||||
var err error
|
||||
if nginx.MaxmindEditionIDs != "" {
|
||||
if err = nginx.ValidateGeoLite2DBEditions(); err != nil {
|
||||
if err := nginx.ValidateGeoLite2DBEditions(); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
if nginx.MaxmindLicenseKey != "" || nginx.MaxmindMirror != "" {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package flags
|
|||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNoMandatoryFlag(t *testing.T) {
|
||||
|
|
@ -33,7 +34,8 @@ func TestDefaults(t *testing.T) {
|
|||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd",
|
||||
os.Args = []string{
|
||||
"cmd",
|
||||
"--default-backend-service", "namespace/test",
|
||||
"--http-port", "0",
|
||||
"--https-port", "0",
|
||||
|
|
@ -53,8 +55,8 @@ func TestDefaults(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSetupSSLProxy(t *testing.T) {
|
||||
// TODO
|
||||
func TestSetupSSLProxy(_ *testing.T) {
|
||||
// TODO TestSetupSSLProxy
|
||||
}
|
||||
|
||||
func TestFlagConflict(t *testing.T) {
|
||||
|
|
@ -108,3 +110,105 @@ func TestMaxmindRetryDownload(t *testing.T) {
|
|||
t.Fatalf("Expected an error parsing flags but none returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableLeaderElectionFlag(t *testing.T) {
|
||||
ResetForTesting(func() { t.Fatal("Parsing failed") })
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--disable-leader-election", "--http-port", "80", "--https-port", "443"}
|
||||
|
||||
_, conf, err := ParseFlags()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error parsing default flags: %v", err)
|
||||
}
|
||||
|
||||
if !conf.DisableLeaderElection {
|
||||
t.Fatalf("Expected --disable-leader-election and conf.DisableLeaderElection as true, but found: %v", conf.DisableLeaderElection)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIfLeaderElectionDisabledFlagIsFalse(t *testing.T) {
|
||||
ResetForTesting(func() { t.Fatal("Parsing failed") })
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--http-port", "80", "--https-port", "443"}
|
||||
|
||||
_, conf, err := ParseFlags()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error parsing default flags: %v", err)
|
||||
}
|
||||
|
||||
if conf.DisableLeaderElection {
|
||||
t.Fatalf("Expected --disable-leader-election and conf.DisableLeaderElection as false, but found: %v", conf.DisableLeaderElection)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeaderElectionTTLDefaultValue(t *testing.T) {
|
||||
ResetForTesting(func() { t.Fatal("Parsing failed") })
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--http-port", "80", "--https-port", "443"}
|
||||
|
||||
_, conf, err := ParseFlags()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error parsing default flags: %v", err)
|
||||
}
|
||||
|
||||
if conf.ElectionTTL != 30*time.Second {
|
||||
t.Fatalf("Expected --election-ttl and conf.ElectionTTL as 30s, but found: %v", conf.ElectionTTL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeaderElectionTTLParseValueInSeconds(t *testing.T) {
|
||||
ResetForTesting(func() { t.Fatal("Parsing failed") })
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--http-port", "80", "--https-port", "443", "--election-ttl", "10s"}
|
||||
|
||||
_, conf, err := ParseFlags()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error parsing default flags: %v", err)
|
||||
}
|
||||
|
||||
if conf.ElectionTTL != 10*time.Second {
|
||||
t.Fatalf("Expected --election-ttl and conf.ElectionTTL as 10s, but found: %v", conf.ElectionTTL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeaderElectionTTLParseValueInMinutes(t *testing.T) {
|
||||
ResetForTesting(func() { t.Fatal("Parsing failed") })
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--http-port", "80", "--https-port", "443", "--election-ttl", "10m"}
|
||||
|
||||
_, conf, err := ParseFlags()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error parsing default flags: %v", err)
|
||||
}
|
||||
|
||||
if conf.ElectionTTL != 10*time.Minute {
|
||||
t.Fatalf("Expected --election-ttl and conf.ElectionTTL as 10m, but found: %v", conf.ElectionTTL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLeaderElectionTTLParseValueInHours(t *testing.T) {
|
||||
ResetForTesting(func() { t.Fatal("Parsing failed") })
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--http-port", "80", "--https-port", "443", "--election-ttl", "1h"}
|
||||
|
||||
_, conf, err := ParseFlags()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error parsing default flags: %v", err)
|
||||
}
|
||||
|
||||
if conf.ElectionTTL != 1*time.Hour {
|
||||
t.Fatalf("Expected --election-ttl and conf.ElectionTTL as 1h, but found: %v", conf.ElectionTTL)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ import (
|
|||
)
|
||||
|
||||
func RegisterHealthz(healthPath string, mux *http.ServeMux, checks ...healthz.HealthChecker) {
|
||||
|
||||
healthCheck := []healthz.HealthChecker{healthz.PingHealthz}
|
||||
if len(checks) > 0 {
|
||||
healthCheck = append(healthCheck, checks...)
|
||||
|
|
@ -67,7 +66,7 @@ func RegisterProfiler(host string, port int) {
|
|||
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", host, port),
|
||||
//G112 (CWE-400): Potential Slowloris Attack
|
||||
// G112 (CWE-400): Potential Slowloris Attack
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
Handler: mux,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func (p *TCPProxy) Handle(conn net.Conn) {
|
|||
}
|
||||
|
||||
proxy := p.Default
|
||||
hostname, err := parser.GetHostname(data[:])
|
||||
hostname, err := parser.GetHostname(data)
|
||||
if err == nil {
|
||||
klog.V(4).InfoS("TLS Client Hello", "host", hostname)
|
||||
proxy = p.Get(hostname)
|
||||
|
|
@ -91,8 +91,14 @@ func (p *TCPProxy) Handle(conn net.Conn) {
|
|||
|
||||
if proxy.ProxyProtocol {
|
||||
// write out the Proxy Protocol header
|
||||
localAddr := conn.LocalAddr().(*net.TCPAddr)
|
||||
remoteAddr := conn.RemoteAddr().(*net.TCPAddr)
|
||||
localAddr, ok := conn.LocalAddr().(*net.TCPAddr)
|
||||
if !ok {
|
||||
klog.Errorf("unexpected type: %T", conn.LocalAddr())
|
||||
}
|
||||
remoteAddr, ok := conn.RemoteAddr().(*net.TCPAddr)
|
||||
if !ok {
|
||||
klog.Errorf("unexpected type: %T", conn.RemoteAddr())
|
||||
}
|
||||
protocol := "UNKNOWN"
|
||||
if remoteAddr.IP.To4() != nil {
|
||||
protocol = "TCP4"
|
||||
|
|
@ -119,9 +125,8 @@ func (p *TCPProxy) Handle(conn net.Conn) {
|
|||
|
||||
func pipe(client, server net.Conn) {
|
||||
doCopy := func(s, c net.Conn, cancel chan<- bool) {
|
||||
if _, err := io.Copy(s, c); err != nil {
|
||||
klog.Errorf("Error copying data: %v", err)
|
||||
}
|
||||
//nolint:errcheck // No need to catch these errors
|
||||
io.Copy(s, c)
|
||||
cancel <- true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ import (
|
|||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
// FileWatcher is an interface we use to watch changes in files
|
||||
type FileWatcher interface {
|
||||
// Watcher is an interface we use to watch changes in files
|
||||
type Watcher interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ type OSFileWatcher struct {
|
|||
}
|
||||
|
||||
// NewFileWatcher creates a new FileWatcher
|
||||
func NewFileWatcher(file string, onEvent func()) (FileWatcher, error) {
|
||||
func NewFileWatcher(file string, onEvent func()) (Watcher, error) {
|
||||
fw := OSFileWatcher{
|
||||
file: file,
|
||||
onEvent: onEvent,
|
||||
|
|
|
|||
|
|
@ -17,4 +17,4 @@ limitations under the License.
|
|||
package file
|
||||
|
||||
// ReadWriteByUser defines linux permission to read and write files for the owner user
|
||||
const ReadWriteByUser = 0700
|
||||
const ReadWriteByUser = 0o700
|
||||
|
|
|
|||
|
|
@ -33,12 +33,10 @@ const (
|
|||
DefaultSSLDirectory = "/etc/ingress-controller/ssl"
|
||||
)
|
||||
|
||||
var (
|
||||
directories = []string{
|
||||
DefaultSSLDirectory,
|
||||
AuthDirectory,
|
||||
}
|
||||
)
|
||||
var directories = []string{
|
||||
DefaultSSLDirectory,
|
||||
AuthDirectory,
|
||||
}
|
||||
|
||||
// CreateRequiredDirectories verifies if the required directories to
|
||||
// start the ingress controller exist and creates the missing ones.
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func GetRemovedIngresses(rucfg, newcfg *ingress.Configuration) []string {
|
|||
|
||||
// IsDynamicConfigurationEnough returns whether a Configuration can be
|
||||
// dynamically applied, without reloading the backend.
|
||||
func IsDynamicConfigurationEnough(newcfg *ingress.Configuration, oldcfg *ingress.Configuration) bool {
|
||||
func IsDynamicConfigurationEnough(newcfg, oldcfg *ingress.Configuration) bool {
|
||||
copyOfRunningConfig := *oldcfg
|
||||
copyOfPcfg := *newcfg
|
||||
|
||||
|
|
@ -133,21 +133,21 @@ func IsDynamicConfigurationEnough(newcfg *ingress.Configuration, oldcfg *ingress
|
|||
// clearL4serviceEndpoints is a helper function to clear endpoints from the ingress configuration since they should be ignored when
|
||||
// checking if the new configuration changes can be applied dynamically.
|
||||
func clearL4serviceEndpoints(config *ingress.Configuration) {
|
||||
var clearedTCPL4Services []ingress.L4Service
|
||||
var clearedUDPL4Services []ingress.L4Service
|
||||
for _, service := range config.TCPEndpoints {
|
||||
clearedTCPL4Services := make([]ingress.L4Service, 0, len(config.TCPEndpoints))
|
||||
clearedUDPL4Services := make([]ingress.L4Service, 0, len(config.UDPEndpoints))
|
||||
for i := range config.TCPEndpoints {
|
||||
copyofService := ingress.L4Service{
|
||||
Port: service.Port,
|
||||
Backend: service.Backend,
|
||||
Port: config.TCPEndpoints[i].Port,
|
||||
Backend: config.TCPEndpoints[i].Backend,
|
||||
Endpoints: []ingress.Endpoint{},
|
||||
Service: nil,
|
||||
}
|
||||
clearedTCPL4Services = append(clearedTCPL4Services, copyofService)
|
||||
}
|
||||
for _, service := range config.UDPEndpoints {
|
||||
for i := range config.UDPEndpoints {
|
||||
copyofService := ingress.L4Service{
|
||||
Port: service.Port,
|
||||
Backend: service.Backend,
|
||||
Port: config.UDPEndpoints[i].Port,
|
||||
Backend: config.UDPEndpoints[i].Backend,
|
||||
Endpoints: []ingress.Endpoint{},
|
||||
Service: nil,
|
||||
}
|
||||
|
|
@ -160,7 +160,7 @@ func clearL4serviceEndpoints(config *ingress.Configuration) {
|
|||
// clearCertificates is a helper function to clear Certificates from the ingress configuration since they should be ignored when
|
||||
// checking if the new configuration changes can be applied dynamically if dynamic certificates is on
|
||||
func clearCertificates(config *ingress.Configuration) {
|
||||
var clearedServers []*ingress.Server
|
||||
clearedServers := make([]*ingress.Server, 0, len(config.Servers))
|
||||
for _, server := range config.Servers {
|
||||
copyOfServer := *server
|
||||
copyOfServer.SSLCert = nil
|
||||
|
|
@ -169,16 +169,16 @@ func clearCertificates(config *ingress.Configuration) {
|
|||
config.Servers = clearedServers
|
||||
}
|
||||
|
||||
type redirect struct {
|
||||
type Redirect struct {
|
||||
From string
|
||||
To string
|
||||
SSLCert *ingress.SSLCert
|
||||
}
|
||||
|
||||
// BuildRedirects build the redirects of servers based on configurations and certificates
|
||||
func BuildRedirects(servers []*ingress.Server) []*redirect {
|
||||
func BuildRedirects(servers []*ingress.Server) []*Redirect {
|
||||
names := sets.Set[string]{}
|
||||
redirectServers := make([]*redirect, 0)
|
||||
redirectServers := make([]*Redirect, 0)
|
||||
|
||||
for _, srv := range servers {
|
||||
if !srv.RedirectFromToWWW {
|
||||
|
|
@ -212,7 +212,7 @@ func BuildRedirects(servers []*ingress.Server) []*redirect {
|
|||
continue
|
||||
}
|
||||
|
||||
r := &redirect{
|
||||
r := &Redirect{
|
||||
From: from,
|
||||
To: to,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ limitations under the License.
|
|||
|
||||
package process
|
||||
|
||||
// ProcessController defines a common interface for a process to be controlled,
|
||||
// Controller defines a common interface for a process to be controlled,
|
||||
// like the configurer, the webhook or the proper ingress controller
|
||||
type ProcessController interface {
|
||||
type Controller interface {
|
||||
Start()
|
||||
Stop() error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ type exiter func(code int)
|
|||
|
||||
// HandleSigterm receives a ProcessController interface and deals with
|
||||
// the graceful shutdown
|
||||
func HandleSigterm(ngx ProcessController, delay int, exit exiter) {
|
||||
func HandleSigterm(ngx Controller, delay int, exit exiter) {
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChan, syscall.SIGTERM)
|
||||
<-signalChan
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func (f *FakeProcess) exiterFunc(code int) {
|
|||
}
|
||||
|
||||
func sendDelayedSignal(delay time.Duration) error {
|
||||
time.Sleep(delay * time.Second)
|
||||
time.Sleep(delay)
|
||||
return syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ func TestHandleSigterm(t *testing.T) {
|
|||
process := &FakeProcess{shouldError: tt.shouldError}
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
go func() {
|
||||
err := sendDelayedSignal(2) // Send a signal after 2 seconds
|
||||
err := sendDelayedSignal(2 * time.Second) // Send a signal after 2 seconds
|
||||
if err != nil {
|
||||
t.Errorf("error sending delayed signal: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"runtime"
|
||||
)
|
||||
|
||||
// NumCPU ...
|
||||
// NumCPU returns the number of logical CPUs usable by the current process.
|
||||
func NumCPU() int {
|
||||
return runtime.NumCPU()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,23 +20,20 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
testCasesElementMatch = []struct {
|
||||
listA []string
|
||||
listB []string
|
||||
expected bool
|
||||
}{
|
||||
{nil, nil, true},
|
||||
{[]string{"1"}, nil, false},
|
||||
{[]string{"1"}, []string{"1"}, true},
|
||||
{[]string{"1", "2", "1"}, []string{"1", "1", "2"}, true},
|
||||
{[]string{"1", "3", "1"}, []string{"1", "1", "2"}, false},
|
||||
{[]string{"1", "1"}, []string{"1", "2"}, false},
|
||||
}
|
||||
)
|
||||
var testCasesElementMatch = []struct {
|
||||
listA []string
|
||||
listB []string
|
||||
expected bool
|
||||
}{
|
||||
{nil, nil, true},
|
||||
{[]string{"1"}, nil, false},
|
||||
{[]string{"1"}, []string{"1"}, true},
|
||||
{[]string{"1", "2", "1"}, []string{"1", "1", "2"}, true},
|
||||
{[]string{"1", "3", "1"}, []string{"1", "1", "2"}, false},
|
||||
{[]string{"1", "1"}, []string{"1", "2"}, false},
|
||||
}
|
||||
|
||||
func TestElementsMatch(t *testing.T) {
|
||||
|
||||
for _, testCase := range testCasesElementMatch {
|
||||
result := StringElementsMatch(testCase.listA, testCase.listB)
|
||||
if result != testCase.expected {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue