Fix golangci-lint errors (#10196)

* Fix golangci-lint errors

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix dupl errors

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix comments

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix errcheck lint errors

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix assert in e2e test

Signed-off-by: z1cheng <imchench@gmail.com>

* Not interrupt the waitForPodsReady

Signed-off-by: z1cheng <imchench@gmail.com>

* Replace string with constant

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix comments

Signed-off-by: z1cheng <imchench@gmail.com>

* Revert write file permision

Signed-off-by: z1cheng <imchench@gmail.com>

---------

Signed-off-by: z1cheng <imchench@gmail.com>
This commit is contained in:
Chen Chen 2023-08-31 15:36:48 +08:00 committed by GitHub
parent 46d87d3462
commit b3060bfbd0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
253 changed files with 2434 additions and 2113 deletions

View file

@ -100,7 +100,7 @@ func matchHostnames(pattern, host string) bool {
host = strings.TrimSuffix(host, ".")
pattern = strings.TrimSuffix(pattern, ".")
if len(pattern) == 0 || len(host) == 0 {
if pattern == "" || host == "" {
return false
}

View file

@ -29,7 +29,7 @@ import (
)
// Name returns the healthcheck name
func (n NGINXController) Name() string {
func (n *NGINXController) Name() string {
return "nginx-ingress-controller"
}

View file

@ -32,7 +32,7 @@ import (
)
func TestNginxCheck(t *testing.T) {
var tests = []struct {
tests := []struct {
healthzPath string
}{
{"/healthz"},
@ -42,7 +42,6 @@ func TestNginxCheck(t *testing.T) {
for _, tt := range tests {
testName := fmt.Sprintf("health path: %s", tt.healthzPath)
t.Run(testName, func(t *testing.T) {
mux := http.NewServeMux()
listener, err := tryListen("tcp", fmt.Sprintf(":%v", nginx.StatusPort))
@ -50,7 +49,7 @@ func TestNginxCheck(t *testing.T) {
t.Fatalf("creating tcp listener: %s", err)
}
defer listener.Close()
//nolint:gosec // Ignore not configured ReadHeaderTimeout in testing
server := &httptest.Server{
Listener: listener,
Config: &http.Server{
@ -103,10 +102,10 @@ func TestNginxCheck(t *testing.T) {
}
}()
go func() {
cmd.Wait() //nolint:errcheck
cmd.Wait() //nolint:errcheck // Ignore the error
}()
if _, err := pidFile.Write([]byte(fmt.Sprintf("%v", pid))); err != nil {
if _, err := fmt.Fprintf(pidFile, "%v", pid); err != nil {
t.Errorf("unexpected error writing the pid file: %v", err)
}
@ -121,7 +120,7 @@ func TestNginxCheck(t *testing.T) {
})
// pollute pid file
pidFile.Write([]byte("999999")) //nolint:errcheck
pidFile.WriteString("999999") //nolint:errcheck // Ignore the error
pidFile.Close()
t.Run("bad pid", func(t *testing.T) {
@ -134,7 +133,7 @@ func TestNginxCheck(t *testing.T) {
}
func callHealthz(expErr bool, healthzPath string, mux *http.ServeMux) error {
req, err := http.NewRequest(http.MethodGet, healthzPath, nil)
req, err := http.NewRequest(http.MethodGet, healthzPath, http.NoBody)
if err != nil {
return fmt.Errorf("healthz error: %v", err)
}

View file

@ -29,10 +29,8 @@ import (
"k8s.io/ingress-nginx/pkg/util/runtime"
)
var (
// EnableSSLChainCompletion Autocomplete SSL certificate chains with missing intermediate CA certificates.
EnableSSLChainCompletion = false
)
// EnableSSLChainCompletion Autocomplete SSL certificate chains with missing intermediate CA certificates.
var EnableSSLChainCompletion = false
const (
// http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size
@ -91,7 +89,7 @@ const (
// Configuration represents the content of nginx.conf file
type Configuration struct {
defaults.Backend `json:",squash"` //nolint:staticcheck
defaults.Backend `json:",squash"` //nolint:staticcheck // Ignore unknown JSON option "squash" error
// AllowSnippetAnnotations enable users to add their own snippets via ingress annotation.
// If disabled, only snippets added via ConfigMap are added to ingress.
@ -141,9 +139,9 @@ type Configuration struct {
// By default access logs go to /var/log/nginx/access.log
AccessLogPath string `json:"access-log-path,omitempty"`
// HttpAccessLogPath sets the path of the access logs for http context globally if enabled
// HTTPAccessLogPath sets the path of the access logs for http context globally if enabled
// http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log
HttpAccessLogPath string `json:"http-access-log-path,omitempty"`
HTTPAccessLogPath string `json:"http-access-log-path,omitempty"`
// StreamAccessLogPath sets the path of the access logs for stream context globally if enabled
// http://nginx.org/en/docs/stream/ngx_stream_log_module.html#access_log
@ -230,19 +228,19 @@ type Configuration struct {
// https://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_max_field_size
// HTTP2MaxFieldSize Limits the maximum size of an HPACK-compressed request header field
// NOTE: Deprecated
// Deprecated: HTTP2MaxFieldSize is deprecated.
HTTP2MaxFieldSize string `json:"http2-max-field-size,omitempty"`
// https://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_max_header_size
// HTTP2MaxHeaderSize Limits the maximum size of the entire request header list after HPACK decompression
// NOTE: Deprecated
// Deprecated: HTTP2MaxHeaderSize is deprecated.
HTTP2MaxHeaderSize string `json:"http2-max-header-size,omitempty"`
// http://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_max_requests
// HTTP2MaxRequests Sets the maximum number of requests (including push requests) that can be served
// through one HTTP/2 connection, after which the next client request will lead to connection closing
// and the need of establishing a new connection.
// NOTE: Deprecated
// Deprecated: HTTP2MaxRequests is deprecated.
HTTP2MaxRequests int `json:"http2-max-requests,omitempty"`
// http://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_max_concurrent_streams
@ -552,7 +550,7 @@ type Configuration struct {
UseForwardedHeaders bool `json:"use-forwarded-headers"`
// Sets whether to enable the real ip module
EnableRealIp bool `json:"enable-real-ip"`
EnableRealIP bool `json:"enable-real-ip"`
// Sets the header field for identifying the originating IP address of a client
// Default is X-Forwarded-For
@ -621,7 +619,7 @@ type Configuration struct {
// Default: 0.01
OtelSamplerRatio float32 `json:"otel-sampler-ratio"`
//OtelSamplerParentBased specifies the parent based sampler to be use for any traces created
// OtelSamplerParentBased specifies the parent based sampler to be use for any traces created
// Default: true
OtelSamplerParentBased bool `json:"otel-sampler-parent-based"`
@ -891,7 +889,7 @@ func NewDefault() Configuration {
EnableUnderscoresInHeaders: false,
ErrorLogLevel: errorLevel,
UseForwardedHeaders: false,
EnableRealIp: false,
EnableRealIP: false,
ForwardedForHeader: "X-Forwarded-For",
ComputeFullForwardedFor: false,
ProxyAddOriginalURIHeader: false,
@ -1039,41 +1037,41 @@ func NewDefault() Configuration {
// TemplateConfig contains the nginx configuration to render the file nginx.conf
type TemplateConfig struct {
ProxySetHeaders map[string]string
AddHeaders map[string]string
BacklogSize int
Backends []*ingress.Backend
PassthroughBackends []*ingress.SSLPassthroughBackend
Servers []*ingress.Server
TCPBackends []ingress.L4Service
UDPBackends []ingress.L4Service
HealthzURI string
Cfg Configuration
IsIPV6Enabled bool
IsSSLPassthroughEnabled bool
NginxStatusIpv4Whitelist []string
NginxStatusIpv6Whitelist []string
RedirectServers interface{}
ListenPorts *ListenPorts
PublishService *apiv1.Service
EnableMetrics bool
MaxmindEditionFiles *[]string
MonitorMaxBatchSize int
PID string
StatusPath string
StatusPort int
StreamPort int
StreamSnippets []string
ProxySetHeaders map[string]string `json:"ProxySetHeaders"`
AddHeaders map[string]string `json:"AddHeaders"`
BacklogSize int `json:"BacklogSize"`
Backends []*ingress.Backend `json:"Backends"`
PassthroughBackends []*ingress.SSLPassthroughBackend `json:"PassthroughBackends"`
Servers []*ingress.Server `json:"Servers"`
TCPBackends []ingress.L4Service `json:"TCPBackends"`
UDPBackends []ingress.L4Service `json:"UDPBackends"`
HealthzURI string `json:"HealthzURI"`
Cfg Configuration `json:"Cfg"`
IsIPV6Enabled bool `json:"IsIPV6Enabled"`
IsSSLPassthroughEnabled bool `json:"IsSSLPassthroughEnabled"`
NginxStatusIpv4Whitelist []string `json:"NginxStatusIpv4Whitelist"`
NginxStatusIpv6Whitelist []string `json:"NginxStatusIpv6Whitelist"`
RedirectServers interface{} `json:"RedirectServers"`
ListenPorts *ListenPorts `json:"ListenPorts"`
PublishService *apiv1.Service `json:"PublishService"`
EnableMetrics bool `json:"EnableMetrics"`
MaxmindEditionFiles *[]string `json:"MaxmindEditionFiles"`
MonitorMaxBatchSize int `json:"MonitorMaxBatchSize"`
PID string `json:"PID"`
StatusPath string `json:"StatusPath"`
StatusPort int `json:"StatusPort"`
StreamPort int `json:"StreamPort"`
StreamSnippets []string `json:"StreamSnippets"`
}
// ListenPorts describe the ports required to run the
// NGINX Ingress controller
type ListenPorts struct {
HTTP int
HTTPS int
Health int
Default int
SSLProxy int
HTTP int `json:"HTTP"`
HTTPS int `json:"HTTPS"`
Health int `json:"Health"`
Default int `json:"Default"`
SSLProxy int `json:"SSLProxy"`
}
// GlobalExternalAuth describe external authentication configuration for the

View file

@ -114,7 +114,7 @@ type Configuration struct {
DisableCatchAll bool
IngressClassConfiguration *ingressclass.IngressClassConfiguration
IngressClassConfiguration *ingressclass.Configuration
ValidationWebhook string
ValidationWebhookCertPath string
@ -143,7 +143,7 @@ type Configuration struct {
func getIngressPodZone(svc *apiv1.Service) string {
svcKey := k8s.MetaNamespaceKey(svc)
if svcZoneAnnotation, ok := svc.ObjectMeta.GetAnnotations()[apiv1.AnnotationTopologyMode]; ok {
if strings.ToLower(svcZoneAnnotation) == "auto" {
if strings.EqualFold(svcZoneAnnotation, "auto") {
if foundZone, ok := k8s.IngressNodeDetails.GetLabels()[apiv1.LabelTopologyZone]; ok {
klog.V(3).Infof("Svc has topology aware annotation enabled, try to use zone %q where controller pod is running for Service %q ", foundZone, svcKey)
return foundZone
@ -154,7 +154,7 @@ func getIngressPodZone(svc *apiv1.Service) string {
}
// GetPublishService returns the Service used to set the load-balancer status of Ingresses.
func (n NGINXController) GetPublishService() *apiv1.Service {
func (n *NGINXController) GetPublishService() *apiv1.Service {
s, err := n.store.GetService(n.cfg.PublishService)
if err != nil {
return nil
@ -189,13 +189,16 @@ func (n *NGINXController) syncIngress(interface{}) error {
if !utilingress.IsDynamicConfigurationEnough(pcfg, n.runningConfig) {
klog.InfoS("Configuration changes detected, backend reload required")
hash, _ := hashstructure.Hash(pcfg, hashstructure.FormatV1, &hashstructure.HashOptions{
hash, err := hashstructure.Hash(pcfg, hashstructure.FormatV1, &hashstructure.HashOptions{
TagName: "json",
})
if err != nil {
klog.Errorf("unexpected error hashing configuration: %v", err)
}
pcfg.ConfigurationChecksum = fmt.Sprintf("%v", hash)
err := n.OnUpdate(*pcfg)
err = n.OnUpdate(*pcfg)
if err != nil {
n.metricCollector.IncReloadErrorCount()
n.metricCollector.ConfigSuccess(hash, false)
@ -263,7 +266,7 @@ func (n *NGINXController) syncIngress(interface{}) error {
func (n *NGINXController) CheckWarning(ing *networking.Ingress) ([]string, error) {
warnings := make([]string, 0)
var deprecatedAnnotations = sets.NewString()
deprecatedAnnotations := sets.NewString()
deprecatedAnnotations.Insert(
"enable-influxdb",
"influxdb-measurement",
@ -335,7 +338,7 @@ func (n *NGINXController) CheckIngress(ing *networking.Ingress) error {
}
if n.cfg.DisableCatchAll && ing.Spec.DefaultBackend != nil {
return fmt.Errorf("This deployment is trying to create a catch-all ingress while DisableCatchAll flag is set to true. Remove '.spec.defaultBackend' or set DisableCatchAll flag to false.")
return fmt.Errorf("this deployment is trying to create a catch-all ingress while DisableCatchAll flag is set to true. Remove '.spec.defaultBackend' or set DisableCatchAll flag to false")
}
startRender := time.Now().UnixNano() / 1000000
cfg := n.store.GetBackendConfiguration()
@ -355,10 +358,9 @@ func (n *NGINXController) CheckIngress(ing *networking.Ingress) error {
}
for key, value := range ing.ObjectMeta.GetAnnotations() {
if parser.AnnotationsPrefix != parser.DefaultAnnotationsPrefix {
if strings.HasPrefix(key, fmt.Sprintf("%s/", parser.DefaultAnnotationsPrefix)) {
return fmt.Errorf("This deployment has a custom annotation prefix defined. Use '%s' instead of '%s'", parser.AnnotationsPrefix, parser.DefaultAnnotationsPrefix)
return fmt.Errorf("this deployment has a custom annotation prefix defined. Use '%s' instead of '%s'", parser.AnnotationsPrefix, parser.DefaultAnnotationsPrefix)
}
}
@ -374,10 +376,9 @@ func (n *NGINXController) CheckIngress(ing *networking.Ingress) error {
return fmt.Errorf("%s annotation cannot be used. Snippet directives are disabled by the Ingress administrator", key)
}
if len(cfg.GlobalRateLimitMemcachedHost) == 0 && strings.HasPrefix(key, fmt.Sprintf("%s/%s", parser.AnnotationsPrefix, "global-rate-limit")) {
if cfg.GlobalRateLimitMemcachedHost == "" && strings.HasPrefix(key, fmt.Sprintf("%s/%s", parser.AnnotationsPrefix, "global-rate-limit")) {
return fmt.Errorf("'global-rate-limit*' annotations require 'global-rate-limit-memcached-host' settings configured in the global configmap")
}
}
k8s.SetDefaultNGINXPathType(ing)
@ -401,7 +402,7 @@ func (n *NGINXController) CheckIngress(ing *networking.Ingress) error {
startTest := time.Now().UnixNano() / 1000000
_, servers, pcfg := n.getConfiguration(ings)
err = checkOverlap(ing, allIngresses, servers)
err = checkOverlap(ing, servers)
if err != nil {
n.metricCollector.IncCheckErrorCount(ing.ObjectMeta.Namespace, ing.Name)
return err
@ -452,7 +453,7 @@ func (n *NGINXController) getStreamServices(configmapName string, proto apiv1.Pr
return []ingress.L4Service{}
}
var svcs []ingress.L4Service
svcs := make([]ingress.L4Service, 0, len(configmap.Data))
var svcProxyProtocol ingress.ProxyProtocol
rp := []int{
@ -489,10 +490,10 @@ func (n *NGINXController) getStreamServices(configmapName string, proto apiv1.Pr
svcProxyProtocol.Encode = false
// Proxy Protocol is only compatible with TCP Services
if len(nsSvcPort) >= 3 && proto == apiv1.ProtocolTCP {
if len(nsSvcPort) >= 3 && strings.ToUpper(nsSvcPort[2]) == "PROXY" {
if len(nsSvcPort) >= 3 && strings.EqualFold(nsSvcPort[2], "PROXY") {
svcProxyProtocol.Decode = true
}
if len(nsSvcPort) == 4 && strings.ToUpper(nsSvcPort[3]) == "PROXY" {
if len(nsSvcPort) == 4 && strings.EqualFold(nsSvcPort[3], "PROXY") {
svcProxyProtocol.Encode = true
}
}
@ -532,6 +533,7 @@ func (n *NGINXController) getStreamServices(configmapName string, proto apiv1.Pr
klog.V(3).Infof("Searching Endpoints with %v port number %d for Service %q", proto, targetPort, nsName)
for i := range svc.Spec.Ports {
sp := svc.Spec.Ports[i]
//nolint:gosec // Ignore G109 error
if sp.Port == int32(targetPort) {
if sp.Protocol == proto {
endps = getEndpointsFromSlices(svc, &sp, proto, zone, n.store.GetServiceEndpointsSlices)
@ -574,7 +576,7 @@ func (n *NGINXController) getDefaultUpstream() *ingress.Backend {
}
svcKey := n.cfg.DefaultService
if len(svcKey) == 0 {
if svcKey == "" {
upstream.Endpoints = append(upstream.Endpoints, n.DefaultEndpoint())
return upstream
}
@ -690,13 +692,14 @@ func dropSnippetDirectives(anns *annotations.Ingress, ingKey string) {
klog.V(3).Infof("Ingress %q tried to use stream-snippet and the annotation is disabled by the admin. Removing the annotation", ingKey)
anns.StreamSnippet = ""
}
}
}
// getBackendServers returns a list of Upstream and Server to be used by the
// backend. An upstream can be used in multiple servers if the namespace,
// service name and port are the same.
//
//nolint:gocyclo // Ignore function complexity error
func (n *NGINXController) getBackendServers(ingresses []*ingress.Ingress) ([]*ingress.Backend, []*ingress.Server) {
du := n.getDefaultUpstream()
upstreams := n.createUpstreams(ingresses, du)
@ -1030,7 +1033,7 @@ func (n *NGINXController) createUpstreams(data []*ingress.Ingress, du *ingress.B
// configure traffic shaping for canary
if anns.Canary.Enabled {
upstreams[defBackend].NoServer = true
upstreams[defBackend].TrafficShapingPolicy = newTrafficShapingPolicy(anns.Canary)
upstreams[defBackend].TrafficShapingPolicy = newTrafficShapingPolicy(&anns.Canary)
}
if len(upstreams[defBackend].Endpoints) == 0 {
@ -1095,7 +1098,7 @@ func (n *NGINXController) createUpstreams(data []*ingress.Ingress, du *ingress.B
// configure traffic shaping for canary
if anns.Canary.Enabled {
upstreams[name].NoServer = true
upstreams[name].TrafficShapingPolicy = newTrafficShapingPolicy(anns.Canary)
upstreams[name].TrafficShapingPolicy = newTrafficShapingPolicy(&anns.Canary)
}
if len(upstreams[name].Endpoints) == 0 {
@ -1206,7 +1209,6 @@ func (n *NGINXController) serviceEndpoints(svcKey, backendPort string) ([]ingres
if strconv.Itoa(int(servicePort.Port)) == backendPort ||
servicePort.TargetPort.String() == backendPort ||
servicePort.Name == backendPort {
endps := getEndpointsFromSlices(svc, &servicePort, apiv1.ProtocolTCP, zone, n.store.GetServiceEndpointsSlices)
if len(endps) == 0 {
klog.Warningf("Service %q does not have any active Endpoint.", svcKey)
@ -1239,8 +1241,8 @@ func (n *NGINXController) getDefaultSSLCertificate() *ingress.SSLCert {
// one root location, which uses a default backend if left unspecified.
func (n *NGINXController) createServers(data []*ingress.Ingress,
upstreams map[string]*ingress.Backend,
du *ingress.Backend) map[string]*ingress.Server {
du *ingress.Backend,
) map[string]*ingress.Server {
servers := make(map[string]*ingress.Server, len(data))
allAliases := make(map[string][]string, len(data))
@ -1282,7 +1284,8 @@ func (n *NGINXController) createServers(data []*ingress.Ingress,
Rewrite: false,
},
},
}}
},
}
// initialize all other servers
for _, ing := range data {
@ -1532,7 +1535,7 @@ func locationApplyAnnotations(loc *ingress.Location, anns *annotations.Ingress)
}
// OK to merge canary ingresses iff there exists one or more ingresses to potentially merge into
func nonCanaryIngressExists(ingresses []*ingress.Ingress, canaryIngresses []*ingress.Ingress) bool {
func nonCanaryIngressExists(ingresses, canaryIngresses []*ingress.Ingress) bool {
return len(ingresses)-len(canaryIngresses) > 0
}
@ -1540,12 +1543,12 @@ func nonCanaryIngressExists(ingresses []*ingress.Ingress, canaryIngresses []*ing
// 1) names of backends do not match and canary doesn't merge into itself
// 2) primary name is not the default upstream
// 3) the primary has a server
func canMergeBackend(primary *ingress.Backend, alternative *ingress.Backend) bool {
func canMergeBackend(primary, alternative *ingress.Backend) bool {
return alternative != nil && primary.Name != alternative.Name && primary.Name != defUpstreamName && !primary.NoServer
}
// Performs the merge action and checks to ensure that one two alternative backends do not merge into each other
func mergeAlternativeBackend(ing *ingress.Ingress, priUps *ingress.Backend, altUps *ingress.Backend) bool {
func mergeAlternativeBackend(ing *ingress.Ingress, priUps, altUps *ingress.Backend) bool {
if priUps.NoServer {
klog.Warningf("unable to merge alternative backend %v into primary backend %v because %v is a primary backend",
altUps.Name, priUps.Name, priUps.Name)
@ -1563,8 +1566,7 @@ func mergeAlternativeBackend(ing *ingress.Ingress, priUps *ingress.Backend, altU
priUps.SessionAffinity.DeepCopyInto(&altUps.SessionAffinity)
}
priUps.AlternativeBackends =
append(priUps.AlternativeBackends, altUps.Name)
priUps.AlternativeBackends = append(priUps.AlternativeBackends, altUps.Name)
return true
}
@ -1574,8 +1576,8 @@ func mergeAlternativeBackend(ing *ingress.Ingress, priUps *ingress.Backend, altU
// to a backend's alternative list.
// If no match is found, then the serverless backend is deleted.
func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingress.Backend,
servers map[string]*ingress.Server) {
servers map[string]*ingress.Server,
) {
// merge catch-all alternative backends
if ing.Spec.DefaultBackend != nil {
upsName := upstreamName(ing.Namespace, ing.Spec.DefaultBackend.Service)
@ -1585,7 +1587,6 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
if altUps == nil {
klog.Warningf("alternative backend %s has already been removed", upsName)
} else {
merged := false
altEqualsPri := false
@ -1676,8 +1677,8 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
// extractTLSSecretName returns the name of the Secret containing a SSL
// certificate for the given host name, or an empty string.
func extractTLSSecretName(host string, ing *ingress.Ingress,
getLocalSSLCert func(string) (*ingress.SSLCert, error)) string {
getLocalSSLCert func(string) (*ingress.SSLCert, error),
) string {
if ing == nil {
return ""
}
@ -1694,7 +1695,6 @@ func extractTLSSecretName(host string, ing *ingress.Ingress,
// no TLS host matching host name, try each TLS host for matching SAN or CN
for _, tls := range ing.Spec.TLS {
if tls.SecretName == "" {
// There's no secretName specified, so it will never be available
continue
@ -1753,6 +1753,7 @@ func externalNamePorts(name string, svc *apiv1.Service) *apiv1.ServicePort {
}
for _, svcPort := range svc.Spec.Ports {
//nolint:gosec // Ignore G109 error
if svcPort.Port != int32(port) {
continue
}
@ -1771,13 +1772,14 @@ func externalNamePorts(name string, svc *apiv1.Service) *apiv1.ServicePort {
// ExternalName without port
return &apiv1.ServicePort{
Protocol: "TCP",
Protocol: "TCP",
//nolint:gosec // Ignore G109 error
Port: int32(port),
TargetPort: intstr.FromInt(port),
}
}
func checkOverlap(ing *networking.Ingress, ingresses []*ingress.Ingress, servers []*ingress.Server) error {
func checkOverlap(ing *networking.Ingress, servers []*ingress.Server) error {
for _, rule := range ing.Spec.Rules {
if rule.HTTP == nil {
continue
@ -1870,7 +1872,7 @@ func (n *NGINXController) getStreamSnippets(ingresses []*ingress.Ingress) []stri
}
// newTrafficShapingPolicy creates new ingress.TrafficShapingPolicy instance using canary configuration
func newTrafficShapingPolicy(cfg canary.Config) ingress.TrafficShapingPolicy {
func newTrafficShapingPolicy(cfg *canary.Config) ingress.TrafficShapingPolicy {
return ingress.TrafficShapingPolicy{
Weight: cfg.Weight,
WeightTotal: cfg.WeightTotal,

View file

@ -60,51 +60,56 @@ import (
"k8s.io/ingress-nginx/pkg/util/file"
)
const (
exampleBackend = "example-http-svc-1-80"
TRUE = "true"
)
type fakeIngressStore struct {
ingresses []*ingress.Ingress
configuration ngx_config.Configuration
}
func (fakeIngressStore) GetIngressClass(ing *networking.Ingress, icConfig *ingressclass.IngressClassConfiguration) (string, error) {
func (fakeIngressStore) GetIngressClass(_ *networking.Ingress, _ *ingressclass.Configuration) (string, error) {
return "nginx", nil
}
func (fis fakeIngressStore) GetBackendConfiguration() ngx_config.Configuration {
func (fis *fakeIngressStore) GetBackendConfiguration() ngx_config.Configuration {
return fis.configuration
}
func (fis fakeIngressStore) GetSecurityConfiguration() defaults.SecurityConfiguration {
func (fis *fakeIngressStore) GetSecurityConfiguration() defaults.SecurityConfiguration {
return defaults.SecurityConfiguration{
AnnotationsRiskLevel: fis.configuration.AnnotationsRiskLevel,
AllowCrossNamespaceResources: fis.configuration.AllowCrossNamespaceResources,
}
}
func (fakeIngressStore) GetConfigMap(key string) (*corev1.ConfigMap, error) {
func (fakeIngressStore) GetConfigMap(_ string) (*corev1.ConfigMap, error) {
return nil, fmt.Errorf("test error")
}
func (fakeIngressStore) GetSecret(key string) (*corev1.Secret, error) {
func (fakeIngressStore) GetSecret(_ string) (*corev1.Secret, error) {
return nil, fmt.Errorf("test error")
}
func (fakeIngressStore) GetService(key string) (*corev1.Service, error) {
func (fakeIngressStore) GetService(_ string) (*corev1.Service, error) {
return nil, fmt.Errorf("test error")
}
func (fakeIngressStore) GetServiceEndpointsSlices(key string) ([]*discoveryv1.EndpointSlice, error) {
func (fakeIngressStore) GetServiceEndpointsSlices(_ string) ([]*discoveryv1.EndpointSlice, error) {
return nil, fmt.Errorf("test error")
}
func (fis fakeIngressStore) ListIngresses() []*ingress.Ingress {
func (fis *fakeIngressStore) ListIngresses() []*ingress.Ingress {
return fis.ingresses
}
func (fis fakeIngressStore) FilterIngresses(ingresses []*ingress.Ingress, filterFunc store.IngressFilterFunc) []*ingress.Ingress {
func (fis *fakeIngressStore) FilterIngresses(ingresses []*ingress.Ingress, _ store.IngressFilterFunc) []*ingress.Ingress {
return ingresses
}
func (fakeIngressStore) GetLocalSSLCert(name string) (*ingress.SSLCert, error) {
func (fakeIngressStore) GetLocalSSLCert(_ string) (*ingress.SSLCert, error) {
return nil, fmt.Errorf("test error")
}
@ -120,7 +125,7 @@ func (fakeIngressStore) GetDefaultBackend() defaults.Backend {
return defaults.Backend{}
}
func (fakeIngressStore) Run(stopCh chan struct{}) {}
func (fakeIngressStore) Run(_ chan struct{}) {}
type testNginxTestCommand struct {
t *testing.T
@ -129,7 +134,7 @@ type testNginxTestCommand struct {
err error
}
func (ntc testNginxTestCommand) ExecCommand(args ...string) *exec.Cmd {
func (ntc testNginxTestCommand) ExecCommand(_ ...string) *exec.Cmd {
return nil
}
@ -152,7 +157,7 @@ func (ntc testNginxTestCommand) Test(cfg string) ([]byte, error) {
type fakeTemplate struct{}
func (fakeTemplate) Write(conf ngx_config.TemplateConfig) ([]byte, error) {
func (fakeTemplate) Write(conf *ngx_config.TemplateConfig) ([]byte, error) {
r := []byte{}
for _, s := range conf.Servers {
if len(r) > 0 {
@ -196,7 +201,7 @@ func TestCheckIngress(t *testing.T) {
nginx.metricCollector = metric.DummyCollector{}
nginx.t = fakeTemplate{}
nginx.store = fakeIngressStore{
nginx.store = &fakeIngressStore{
ingresses: []*ingress.Ingress{},
}
@ -226,7 +231,7 @@ func TestCheckIngress(t *testing.T) {
}
t.Run("When the hostname is updated", func(t *testing.T) {
nginx.store = fakeIngressStore{
nginx.store = &fakeIngressStore{
ingresses: []*ingress.Ingress{
{
Ingress: *ing,
@ -273,7 +278,7 @@ func TestCheckIngress(t *testing.T) {
})
t.Run("When snippets are disabled and user tries to use snippet annotation", func(t *testing.T) {
nginx.store = fakeIngressStore{
nginx.store = &fakeIngressStore{
ingresses: []*ingress.Ingress{},
configuration: ngx_config.Configuration{
AllowSnippetAnnotations: false,
@ -290,7 +295,7 @@ func TestCheckIngress(t *testing.T) {
})
t.Run("When invalid directives are used in annotation values", func(t *testing.T) {
nginx.store = fakeIngressStore{
nginx.store = &fakeIngressStore{
ingresses: []*ingress.Ingress{},
configuration: ngx_config.Configuration{
AnnotationValueWordBlocklist: "invalid_directive, another_directive",
@ -366,12 +371,11 @@ func TestCheckIngress(t *testing.T) {
}
func TestCheckWarning(t *testing.T) {
// Ensure no panic with wrong arguments
var nginx = &NGINXController{}
nginx := &NGINXController{}
nginx.t = fakeTemplate{}
nginx.store = fakeIngressStore{
nginx.store = &fakeIngressStore{
ingresses: []*ingress.Ingress{},
}
@ -390,7 +394,7 @@ func TestCheckWarning(t *testing.T) {
},
}
t.Run("when a deprecated annotation is used a warning should be returned", func(t *testing.T) {
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("enable-influxdb")] = "true"
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("enable-influxdb")] = TRUE
defer func() {
ing.ObjectMeta.Annotations = map[string]string{}
}()
@ -407,7 +411,6 @@ func TestCheckWarning(t *testing.T) {
})
t.Run("When an invalid pathType is used, a warning should be returned", func(t *testing.T) {
rules := ing.Spec.DeepCopy().Rules
ing.Spec.Rules = []networking.IngressRule{
{
@ -443,8 +446,8 @@ func TestCheckWarning(t *testing.T) {
}
t.Run("adding invalid annotations increases the warning count", func(t *testing.T) {
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("enable-influxdb")] = "true"
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("secure-verify-ca-secret")] = "true"
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("enable-influxdb")] = TRUE
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("secure-verify-ca-secret")] = TRUE
ing.ObjectMeta.Annotations[parser.GetAnnotationWithPrefix("influxdb-host")] = "blabla"
defer func() {
ing.ObjectMeta.Annotations = map[string]string{}
@ -472,6 +475,7 @@ func TestCheckWarning(t *testing.T) {
})
}
//nolint:dupl // Ignore dupl errors for similar test case
func TestMergeAlternativeBackends(t *testing.T) {
testCases := map[string]struct {
ingress *ingress.Ingress
@ -1537,8 +1541,8 @@ func TestExtractTLSSecretName(t *testing.T) {
}
}
//nolint:gocyclo // Ignore function complexity error
func TestGetBackendServers(t *testing.T) {
testCases := []struct {
Ingresses []*ingress.Ingress
Validate func(ingresses []*ingress.Ingress, upstreams []*ingress.Backend, servers []*ingress.Server)
@ -2078,7 +2082,7 @@ func TestGetBackendServers(t *testing.T) {
t.Errorf("server hostname should be 'example.com', got '%s'", s.Hostname)
}
if s.Locations[0].Backend != "example-http-svc-1-80" || s.Locations[1].Backend != "example-http-svc-1-80" || s.Locations[2].Backend != "example-http-svc-1-80" {
if s.Locations[0].Backend != exampleBackend || s.Locations[1].Backend != exampleBackend || s.Locations[2].Backend != exampleBackend {
t.Errorf("all location backend should be 'example-http-svc-1-80'")
}
@ -2087,7 +2091,7 @@ func TestGetBackendServers(t *testing.T) {
return
}
if upstreams[0].Name != "example-http-svc-1-80" {
if upstreams[0].Name != exampleBackend {
t.Errorf("example-http-svc-1-80 should be first upstream, got %s", upstreams[0].Name)
return
}
@ -2101,6 +2105,7 @@ func TestGetBackendServers(t *testing.T) {
SetConfigMap: testConfigMap,
},
{
//nolint:dupl // Ignore dupl errors for similar test case
Ingresses: []*ingress.Ingress{
{
Ingress: networking.Ingress{
@ -2208,6 +2213,7 @@ func TestGetBackendServers(t *testing.T) {
SetConfigMap: testConfigMap,
},
{
//nolint:dupl // Ignore dupl errors for similar test case
Ingresses: []*ingress.Ingress{
{
Ingress: networking.Ingress{
@ -2319,7 +2325,7 @@ func TestGetBackendServers(t *testing.T) {
SelfLink: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/config", ns),
},
Data: map[string]string{
"proxy-ssl-location-only": "true",
"proxy-ssl-location-only": TRUE,
},
}
},
@ -2380,7 +2386,7 @@ func TestGetBackendServers(t *testing.T) {
SelfLink: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/config", ns),
},
Data: map[string]string{
"proxy-ssl-location-only": "true",
"proxy-ssl-location-only": TRUE,
},
}
},
@ -2449,7 +2455,6 @@ func TestGetBackendServers(t *testing.T) {
if len(s.Locations[0].Allowlist.CIDR) != 1 || s.Locations[0].Allowlist.CIDR[0] != "10.0.0.0/24" {
t.Errorf("allow list was incorrectly dropped, len should be 1 and contain 10.0.0.0/24")
}
},
SetConfigMap: func(ns string) *corev1.ConfigMap {
return &corev1.ConfigMap{
@ -2520,7 +2525,7 @@ func newNGINXController(t *testing.T) *NGINXController {
channels.NewRingChannel(10),
false,
true,
&ingressclass.IngressClassConfiguration{
&ingressclass.Configuration{
Controller: "k8s.io/ingress-nginx",
AnnotationValue: "nginx",
},
@ -2586,7 +2591,7 @@ func newDynamicNginxController(t *testing.T, setConfigMap func(string) *corev1.C
channels.NewRingChannel(10),
false,
true,
&ingressclass.IngressClassConfiguration{
&ingressclass.Configuration{
Controller: "k8s.io/ingress-nginx",
AnnotationValue: "nginx",
},

View file

@ -36,8 +36,8 @@ import (
// getEndpointsFromSlices returns a list of Endpoint structs for a given service/target port combination.
func getEndpointsFromSlices(s *corev1.Service, port *corev1.ServicePort, proto corev1.Protocol, zoneForHints string,
getServiceEndpointsSlices func(string) ([]*discoveryv1.EndpointSlice, error)) []ingress.Endpoint {
getServiceEndpointsSlices func(string) ([]*discoveryv1.EndpointSlice, error),
) []ingress.Endpoint {
upsServers := []ingress.Endpoint{}
if s == nil || port == nil {
@ -94,7 +94,7 @@ func getEndpointsFromSlices(s *corev1.Service, port *corev1.ServicePort, proto c
if !reflect.DeepEqual(*epPort.Protocol, proto) {
continue
}
var targetPort int32 = 0
var targetPort int32
if port.Name == "" {
// port.Name is optional if there is only one port
targetPort = *epPort.Port

View file

@ -27,6 +27,7 @@ import (
"k8s.io/ingress-nginx/pkg/apis/ingress"
)
//nolint:dupl // Ignore dupl errors for similar test case
func TestGetEndpointsFromSlices(t *testing.T) {
tests := []struct {
name string

View file

@ -29,9 +29,9 @@ const (
DefaultAnnotationValue = "nginx"
)
// IngressClassConfiguration defines the various aspects of IngressClass parsing
// Configuration defines the various aspects of IngressClass parsing
// and how the controller should behave in each case
type IngressClassConfiguration struct {
type Configuration struct {
// Controller defines the controller value this daemon watch to.
// Defaults to "k8s.io/ingress-nginx" defined in flags
Controller string
@ -45,7 +45,7 @@ type IngressClassConfiguration struct {
// IgnoreIngressClass defines if Controller should ignore the IngressClass Object if no permissions are
// granted on IngressClass
IgnoreIngressClass bool
//IngressClassByName defines if the Controller should watch for Ingress Classes by
// IngressClassByName defines if the Controller should watch for Ingress Classes by
// .metadata.name together with .spec.Controller
IngressClassByName bool
}

View file

@ -113,7 +113,7 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro
if n.cfg.ValidationWebhook != "" {
n.validationWebhookServer = &http.Server{
Addr: config.ValidationWebhook,
//G112 (CWE-400): Potential Slowloris Attack
// G112 (CWE-400): Potential Slowloris Attack
ReadHeaderTimeout: 10 * time.Second,
Handler: adm_controller.NewAdmissionControllerServer(&adm_controller.IngressAdmission{Checker: n}),
TLSConfig: ssl.NewTLSListener(n.cfg.ValidationWebhookCertPath, n.cfg.ValidationWebhookKeyPath).TLSConfig(),
@ -429,7 +429,7 @@ func (n *NGINXController) start(cmd *exec.Cmd) {
}
// DefaultEndpoint returns the default endpoint to be use as default server that returns 404.
func (n NGINXController) DefaultEndpoint() ingress.Endpoint {
func (n *NGINXController) DefaultEndpoint() ingress.Endpoint {
return ingress.Endpoint{
Address: "127.0.0.1",
Port: fmt.Sprintf("%v", n.cfg.ListenPorts.Default),
@ -438,8 +438,9 @@ func (n NGINXController) DefaultEndpoint() ingress.Endpoint {
}
// generateTemplate returns the nginx configuration file content
func (n NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressCfg ingress.Configuration) ([]byte, error) {
//
//nolint:gocritic // the cfg shouldn't be changed, and shouldn't be mutated by other processes while being rendered.
func (n *NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressCfg ingress.Configuration) ([]byte, error) {
if n.cfg.EnableSSLPassthrough {
servers := []*tcpproxy.TCPServer{}
for _, pb := range ingressCfg.PassthroughBackends {
@ -458,6 +459,7 @@ func (n NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressC
}
} else {
for _, sp := range svc.Spec.Ports {
//nolint:gosec // Ignore G109 error
if sp.Port == int32(port) {
port = int(sp.Port)
break
@ -563,7 +565,7 @@ func (n NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressC
if err != nil {
klog.Warningf("Error reading Secret %q from local store: %v", secretName, err)
} else {
nsSecName := strings.Replace(secretName, "/", "-", -1)
nsSecName := strings.ReplaceAll(secretName, "/", "-")
dh, ok := secret.Data["dhparam.pem"]
if ok {
pemFileName, err := ssl.AddOrUpdateDHParam(nsSecName, dh)
@ -589,7 +591,7 @@ func (n NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressC
}
}
tc := ngx_config.TemplateConfig{
tc := &ngx_config.TemplateConfig{
ProxySetHeaders: setHeaders,
AddHeaders: addHeaders,
BacklogSize: sysctlSomaxconn(),
@ -623,7 +625,7 @@ func (n NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressC
// testTemplate checks if the NGINX configuration inside the byte array is valid
// running the command "nginx -t" using a temporal file.
func (n NGINXController) testTemplate(cfg []byte) error {
func (n *NGINXController) testTemplate(cfg []byte) error {
if len(cfg) == 0 {
return fmt.Errorf("invalid NGINX configuration (empty)")
}
@ -658,6 +660,8 @@ Error: %v
// changes were detected. The received backend Configuration is merged with the
// configuration ConfigMap before generating the final configuration file.
// Returns nil in case the backend was successfully reloaded.
//
//nolint:gocritic // the cfg shouldn't be changed, and shouldn't be mutated by other processes while being rendered.
func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
cfg := n.store.GetBackendConfiguration()
cfg.Resolver = n.resolver
@ -667,12 +671,12 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
return err
}
err = createOpentracingCfg(cfg)
err = createOpentracingCfg(&cfg)
if err != nil {
return err
}
err = createOpentelemetryCfg(cfg)
err = createOpentelemetryCfg(&cfg)
if err != nil {
return err
}
@ -683,7 +687,10 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
}
if klog.V(2).Enabled() {
src, _ := os.ReadFile(cfgPath)
src, err := os.ReadFile(cfgPath)
if err != nil {
return err
}
if !bytes.Equal(src, content) {
tmpfile, err := os.CreateTemp("", "new-nginx-cfg")
if err != nil {
@ -694,11 +701,14 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
if err != nil {
return err
}
//nolint:gosec //Ignore G204 error
diffOutput, err := exec.Command("diff", "-I", "'# Configuration.*'", "-u", cfgPath, tmpfile.Name()).CombinedOutput()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
ws := exitError.Sys().(syscall.WaitStatus)
ws, ok := exitError.Sys().(syscall.WaitStatus)
if !ok {
klog.Errorf("unexpected type: %T", exitError.Sys())
}
if ws.ExitStatus() == 2 {
klog.Warningf("Failed to executing diff command: %v", err)
}
@ -828,9 +838,10 @@ func (n *NGINXController) configureDynamically(pcfg *ingress.Configuration) erro
return nil
}
func updateStreamConfiguration(TCPEndpoints []ingress.L4Service, UDPEndpoints []ingress.L4Service) error {
func updateStreamConfiguration(tcpEndpoints, udpEndpoints []ingress.L4Service) error {
streams := make([]ingress.Backend, 0)
for _, ep := range TCPEndpoints {
for i := range tcpEndpoints {
ep := &tcpEndpoints[i]
var service *apiv1.Service
if ep.Service != nil {
service = &apiv1.Service{Spec: ep.Service.Spec}
@ -844,7 +855,8 @@ func updateStreamConfiguration(TCPEndpoints []ingress.L4Service, UDPEndpoints []
Service: service,
})
}
for _, ep := range UDPEndpoints {
for i := range udpEndpoints {
ep := &udpEndpoints[i]
var service *apiv1.Service
if ep.Service != nil {
service = &apiv1.Service{Spec: ep.Service.Spec}
@ -1034,7 +1046,7 @@ ratio = {{ .OtelSamplerRatio }}
parent_based = {{ .OtelSamplerParentBased }}
`
func datadogOpentracingCfg(cfg ngx_config.Configuration) (string, error) {
func datadogOpentracingCfg(cfg *ngx_config.Configuration) (string, error) {
m := map[string]interface{}{
"service": cfg.DatadogServiceName,
"agent_host": cfg.DatadogCollectorHost,
@ -1058,7 +1070,7 @@ func datadogOpentracingCfg(cfg ngx_config.Configuration) (string, error) {
return string(buf), nil
}
func opentracingCfgFromTemplate(cfg ngx_config.Configuration, tmplName string, tmplText string) (string, error) {
func opentracingCfgFromTemplate(cfg *ngx_config.Configuration, tmplName, tmplText string) (string, error) {
tmpl, err := template.New(tmplName).Parse(tmplText)
if err != nil {
return "", err
@ -1073,17 +1085,18 @@ func opentracingCfgFromTemplate(cfg ngx_config.Configuration, tmplName string, t
return tmplBuf.String(), nil
}
func createOpentracingCfg(cfg ngx_config.Configuration) error {
func createOpentracingCfg(cfg *ngx_config.Configuration) error {
var configData string
var err error
if cfg.ZipkinCollectorHost != "" {
switch {
case cfg.ZipkinCollectorHost != "":
configData, err = opentracingCfgFromTemplate(cfg, "zipkin", zipkinTmpl)
} else if cfg.JaegerCollectorHost != "" || cfg.JaegerEndpoint != "" {
case cfg.JaegerCollectorHost != "" || cfg.JaegerEndpoint != "":
configData, err = opentracingCfgFromTemplate(cfg, "jaeger", jaegerTmpl)
} else if cfg.DatadogCollectorHost != "" {
case cfg.DatadogCollectorHost != "":
configData, err = datadogOpentracingCfg(cfg)
} else {
default:
configData = "{}"
}
@ -1097,8 +1110,7 @@ func createOpentracingCfg(cfg ngx_config.Configuration) error {
return os.WriteFile("/etc/nginx/opentracing.json", []byte(expanded), file.ReadWriteByUser)
}
func createOpentelemetryCfg(cfg ngx_config.Configuration) error {
func createOpentelemetryCfg(cfg *ngx_config.Configuration) error {
tmpl, err := template.New("otel").Parse(otelTmpl)
if err != nil {
return err
@ -1123,7 +1135,10 @@ func cleanTempNginxCfg() error {
return filepath.SkipDir
}
dur, _ := time.ParseDuration("-5m")
dur, err := time.ParseDuration("-5m")
if err != nil {
return err
}
fiveMinutesAgo := time.Now().Add(dur)
if strings.HasPrefix(info.Name(), tempNginxPattern) && info.ModTime().Before(fiveMinutesAgo) {
files = append(files, path)

View file

@ -58,6 +58,7 @@ func TestConfigureDynamically(t *testing.T) {
server := &httptest.Server{
Listener: listener,
//nolint:gosec // Ignore not configured ReadHeaderTimeout in testing
Config: &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
@ -76,23 +77,17 @@ func TestConfigureDynamically(t *testing.T) {
switch r.URL.Path {
case "/configuration/backends":
{
if strings.Contains(body, "target") {
t.Errorf("unexpected target reference in JSON content: %v", body)
}
if strings.Contains(body, "target") {
t.Errorf("unexpected target reference in JSON content: %v", body)
}
if !strings.Contains(body, "service") {
t.Errorf("service reference should be present in JSON content: %v", body)
}
if !strings.Contains(body, "service") {
t.Errorf("service reference should be present in JSON content: %v", body)
}
case "/configuration/general":
{
}
case "/configuration/servers":
{
if !strings.Contains(body, `{"certificates":{},"servers":{"myapp.fake":"-1"}}`) {
t.Errorf("should be present in JSON content: %v", body)
}
if !strings.Contains(body, `{"certificates":{},"servers":{"myapp.fake":"-1"}}`) {
t.Errorf("should be present in JSON content: %v", body)
}
default:
t.Errorf("unknown request to %s", r.URL.Path)
@ -218,6 +213,7 @@ func TestConfigureCertificates(t *testing.T) {
server := &httptest.Server{
Listener: listener,
//nolint:gosec // Ignore not configured ReadHeaderTimeout in testing
Config: &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
@ -414,6 +410,7 @@ func TestCleanTempNginxCfg(t *testing.T) {
}
}
//nolint:unparam // Ingnore `network` always receives `"tcp"` error
func tryListen(network, address string) (l net.Listener, err error) {
condFunc := func() (bool, error) {
l, err = net.Listen(network, address)

View file

@ -30,7 +30,10 @@ func IsRespawnIfRequired(err error) bool {
return false
}
waitStatus := exitError.Sys().(syscall.WaitStatus)
waitStatus, ok := exitError.Sys().(syscall.WaitStatus)
if !ok {
return false
}
klog.Warningf(`
-------------------------------------------------------------------------------
NGINX master process died (%v): %v

View file

@ -50,7 +50,7 @@ func setupLeaderElection(config *leaderElectionConfig) {
var cancelContext context.CancelFunc
var newLeaderCtx = func(ctx context.Context) context.CancelFunc {
newLeaderCtx := func(ctx context.Context) context.CancelFunc {
// allow to cancel the context in case we stop being the leader
leaderCtx, cancel := context.WithCancel(ctx)
go elector.Run(leaderCtx)
@ -86,8 +86,10 @@ func setupLeaderElection(config *leaderElectionConfig) {
}
broadcaster := record.NewBroadcaster()
hostname, _ := os.Hostname()
hostname, err := os.Hostname()
if err != nil {
klog.Errorf("unexpected error getting hostname: %v", err)
}
recorder := broadcaster.NewRecorder(scheme.Scheme, apiv1.EventSource{
Component: "ingress-leader-elector",
Host: hostname,
@ -107,7 +109,7 @@ func setupLeaderElection(config *leaderElectionConfig) {
ttl := 30 * time.Second
elector, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
elector, err = leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
Lock: lock,
LeaseDuration: ttl,
RenewDeadline: ttl / 2,

View file

@ -88,10 +88,11 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
auth := secret.Data["auth"]
// namespace/secretName -> namespace-secretName
nsSecName := strings.Replace(secretName, "/", "-", -1)
nsSecName := strings.ReplaceAll(secretName, "/", "-")
var sslCert *ingress.SSLCert
if okcert && okkey {
switch {
case okcert && okkey:
if cert == nil {
return nil, fmt.Errorf("key 'tls.crt' missing from Secret %q", secretName)
}
@ -144,7 +145,7 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
}
klog.V(3).InfoS(msg)
} else if len(ca) > 0 {
case len(ca) > 0:
sslCert, err = ssl.CreateCACert(ca)
if err != nil {
return nil, fmt.Errorf("unexpected error creating SSL Cert: %v", err)
@ -166,7 +167,7 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
// makes this secret in 'syncSecret' to be used for Certificate Authentication
// this does not enable Certificate Authentication
klog.V(3).InfoS("Configuring Secret for TLS authentication", "secret", secretName)
} else {
default:
if auth != nil {
return nil, ErrSecretForAuth
}

View file

@ -38,7 +38,7 @@ func (s *EndpointSliceLister) MatchByKey(key string) ([]*discoveryv1.EndpointSli
keyNsLen = 0
} else {
// count '/' char
keyNsLen += 1
keyNsLen++
}
// filter endpointSlices owned by svc
for _, listKey := range s.ListKeys() {

View file

@ -87,7 +87,6 @@ func TestEndpointSliceLister(t *testing.T) {
t.Errorf("unexpected error %v", err)
}
eps, err := el.MatchByKey(key)
if err != nil {
t.Errorf("unexpeted error %v", err)
}

View file

@ -105,7 +105,7 @@ type Storer interface {
Run(stopCh chan struct{})
// GetIngressClass validates given ingress against ingress class configuration and returns the ingress class.
GetIngressClass(ing *networkingv1.Ingress, icConfig *ingressclass.IngressClassConfiguration) (string, error)
GetIngressClass(ing *networkingv1.Ingress, icConfig *ingressclass.Configuration) (string, error)
}
// EventType type of event associated with an informer
@ -242,7 +242,9 @@ type k8sStore struct {
defaultSSLCertificate string
}
// New creates a new object store to be used in the ingress controller
// New creates a new object store to be used in the ingress controller.
//
//nolint:gocyclo // Ignore function complexity error.
func New(
namespace string,
namespaceSelector labels.Selector,
@ -252,9 +254,9 @@ func New(
updateCh *channels.RingChannel,
disableCatchAll bool,
deepInspector bool,
icConfig *ingressclass.IngressClassConfiguration,
disableSyncEvents bool) Storer {
icConfig *ingressclass.Configuration,
disableSyncEvents bool,
) Storer {
store := &k8sStore{
informers: &Informer{},
listers: &Lister{},
@ -474,7 +476,8 @@ func New(
_, errOld = store.GetIngressClass(oldIng, icConfig)
classCur, errCur = store.GetIngressClass(curIng, icConfig)
}
if errOld != nil && errCur == nil {
switch {
case errOld != nil && errCur == nil:
if hasCatchAllIngressRule(curIng.Spec) && disableCatchAll {
klog.InfoS("ignoring update for catch-all ingress because of --disable-catch-all", "ingress", klog.KObj(curIng))
return
@ -482,11 +485,11 @@ func New(
klog.InfoS("creating ingress", "ingress", klog.KObj(curIng), "ingressclass", classCur)
recorder.Eventf(curIng, corev1.EventTypeNormal, "Sync", "Scheduled for sync")
} else if errOld == nil && errCur != nil {
case errOld == nil && errCur != nil:
klog.InfoS("removing ingress because of unknown ingressclass", "ingress", klog.KObj(curIng))
ingDeleteHandler(old)
return
} else if errCur == nil && !reflect.DeepEqual(old, cur) {
case errCur == nil && !reflect.DeepEqual(old, cur):
if hasCatchAllIngressRule(curIng.Spec) && disableCatchAll {
klog.InfoS("ignoring update for catch-all ingress and delete old one because of --disable-catch-all", "ingress", klog.KObj(curIng))
ingDeleteHandler(old)
@ -494,7 +497,7 @@ func New(
}
recorder.Eventf(curIng, corev1.EventTypeNormal, "Sync", "Scheduled for sync")
} else {
default:
klog.V(3).InfoS("No changes on ingress. Skipping update", "ingress", klog.KObj(curIng))
return
}
@ -519,7 +522,10 @@ func New(
ingressClassEventHandler := cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
ingressclass := obj.(*networkingv1.IngressClass)
ingressclass, ok := obj.(*networkingv1.IngressClass)
if !ok {
klog.Errorf("unexpected type: %T", obj)
}
foundClassByName := false
if icConfig.IngressClassByName && ingressclass.Name == icConfig.AnnotationValue {
klog.InfoS("adding ingressclass as ingress-class-by-name is configured", "ingressclass", klog.KObj(ingressclass))
@ -541,7 +547,10 @@ func New(
}
},
DeleteFunc: func(obj interface{}) {
ingressclass := obj.(*networkingv1.IngressClass)
ingressclass, ok := obj.(*networkingv1.IngressClass)
if !ok {
klog.Errorf("unexpected type: %T", obj)
}
if ingressclass.Spec.Controller != icConfig.Controller {
klog.InfoS("ignoring ingressclass as the spec.controller is not the same of this ingress", "ingressclass", klog.KObj(ingressclass))
return
@ -557,8 +566,14 @@ func New(
}
},
UpdateFunc: func(old, cur interface{}) {
oic := old.(*networkingv1.IngressClass)
cic := cur.(*networkingv1.IngressClass)
oic, ok := old.(*networkingv1.IngressClass)
if !ok {
klog.Errorf("unexpected type: %T", old)
}
cic, ok := cur.(*networkingv1.IngressClass)
if !ok {
klog.Errorf("unexpected type: %T", cur)
}
if cic.Spec.Controller != icConfig.Controller {
klog.InfoS("ignoring ingressclass as the spec.controller is not the same of this ingress", "ingressclass", klog.KObj(cic))
return
@ -581,7 +596,10 @@ func New(
secrEventHandler := cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
sec := obj.(*corev1.Secret)
sec, ok := obj.(*corev1.Secret)
if !ok {
klog.Errorf("unexpected type: %T", obj)
}
key := k8s.MetaNamespaceKey(sec)
if store.defaultSSLCertificate == key {
@ -608,7 +626,10 @@ func New(
},
UpdateFunc: func(old, cur interface{}) {
if !reflect.DeepEqual(old, cur) {
sec := cur.(*corev1.Secret)
sec, ok := cur.(*corev1.Secret)
if !ok {
klog.Errorf("unexpected type: %T", cur)
}
key := k8s.MetaNamespaceKey(sec)
if !watchedNamespace(sec.Namespace) {
@ -695,8 +716,14 @@ func New(
}
},
UpdateFunc: func(old, cur interface{}) {
oeps := old.(*discoveryv1.EndpointSlice)
ceps := cur.(*discoveryv1.EndpointSlice)
oeps, ok := old.(*discoveryv1.EndpointSlice)
if !ok {
klog.Errorf("unexpected type: %T", old)
}
ceps, ok := cur.(*discoveryv1.EndpointSlice)
if !ok {
klog.Errorf("unexpected type: %T", cur)
}
if !reflect.DeepEqual(ceps.Endpoints, oeps.Endpoints) {
updateCh.In() <- Event{
Type: UpdateEvent,
@ -750,7 +777,10 @@ func New(
cmEventHandler := cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
cfgMap := obj.(*corev1.ConfigMap)
cfgMap, ok := obj.(*corev1.ConfigMap)
if !ok {
klog.Errorf("unexpected type: %T", obj)
}
key := k8s.MetaNamespaceKey(cfgMap)
handleCfgMapEvent(key, cfgMap, "CREATE")
},
@ -759,7 +789,10 @@ func New(
return
}
cfgMap := cur.(*corev1.ConfigMap)
cfgMap, ok := cur.(*corev1.ConfigMap)
if !ok {
klog.Errorf("unexpected type: %T", cur)
}
key := k8s.MetaNamespaceKey(cfgMap)
handleCfgMapEvent(key, cfgMap, "UPDATE")
},
@ -767,7 +800,10 @@ func New(
serviceHandler := cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
svc := obj.(*corev1.Service)
svc, ok := obj.(*corev1.Service)
if !ok {
klog.Errorf("unexpected type: %T", obj)
}
if svc.Spec.Type == corev1.ServiceTypeExternalName {
updateCh.In() <- Event{
Type: CreateEvent,
@ -776,7 +812,10 @@ func New(
}
},
DeleteFunc: func(obj interface{}) {
svc := obj.(*corev1.Service)
svc, ok := obj.(*corev1.Service)
if !ok {
klog.Errorf("unexpected type: %T", obj)
}
if svc.Spec.Type == corev1.ServiceTypeExternalName {
updateCh.In() <- Event{
Type: DeleteEvent,
@ -785,8 +824,14 @@ func New(
}
},
UpdateFunc: func(old, cur interface{}) {
oldSvc := old.(*corev1.Service)
curSvc := cur.(*corev1.Service)
oldSvc, ok := old.(*corev1.Service)
if !ok {
klog.Errorf("unexpected type: %T", old)
}
curSvc, ok := cur.(*corev1.Service)
if !ok {
klog.Errorf("unexpected type: %T", cur)
}
if reflect.DeepEqual(oldSvc, curSvc) {
return
@ -821,7 +866,10 @@ func New(
}
// do not wait for informers to read the configmap configuration
ns, name, _ := k8s.ParseNameNS(configmap)
ns, name, err := k8s.ParseNameNS(configmap)
if err != nil {
klog.Errorf("unexpected error parsing name and ns: %v", err)
}
cm, err := client.CoreV1().ConfigMaps(ns).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
klog.Warningf("Unexpected error reading configuration configmap: %v", err)
@ -837,10 +885,10 @@ func hasCatchAllIngressRule(spec networkingv1.IngressSpec) bool {
return spec.DefaultBackend != nil
}
func checkBadAnnotationValue(annotations map[string]string, badwords string) error {
func checkBadAnnotationValue(annotationMap map[string]string, badwords string) error {
arraybadWords := strings.Split(strings.TrimSpace(badwords), ",")
for annotation, value := range annotations {
for annotation, value := range annotationMap {
if strings.HasPrefix(annotation, fmt.Sprintf("%s/", parser.AnnotationsPrefix)) {
for _, forbiddenvalue := range arraybadWords {
if strings.Contains(value, forbiddenvalue) {
@ -999,7 +1047,7 @@ func (s *k8sStore) GetService(key string) (*corev1.Service, error) {
return s.listers.Service.ByKey(key)
}
func (s *k8sStore) GetIngressClass(ing *networkingv1.Ingress, icConfig *ingressclass.IngressClassConfiguration) (string, error) {
func (s *k8sStore) GetIngressClass(ing *networkingv1.Ingress, icConfig *ingressclass.Configuration) (string, error) {
// First we try ingressClassName
if !icConfig.IgnoreIngressClass && ing.Spec.IngressClassName != nil {
iclass, err := s.listers.IngressClass.ByKey(*ing.Spec.IngressClassName)
@ -1010,11 +1058,11 @@ func (s *k8sStore) GetIngressClass(ing *networkingv1.Ingress, icConfig *ingressc
}
// Then we try annotation
if ingressclass, ok := ing.GetAnnotations()[ingressclass.IngressKey]; ok {
if ingressclass != icConfig.AnnotationValue {
if class, ok := ing.GetAnnotations()[ingressclass.IngressKey]; ok {
if class != icConfig.AnnotationValue {
return "", fmt.Errorf("ingress class annotation is not equal to the expected by Ingress Controller")
}
return ingressclass, nil
return class, nil
}
// Then we accept if the WithoutClass is enabled
@ -1055,7 +1103,10 @@ func (s *k8sStore) ListIngresses() []*ingress.Ingress {
// filter ingress rules
ingresses := make([]*ingress.Ingress, 0)
for _, item := range s.listers.IngressWithAnnotation.List() {
ing := item.(*ingress.Ingress)
ing, ok := item.(*ingress.Ingress)
if !ok {
klog.Errorf("unexpected type: %T", item)
}
ingresses = append(ingresses, ing)
}

View file

@ -44,29 +44,27 @@ import (
var pathPrefix networking.PathType = networking.PathTypePrefix
var DefaultClassConfig = &ingressclass.IngressClassConfiguration{
var DefaultClassConfig = &ingressclass.Configuration{
Controller: ingressclass.DefaultControllerName,
AnnotationValue: ingressclass.DefaultAnnotationValue,
WatchWithoutClass: false,
}
var (
commonIngressSpec = networking.IngressSpec{
Rules: []networking.IngressRule{
{
Host: "dummy",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
PathType: &pathPrefix,
Backend: networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: "http-svc",
Port: networking.ServiceBackendPort{
Number: 80,
},
var commonIngressSpec = networking.IngressSpec{
Rules: []networking.IngressRule{
{
Host: "dummy",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
PathType: &pathPrefix,
Backend: networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: "http-svc",
Port: networking.ServiceBackendPort{
Number: 80,
},
},
},
@ -75,12 +73,15 @@ var (
},
},
},
}
)
},
}
const updateDummyHost = "update-dummy"
//nolint:gocyclo // Ignore function complexity error
func TestStore(t *testing.T) {
//TODO: move env definition to docker image?
os.Setenv("KUBEBUILDER_ASSETS", "/usr/local/bin")
// TODO: move env definition to docker image?
t.Setenv("KUBEBUILDER_ASSETS", "/usr/local/bin")
pathPrefix = networking.PathTypePrefix
@ -90,9 +91,12 @@ func TestStore(t *testing.T) {
t.Fatalf("error: %v", err)
}
emptySelector, _ := labels.Parse("")
emptySelector, err := labels.Parse("")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
defer te.Stop() //nolint:errcheck
defer te.Stop() //nolint:errcheck // Ignore the error
clientSet, err := kubernetes.NewForConfig(cfg)
if err != nil {
@ -176,7 +180,11 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -230,7 +238,7 @@ func TestStore(t *testing.T) {
time.Sleep(1 * time.Second)
ni := ing.DeepCopy()
ni.Spec.Rules[0].Host = "update-dummy"
ni.Spec.Rules[0].Host = updateDummyHost
_ = ensureIngress(ni, clientSet, t)
if err != nil {
t.Errorf("error creating ingress: %v", err)
@ -281,7 +289,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -343,7 +354,7 @@ func TestStore(t *testing.T) {
defer deleteIngress(invalidIngress, clientSet, t)
ni := ing.DeepCopy()
ni.Spec.Rules[0].Host = "update-dummy"
ni.Spec.Rules[0].Host = updateDummyHost
_ = ensureIngress(ni, clientSet, t)
if err != nil {
t.Errorf("error creating ingress: %v", err)
@ -392,7 +403,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -411,7 +425,7 @@ func TestStore(t *testing.T) {
}
}(updateCh)
ingressClassconfig := &ingressclass.IngressClassConfiguration{
ingressClassconfig := &ingressclass.Configuration{
Controller: ingressclass.DefaultControllerName,
AnnotationValue: ingressclass.DefaultAnnotationValue,
WatchWithoutClass: true,
@ -463,7 +477,7 @@ func TestStore(t *testing.T) {
time.Sleep(1 * time.Second)
validIngressUpdated := validIngress1.DeepCopy()
validIngressUpdated.Spec.Rules[0].Host = "update-dummy"
validIngressUpdated.Spec.Rules[0].Host = updateDummyHost
_ = ensureIngress(validIngressUpdated, clientSet, t)
if err != nil {
t.Errorf("error updating ingress: %v", err)
@ -523,7 +537,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -542,7 +559,7 @@ func TestStore(t *testing.T) {
}
}(updateCh)
ingressClassconfig := &ingressclass.IngressClassConfiguration{
ingressClassconfig := &ingressclass.Configuration{
Controller: ingressclass.DefaultControllerName,
AnnotationValue: ic,
IngressClassByName: true,
@ -581,7 +598,7 @@ func TestStore(t *testing.T) {
time.Sleep(1 * time.Second)
ingressUpdated := ing.DeepCopy()
ingressUpdated.Spec.Rules[0].Host = "update-dummy"
ingressUpdated.Spec.Rules[0].Host = updateDummyHost
_ = ensureIngress(ingressUpdated, clientSet, t)
if err != nil {
t.Errorf("error updating ingress: %v", err)
@ -630,7 +647,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -684,7 +704,7 @@ func TestStore(t *testing.T) {
time.Sleep(1 * time.Second)
invalidIngressUpdated := invalidIngress.DeepCopy()
invalidIngressUpdated.Spec.Rules[0].Host = "update-dummy"
invalidIngressUpdated.Spec.Rules[0].Host = updateDummyHost
_ = ensureIngress(invalidIngressUpdated, clientSet, t)
if err != nil {
t.Errorf("error creating ingress: %v", err)
@ -725,7 +745,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -778,7 +801,7 @@ func TestStore(t *testing.T) {
time.Sleep(1 * time.Second)
invalidIngressUpdated := invalidIngress.DeepCopy()
invalidIngressUpdated.Spec.Rules[0].Host = "update-dummy"
invalidIngressUpdated.Spec.Rules[0].Host = updateDummyHost
_ = ensureIngress(invalidIngressUpdated, clientSet, t)
if err != nil {
t.Errorf("error creating ingress: %v", err)
@ -816,7 +839,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -908,7 +934,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -1008,7 +1037,6 @@ func TestStore(t *testing.T) {
if atomic.LoadUint64(&del) != 1 {
t.Errorf("expected 1 events of type Delete but %v occurred", del)
}
})
t.Run("should create an ingress with a secret which does not exist", func(t *testing.T) {
@ -1032,7 +1060,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -1159,7 +1190,10 @@ func TestStore(t *testing.T) {
return
}
e := evt.(Event)
e, ok := evt.(Event)
if !ok {
return
}
if e.Obj == nil {
continue
}
@ -1174,7 +1208,10 @@ func TestStore(t *testing.T) {
}
}(updateCh)
namesapceSelector, _ := labels.Parse("foo=bar")
namesapceSelector, err := labels.Parse("foo=bar")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
storer := New(
ns,
namesapceSelector,
@ -1236,7 +1273,6 @@ func TestStore(t *testing.T) {
if atomic.LoadUint64(&del) != 0 {
t.Errorf("expected 0 events of type Delete but %v occurred", del)
}
})
// test add ingress with secret it doesn't exists and then add secret
// check secret is generated on fs
@ -1274,16 +1310,16 @@ func deleteNamespace(ns string, clientSet kubernetes.Interface, t *testing.T) {
func createIngressClass(clientSet kubernetes.Interface, t *testing.T, controller string) string {
t.Helper()
ingressclass := &networking.IngressClass{
class := &networking.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("ingress-nginx-%v", time.Now().Unix()),
//Namespace: "xpto" // TODO: We don't support namespaced ingress-class yet
// Namespace: "xpto" // TODO: We don't support namespaced ingress-class yet
},
Spec: networking.IngressClassSpec{
Controller: controller,
},
}
ic, err := clientSet.NetworkingV1().IngressClasses().Create(context.TODO(), ingressclass, metav1.CreateOptions{})
ic, err := clientSet.NetworkingV1().IngressClasses().Create(context.TODO(), class, metav1.CreateOptions{})
if err != nil {
t.Errorf("error creating ingress class: %v", err)
}
@ -1299,7 +1335,7 @@ func deleteIngressClass(ic string, clientSet kubernetes.Interface, t *testing.T)
}
}
func createConfigMap(clientSet kubernetes.Interface, ns string, t *testing.T) string {
func createConfigMap(clientSet kubernetes.Interface, ns string, t *testing.T) {
t.Helper()
configMap := &v1.ConfigMap{
@ -1308,51 +1344,47 @@ func createConfigMap(clientSet kubernetes.Interface, ns string, t *testing.T) st
},
}
cm, err := clientSet.CoreV1().ConfigMaps(ns).Create(context.TODO(), configMap, metav1.CreateOptions{})
_, err := clientSet.CoreV1().ConfigMaps(ns).Create(context.TODO(), configMap, metav1.CreateOptions{})
if err != nil {
t.Errorf("error creating the configuration map: %v", err)
}
return cm.Name
}
func ensureIngress(ingress *networking.Ingress, clientSet kubernetes.Interface, t *testing.T) *networking.Ingress {
func ensureIngress(ing *networking.Ingress, clientSet kubernetes.Interface, t *testing.T) *networking.Ingress {
t.Helper()
ing, err := clientSet.NetworkingV1().Ingresses(ingress.Namespace).Update(context.TODO(), ingress, metav1.UpdateOptions{})
newIngress, err := clientSet.NetworkingV1().Ingresses(ing.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
if err != nil {
if k8sErrors.IsNotFound(err) {
t.Logf("Ingress %v not found, creating", ingress)
t.Logf("Ingress %v not found, creating", ing)
ing, err = clientSet.NetworkingV1().Ingresses(ingress.Namespace).Create(context.TODO(), ingress, metav1.CreateOptions{})
newIngress, err = clientSet.NetworkingV1().Ingresses(ing.Namespace).Create(context.TODO(), ing, metav1.CreateOptions{})
if err != nil {
t.Fatalf("error creating ingress %+v: %v", ingress, err)
t.Fatalf("error creating ingress %+v: %v", ing, err)
}
t.Logf("Ingress %+v created", ingress)
return ing
t.Logf("Ingress %+v created", ing)
return newIngress
}
t.Fatalf("error updating ingress %+v: %v", ingress, err)
t.Fatalf("error updating ingress %+v: %v", ing, err)
}
return ing
return newIngress
}
func deleteIngress(ingress *networking.Ingress, clientSet kubernetes.Interface, t *testing.T) {
func deleteIngress(ing *networking.Ingress, clientSet kubernetes.Interface, t *testing.T) {
t.Helper()
err := clientSet.NetworkingV1().Ingresses(ingress.Namespace).Delete(context.TODO(), ingress.Name, metav1.DeleteOptions{})
err := clientSet.NetworkingV1().Ingresses(ing.Namespace).Delete(context.TODO(), ing.Name, metav1.DeleteOptions{})
if err != nil {
t.Errorf("failed to delete ingress %+v: %v", ingress, err)
t.Errorf("failed to delete ingress %+v: %v", ing, err)
}
t.Logf("Ingress %+v deleted", ingress)
t.Logf("Ingress %+v deleted", ing)
}
// newStore creates a new mock object store for tests which do not require the
// use of Informers.
func newStore(t *testing.T) *k8sStore {
func newStore() *k8sStore {
return &k8sStore{
listers: &Lister{
// add more listers if needed
@ -1369,7 +1401,7 @@ func newStore(t *testing.T) *k8sStore {
}
func TestUpdateSecretIngressMap(t *testing.T) {
s := newStore(t)
s := newStore()
ingTpl := &networking.Ingress{
ObjectMeta: metav1.ObjectMeta{
@ -1431,7 +1463,9 @@ func TestUpdateSecretIngressMap(t *testing.T) {
ing.ObjectMeta.SetAnnotations(map[string]string{
parser.GetAnnotationWithPrefix("auth-secret"): "anotherns/auth",
})
s.listers.Ingress.Update(ing)
if err := s.listers.Ingress.Update(ing); err != nil {
t.Errorf("error updating the Ingress: %v", err)
}
s.updateSecretIngressMap(ing)
if l := s.secretIngressMap.Len(); l != 0 {
@ -1456,7 +1490,7 @@ func TestUpdateSecretIngressMap(t *testing.T) {
}
func TestListIngresses(t *testing.T) {
s := newStore(t)
s := newStore()
invalidIngressClass := "something"
validIngressClass := ingressclass.DefaultControllerName
@ -1586,7 +1620,7 @@ func TestWriteSSLSessionTicketKey(t *testing.T) {
}
for _, test := range tests {
s := newStore(t)
s := newStore()
cmap := &v1.ConfigMap{
Data: map[string]string{

View file

@ -91,6 +91,8 @@ const (
)
// ReadConfig obtains the configuration defined by the user merged with the defaults.
//
//nolint:gocyclo // Ignore function complexity error
func ReadConfig(src map[string]string) config.Configuration {
conf := map[string]string{}
// we need to copy the configmap data because the content is altered
@ -116,12 +118,12 @@ func ReadConfig(src map[string]string) config.Configuration {
luaSharedDicts := make(map[string]int)
debugConnectionsList := make([]string, 0)
//parse lua shared dict values
// parse lua shared dict values
if val, ok := conf[luaSharedDictsKey]; ok {
delete(conf, luaSharedDictsKey)
lsd := splitAndTrimSpace(val, ",")
for _, v := range lsd {
v = strings.Replace(v, " ", "", -1)
v = strings.ReplaceAll(v, " ", "")
results := strings.SplitN(v, ":", 2)
dictName := results[0]
size := dictStrToKb(results[1])
@ -196,7 +198,7 @@ func ReadConfig(src map[string]string) config.Configuration {
if ing_net.IsIPV6(ns) {
bindAddressIpv6List = append(bindAddressIpv6List, fmt.Sprintf("[%v]", ns))
} else {
bindAddressIpv4List = append(bindAddressIpv4List, fmt.Sprintf("%v", ns))
bindAddressIpv4List = append(bindAddressIpv4List, ns.String())
}
} else {
klog.Warningf("%v is not a valid textual representation of an IP address", i)
@ -250,7 +252,7 @@ func ReadConfig(src map[string]string) config.Configuration {
if val, ok := conf[globalAuthMethod]; ok {
delete(conf, globalAuthMethod)
if len(val) != 0 && !authreq.ValidMethod(val) {
if val != "" && !authreq.ValidMethod(val) {
klog.Warningf("Global auth location denied - %v.", "invalid HTTP method")
} else {
to.GlobalExternalAuth.Method = val
@ -261,7 +263,10 @@ func ReadConfig(src map[string]string) config.Configuration {
if val, ok := conf[globalAuthSignin]; ok {
delete(conf, globalAuthSignin)
signinURL, _ := parser.StringToURL(val)
signinURL, err := parser.StringToURL(val)
if err != nil {
klog.Errorf("string to URL conversion failed: %v", err)
}
if signinURL == nil {
klog.Warningf("Global auth location denied - %v.", "global-auth-signin setting is undefined and will not be set")
} else {
@ -274,7 +279,10 @@ func ReadConfig(src map[string]string) config.Configuration {
delete(conf, globalAuthSigninRedirectParam)
redirectParam := strings.TrimSpace(val)
dummySigninURL, _ := parser.StringToURL(fmt.Sprintf("%s?%s=dummy", to.GlobalExternalAuth.SigninURL, redirectParam))
dummySigninURL, err := parser.StringToURL(fmt.Sprintf("%s?%s=dummy", to.GlobalExternalAuth.SigninURL, redirectParam))
if err != nil {
klog.Errorf("string to URL conversion failed: %v", err)
}
if dummySigninURL == nil {
klog.Warningf("Global auth redirect parameter denied - %v.", "global-auth-signin-redirect-param setting is invalid and will not be set")
} else {
@ -286,7 +294,7 @@ func ReadConfig(src map[string]string) config.Configuration {
if val, ok := conf[globalAuthResponseHeaders]; ok {
delete(conf, globalAuthResponseHeaders)
if len(val) != 0 {
if val != "" {
harr := splitAndTrimSpace(val, ",")
for _, header := range harr {
if !authreq.ValidHeader(header) {
@ -385,8 +393,8 @@ func ReadConfig(src map[string]string) config.Configuration {
if val, ok := conf[debugConnections]; ok {
delete(conf, debugConnections)
for _, i := range splitAndTrimSpace(val, ",") {
validIp := net.ParseIP(i)
if validIp != nil {
validIP := net.ParseIP(i)
if validIP != nil {
debugConnectionsList = append(debugConnectionsList, i)
} else {
_, _, err := net.ParseCIDR(i)
@ -415,14 +423,14 @@ func ReadConfig(src map[string]string) config.Configuration {
to.DisableIpv6DNS = !ing_net.IsIPv6Enabled()
to.LuaSharedDicts = luaSharedDicts
config := &mapstructure.DecoderConfig{
decoderConfig := &mapstructure.DecoderConfig{
Metadata: nil,
WeaklyTypedInput: true,
Result: &to,
TagName: "json",
}
decoder, err := mapstructure.NewDecoder(config)
decoder, err := mapstructure.NewDecoder(decoderConfig)
if err != nil {
klog.Warningf("unexpected error merging defaults: %v", err)
}
@ -456,6 +464,7 @@ func filterErrors(codes []int) []int {
return fa
}
//nolint:unparam // Ignore `sep` always receives `,` error
func splitAndTrimSpace(s, sep string) []string {
f := func(c rune) bool {
return strings.EqualFold(string(c), sep)
@ -474,8 +483,11 @@ func dictStrToKb(sizeStr string) int {
if sizeMatch == nil {
return -1
}
size, _ := strconv.Atoi(sizeMatch[1]) // validated already with regex
if sizeMatch[2] == "" || strings.ToLower(sizeMatch[2]) == "m" {
size, err := strconv.Atoi(sizeMatch[1]) // validated already with regex
if err != nil {
klog.Errorf("unexpected error converting size string %s to int: %v", sizeStr, err)
}
if sizeMatch[2] == "" || strings.EqualFold(sizeMatch[2], "m") {
size *= 1024
}
return size

View file

@ -52,6 +52,12 @@ const (
nonIdempotent = "non_idempotent"
defBufferSize = 65535
writeIndentOnEmptyLines = true // backward-compatibility
httpProtocol = "HTTP"
autoHTTPProtocol = "AUTO_HTTP"
httpsProtocol = "HTTPS"
grpcProtocol = "GRPC"
grpcsProtocol = "GRPCS"
fcgiProtocol = "FCGI"
)
const (
@ -64,13 +70,13 @@ type Writer interface {
// Write renders the template.
// NOTE: Implementors must ensure that the content of the returned slice is not modified by the implementation
// after the return of this function.
Write(conf config.TemplateConfig) ([]byte, error)
Write(conf *config.TemplateConfig) ([]byte, error)
}
// Template ...
// Template ingress template
type Template struct {
tmpl *text_template.Template
//fw watch.FileWatcher
bp *BufferPool
}
@ -97,7 +103,7 @@ func NewTemplate(file string) (*Template, error) {
// 2. Collapses multiple empty lines to single one
// 3. Re-indent
// (ATW: always returns nil)
func cleanConf(in *bytes.Buffer, out *bytes.Buffer) error {
func cleanConf(in, out *bytes.Buffer) error {
depth := 0
lineStarted := false
emptyLineWritten := false
@ -176,7 +182,7 @@ func cleanConf(in *bytes.Buffer, out *bytes.Buffer) error {
// Write populates a buffer using a template with NGINX configuration
// and the servers and upstreams created by Ingress rules
func (t *Template) Write(conf config.TemplateConfig) ([]byte, error) {
func (t *Template) Write(conf *config.TemplateConfig) ([]byte, error) {
tmplBuf := t.bp.Get()
defer t.bp.Put(tmplBuf)
@ -184,14 +190,14 @@ func (t *Template) Write(conf config.TemplateConfig) ([]byte, error) {
defer t.bp.Put(outCmdBuf)
if klog.V(3).Enabled() {
b, err := json.Marshal(conf)
b, err := json.Marshal(*conf)
if err != nil {
klog.Errorf("unexpected error: %v", err)
}
klog.InfoS("NGINX", "configuration", string(b))
}
err := t.tmpl.Execute(tmplBuf, conf)
err := t.tmpl.Execute(tmplBuf, *conf)
if err != nil {
return nil, err
}
@ -211,78 +217,76 @@ func (t *Template) Write(conf config.TemplateConfig) ([]byte, error) {
return res, nil
}
var (
funcMap = text_template.FuncMap{
"empty": func(input interface{}) bool {
check, ok := input.(string)
if ok {
return len(check) == 0
}
return true
},
"escapeLiteralDollar": escapeLiteralDollar,
"buildLuaSharedDictionaries": buildLuaSharedDictionaries,
"luaConfigurationRequestBodySize": luaConfigurationRequestBodySize,
"buildLocation": buildLocation,
"buildAuthLocation": buildAuthLocation,
"shouldApplyGlobalAuth": shouldApplyGlobalAuth,
"buildAuthResponseHeaders": buildAuthResponseHeaders,
"buildAuthUpstreamLuaHeaders": buildAuthUpstreamLuaHeaders,
"buildAuthProxySetHeaders": buildAuthProxySetHeaders,
"buildAuthUpstreamName": buildAuthUpstreamName,
"shouldApplyAuthUpstream": shouldApplyAuthUpstream,
"extractHostPort": extractHostPort,
"changeHostPort": changeHostPort,
"buildProxyPass": buildProxyPass,
"filterRateLimits": filterRateLimits,
"buildRateLimitZones": buildRateLimitZones,
"buildRateLimit": buildRateLimit,
"configForLua": configForLua,
"locationConfigForLua": locationConfigForLua,
"buildResolvers": buildResolvers,
"buildUpstreamName": buildUpstreamName,
"isLocationInLocationList": isLocationInLocationList,
"isLocationAllowed": isLocationAllowed,
"buildDenyVariable": buildDenyVariable,
"getenv": os.Getenv,
"contains": strings.Contains,
"split": strings.Split,
"hasPrefix": strings.HasPrefix,
"hasSuffix": strings.HasSuffix,
"trimSpace": strings.TrimSpace,
"toUpper": strings.ToUpper,
"toLower": strings.ToLower,
"formatIP": formatIP,
"quote": quote,
"buildNextUpstream": buildNextUpstream,
"getIngressInformation": getIngressInformation,
"serverConfig": func(all config.TemplateConfig, server *ingress.Server) interface{} {
return struct{ First, Second interface{} }{all, server}
},
"isValidByteSize": isValidByteSize,
"buildForwardedFor": buildForwardedFor,
"buildAuthSignURL": buildAuthSignURL,
"buildAuthSignURLLocation": buildAuthSignURLLocation,
"buildOpentracing": buildOpentracing,
"buildOpentelemetry": buildOpentelemetry,
"proxySetHeader": proxySetHeader,
"enforceRegexModifier": enforceRegexModifier,
"buildCustomErrorDeps": buildCustomErrorDeps,
"buildCustomErrorLocationsPerServer": buildCustomErrorLocationsPerServer,
"shouldLoadModSecurityModule": shouldLoadModSecurityModule,
"buildHTTPListener": buildHTTPListener,
"buildHTTPSListener": buildHTTPSListener,
"buildOpentracingForLocation": buildOpentracingForLocation,
"buildOpentelemetryForLocation": buildOpentelemetryForLocation,
"shouldLoadOpentracingModule": shouldLoadOpentracingModule,
"shouldLoadOpentelemetryModule": shouldLoadOpentelemetryModule,
"buildModSecurityForLocation": buildModSecurityForLocation,
"buildMirrorLocations": buildMirrorLocations,
"shouldLoadAuthDigestModule": shouldLoadAuthDigestModule,
"buildServerName": buildServerName,
"buildCorsOriginRegex": buildCorsOriginRegex,
}
)
var funcMap = text_template.FuncMap{
"empty": func(input interface{}) bool {
check, ok := input.(string)
if ok {
return check == ""
}
return true
},
"escapeLiteralDollar": escapeLiteralDollar,
"buildLuaSharedDictionaries": buildLuaSharedDictionaries,
"luaConfigurationRequestBodySize": luaConfigurationRequestBodySize,
"buildLocation": buildLocation,
"buildAuthLocation": buildAuthLocation,
"shouldApplyGlobalAuth": shouldApplyGlobalAuth,
"buildAuthResponseHeaders": buildAuthResponseHeaders,
"buildAuthUpstreamLuaHeaders": buildAuthUpstreamLuaHeaders,
"buildAuthProxySetHeaders": buildAuthProxySetHeaders,
"buildAuthUpstreamName": buildAuthUpstreamName,
"shouldApplyAuthUpstream": shouldApplyAuthUpstream,
"extractHostPort": extractHostPort,
"changeHostPort": changeHostPort,
"buildProxyPass": buildProxyPass,
"filterRateLimits": filterRateLimits,
"buildRateLimitZones": buildRateLimitZones,
"buildRateLimit": buildRateLimit,
"configForLua": configForLua,
"locationConfigForLua": locationConfigForLua,
"buildResolvers": buildResolvers,
"buildUpstreamName": buildUpstreamName,
"isLocationInLocationList": isLocationInLocationList,
"isLocationAllowed": isLocationAllowed,
"buildDenyVariable": buildDenyVariable,
"getenv": os.Getenv,
"contains": strings.Contains,
"split": strings.Split,
"hasPrefix": strings.HasPrefix,
"hasSuffix": strings.HasSuffix,
"trimSpace": strings.TrimSpace,
"toUpper": strings.ToUpper,
"toLower": strings.ToLower,
"formatIP": formatIP,
"quote": quote,
"buildNextUpstream": buildNextUpstream,
"getIngressInformation": getIngressInformation,
"serverConfig": func(all config.TemplateConfig, server *ingress.Server) interface{} {
return struct{ First, Second interface{} }{all, server}
},
"isValidByteSize": isValidByteSize,
"buildForwardedFor": buildForwardedFor,
"buildAuthSignURL": buildAuthSignURL,
"buildAuthSignURLLocation": buildAuthSignURLLocation,
"buildOpentracing": buildOpentracing,
"buildOpentelemetry": buildOpentelemetry,
"proxySetHeader": proxySetHeader,
"enforceRegexModifier": enforceRegexModifier,
"buildCustomErrorDeps": buildCustomErrorDeps,
"buildCustomErrorLocationsPerServer": buildCustomErrorLocationsPerServer,
"shouldLoadModSecurityModule": shouldLoadModSecurityModule,
"buildHTTPListener": buildHTTPListener,
"buildHTTPSListener": buildHTTPSListener,
"buildOpentracingForLocation": buildOpentracingForLocation,
"buildOpentelemetryForLocation": buildOpentelemetryForLocation,
"shouldLoadOpentracingModule": shouldLoadOpentracingModule,
"shouldLoadOpentelemetryModule": shouldLoadOpentelemetryModule,
"buildModSecurityForLocation": buildModSecurityForLocation,
"buildMirrorLocations": buildMirrorLocations,
"shouldLoadAuthDigestModule": shouldLoadAuthDigestModule,
"buildServerName": buildServerName,
"buildCorsOriginRegex": buildCorsOriginRegex,
}
// escapeLiteralDollar will replace the $ character with ${literal_dollar}
// which is made to work via the following configuration in the http section of
@ -296,7 +300,7 @@ func escapeLiteralDollar(input interface{}) string {
if !ok {
return ""
}
return strings.Replace(inputStr, `$`, `${literal_dollar}`, -1)
return strings.ReplaceAll(inputStr, `$`, `${literal_dollar}`)
}
// formatIP will wrap IPv6 addresses in [] and return IPv4 addresses
@ -328,9 +332,7 @@ func quote(input interface{}) string {
return fmt.Sprintf("%q", inputStr)
}
func buildLuaSharedDictionaries(c interface{}, s interface{}) string {
var out []string
func buildLuaSharedDictionaries(c, s interface{}) string {
cfg, ok := c.(config.Configuration)
if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
@ -343,6 +345,7 @@ func buildLuaSharedDictionaries(c interface{}, s interface{}) string {
return ""
}
out := make([]string, 0, len(cfg.LuaSharedDicts))
for name, size := range cfg.LuaSharedDicts {
sizeStr := dictKbToStr(size)
out = append(out, fmt.Sprintf("lua_shared_dict %s %s", name, sizeStr))
@ -364,7 +367,7 @@ func luaConfigurationRequestBodySize(c interface{}) string {
if size < cfg.LuaSharedDicts["certificate_data"] {
size = cfg.LuaSharedDicts["certificate_data"]
}
size = size + 1024
size += 1024
return dictKbToStr(size)
}
@ -418,7 +421,7 @@ func configForLua(input interface{}) string {
}
// locationConfigForLua formats some location specific configuration into Lua table represented as string
func locationConfigForLua(l interface{}, a interface{}) string {
func locationConfigForLua(l, a interface{}) string {
location, ok := l.(*ingress.Location)
if !ok {
klog.Errorf("expected an '*ingress.Location' type but %T was given", l)
@ -459,7 +462,7 @@ func locationConfigForLua(l interface{}, a interface{}) string {
}
// buildResolvers returns the resolvers reading the /etc/resolv.conf file
func buildResolvers(res interface{}, disableIpv6 interface{}) string {
func buildResolvers(res, disableIpv6 interface{}) string {
// NGINX need IPV6 addresses to be surrounded by brackets
nss, ok := res.([]net.IP)
if !ok {
@ -484,7 +487,7 @@ func buildResolvers(res interface{}, disableIpv6 interface{}) string {
}
r = append(r, fmt.Sprintf("[%v]", ns))
} else {
r = append(r, fmt.Sprintf("%v", ns))
r = append(r, ns.String())
}
}
r = append(r, "valid=30s")
@ -554,7 +557,7 @@ func buildAuthLocation(input interface{}, globalExternalAuthURL string) string {
str := base64.URLEncoding.EncodeToString([]byte(location.Path))
// removes "=" after encoding
str = strings.Replace(str, "=", "", -1)
str = strings.ReplaceAll(str, "=", "")
pathType := "default"
if location.PathType != nil {
@ -644,7 +647,7 @@ func buildAuthUpstreamName(input interface{}, host string) string {
// shouldApplyAuthUpstream returns true only in case when ExternalAuth.URL and
// ExternalAuth.KeepaliveConnections are all set
func shouldApplyAuthUpstream(l interface{}, c interface{}) bool {
func shouldApplyAuthUpstream(l, c interface{}) bool {
location, ok := l.(*ingress.Location)
if !ok {
klog.Errorf("expected an '*ingress.Location' type but %T was returned", l)
@ -672,14 +675,14 @@ func shouldApplyAuthUpstream(l interface{}, c interface{}) bool {
}
// extractHostPort will extract the host:port part from the URL specified by url
func extractHostPort(url string) string {
if url == "" {
func extractHostPort(newURL string) string {
if newURL == "" {
return ""
}
authURL, err := parser.StringToURL(url)
authURL, err := parser.StringToURL(newURL)
if err != nil {
klog.Errorf("expected a valid URL but %s was returned", url)
klog.Errorf("expected a valid URL but %s was returned", newURL)
return ""
}
@ -687,14 +690,14 @@ func extractHostPort(url string) string {
}
// changeHostPort will change the host:port part of the url to value
func changeHostPort(url string, value string) string {
if url == "" {
func changeHostPort(newURL, value string) string {
if newURL == "" {
return ""
}
authURL, err := parser.StringToURL(url)
authURL, err := parser.StringToURL(newURL)
if err != nil {
klog.Errorf("expected a valid URL but %s was returned", url)
klog.Errorf("expected a valid URL but %s was returned", newURL)
return ""
}
@ -707,7 +710,7 @@ func changeHostPort(url string, value string) string {
// (specified through the nginx.ingress.kubernetes.io/rewrite-target annotation)
// If the annotation nginx.ingress.kubernetes.io/add-base-url:"true" is specified it will
// add a base tag in the head of the response from the service
func buildProxyPass(host string, b interface{}, loc interface{}) string {
func buildProxyPass(_ string, b, loc interface{}) string {
backends, ok := b.([]*ingress.Backend)
if !ok {
klog.Errorf("expected an '[]*ingress.Backend' type but %T was returned", b)
@ -726,17 +729,17 @@ func buildProxyPass(host string, b interface{}, loc interface{}) string {
proxyPass := "proxy_pass"
switch location.BackendProtocol {
case "AUTO_HTTP":
case autoHTTPProtocol:
proto = "$scheme://"
case "HTTPS":
case httpsProtocol:
proto = "https://"
case "GRPC":
case grpcProtocol:
proto = "grpc://"
proxyPass = "grpc_pass"
case "GRPCS":
case grpcsProtocol:
proto = "grpcs://"
proxyPass = "grpc_pass"
case "FCGI":
case fcgiProtocol:
proto = ""
proxyPass = "fastcgi_pass"
}
@ -748,7 +751,7 @@ func buildProxyPass(host string, b interface{}, loc interface{}) string {
if backend.SSLPassthrough {
proto = "https://"
if location.BackendProtocol == "GRPCS" {
if location.BackendProtocol == grpcsProtocol {
proto = "grpcs://"
}
}
@ -775,7 +778,7 @@ func buildProxyPass(host string, b interface{}, loc interface{}) string {
var xForwardedPrefix string
if len(location.XForwardedPrefix) > 0 {
xForwardedPrefix = fmt.Sprintf("%s X-Forwarded-Prefix \"%s\";\n", proxySetHeader(location), location.XForwardedPrefix)
xForwardedPrefix = fmt.Sprintf("%s X-Forwarded-Prefix %q;\n", proxySetHeader(location), location.XForwardedPrefix)
}
return fmt.Sprintf(`
@ -935,9 +938,7 @@ func isLocationAllowed(input interface{}) bool {
return loc.Denied == nil
}
var (
denyPathSlugMap = map[string]string{}
)
var denyPathSlugMap = map[string]string{}
// buildDenyVariable returns a nginx variable for a location in a
// server to be used in the whitelist check
@ -977,7 +978,11 @@ func buildNextUpstream(i, r interface{}) string {
return ""
}
retryNonIdempotent := r.(bool)
retryNonIdempotent, ok := r.(bool)
if !ok {
klog.Errorf("expected a 'bool' type but %T was returned", i)
return ""
}
parts := strings.Split(nextUpstream, " ")
@ -1002,8 +1007,10 @@ func buildNextUpstream(i, r interface{}) string {
// refer to http://nginx.org/en/docs/syntax.html
// Nginx differentiates between size and offset
// offset directives support gigabytes in addition
var nginxSizeRegex = regexp.MustCompile("^[0-9]+[kKmM]{0,1}$")
var nginxOffsetRegex = regexp.MustCompile("^[0-9]+[kKmMgG]{0,1}$")
var (
nginxSizeRegex = regexp.MustCompile(`^\d+[kKmM]?$`)
nginxOffsetRegex = regexp.MustCompile(`^\d+[kKmMgG]?$`)
)
// isValidByteSize validates size units valid in nginx
// http://nginx.org/en/docs/syntax.html
@ -1153,13 +1160,17 @@ func buildForwardedFor(input interface{}) string {
return ""
}
ffh := strings.Replace(s, "-", "_", -1)
ffh := strings.ReplaceAll(s, "-", "_")
ffh = strings.ToLower(ffh)
return fmt.Sprintf("$http_%v", ffh)
}
func buildAuthSignURL(authSignURL, authRedirectParam string) string {
u, _ := url.Parse(authSignURL)
u, err := url.Parse(authSignURL)
if err != nil {
klog.Errorf("error parsing authSignURL: %v", err)
return ""
}
q := u.Query()
if authRedirectParam == "" {
authRedirectParam = defaultGlobalAuthRedirectParam
@ -1198,7 +1209,7 @@ func randomString() string {
return string(b)
}
func buildOpentracing(c interface{}, s interface{}) string {
func buildOpentracing(c, s interface{}) string {
cfg, ok := c.(config.Configuration)
if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
@ -1217,6 +1228,7 @@ func buildOpentracing(c interface{}, s interface{}) string {
buf := bytes.NewBufferString("")
//nolint:gocritic // rewriting if-else to switch statement is not more readable
if cfg.DatadogCollectorHost != "" {
buf.WriteString("opentracing_load_tracer /usr/local/lib/libdd_opentracing.so /etc/nginx/opentracing.json;")
} else if cfg.ZipkinCollectorHost != "" {
@ -1228,16 +1240,16 @@ func buildOpentracing(c interface{}, s interface{}) string {
buf.WriteString("\r\n")
if cfg.OpentracingOperationName != "" {
buf.WriteString(fmt.Sprintf("opentracing_operation_name \"%s\";\n", cfg.OpentracingOperationName))
fmt.Fprintf(buf, "opentracing_operation_name \"%s\";\n", cfg.OpentracingOperationName)
}
if cfg.OpentracingLocationOperationName != "" {
buf.WriteString(fmt.Sprintf("opentracing_location_operation_name \"%s\";\n", cfg.OpentracingLocationOperationName))
fmt.Fprintf(buf, "opentracing_location_operation_name \"%s\";\n", cfg.OpentracingLocationOperationName)
}
return buf.String()
}
func buildOpentelemetry(c interface{}, s interface{}) string {
func buildOpentelemetry(c, s interface{}) string {
cfg, ok := c.(config.Configuration)
if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
@ -1259,7 +1271,7 @@ func buildOpentelemetry(c interface{}, s interface{}) string {
buf.WriteString("\r\n")
if cfg.OpentelemetryOperationName != "" {
buf.WriteString(fmt.Sprintf("opentelemetry_operation_name \"%s\";\n", cfg.OpentelemetryOperationName))
fmt.Fprintf(buf, "opentelemetry_operation_name \"%s\";\n", cfg.OpentelemetryOperationName)
}
return buf.String()
}
@ -1271,7 +1283,7 @@ func proxySetHeader(loc interface{}) string {
return "proxy_set_header"
}
if location.BackendProtocol == "GRPC" || location.BackendProtocol == "GRPCS" {
if location.BackendProtocol == grpcProtocol || location.BackendProtocol == grpcsProtocol {
return "grpc_set_header"
}
@ -1280,7 +1292,7 @@ func proxySetHeader(loc interface{}) string {
// buildCustomErrorDeps is a utility function returning a struct wrapper with
// the data required to build the 'CUSTOM_ERRORS' template
func buildCustomErrorDeps(upstreamName string, errorCodes []int, enableMetrics bool, modsecurityEnabled bool) interface{} {
func buildCustomErrorDeps(upstreamName string, errorCodes []int, enableMetrics, modsecurityEnabled bool) interface{} {
return struct {
UpstreamName string
ErrorCodes []int
@ -1355,7 +1367,7 @@ func opentracingPropagateContext(location *ingress.Location) string {
return ""
}
if location.BackendProtocol == "GRPC" || location.BackendProtocol == "GRPCS" {
if location.BackendProtocol == grpcProtocol || location.BackendProtocol == grpcsProtocol {
return "opentracing_grpc_propagate_context;"
}
@ -1372,7 +1384,7 @@ func opentelemetryPropagateContext(location *ingress.Location) string {
// shouldLoadModSecurityModule determines whether or not the ModSecurity module needs to be loaded.
// First, it checks if `enable-modsecurity` is set in the ConfigMap. If it is not, it iterates over all locations to
// check if ModSecurity is enabled by the annotation `nginx.ingress.kubernetes.io/enable-modsecurity`.
func shouldLoadModSecurityModule(c interface{}, s interface{}) bool {
func shouldLoadModSecurityModule(c, s interface{}) bool {
cfg, ok := c.(config.Configuration)
if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
@ -1403,7 +1415,7 @@ func shouldLoadModSecurityModule(c interface{}, s interface{}) bool {
return false
}
func buildHTTPListener(t interface{}, s interface{}) string {
func buildHTTPListener(t, s interface{}) string {
var out []string
tc, ok := t.(config.TemplateConfig)
@ -1423,9 +1435,9 @@ func buildHTTPListener(t interface{}, s interface{}) string {
addrV4 = tc.Cfg.BindAddressIpv4
}
co := commonListenOptions(tc, hostname)
co := commonListenOptions(&tc, hostname)
out = append(out, httpListener(addrV4, co, tc)...)
out = append(out, httpListener(addrV4, co, &tc)...)
if !tc.IsIPV6Enabled {
return strings.Join(out, "\n")
@ -1436,12 +1448,12 @@ func buildHTTPListener(t interface{}, s interface{}) string {
addrV6 = tc.Cfg.BindAddressIpv6
}
out = append(out, httpListener(addrV6, co, tc)...)
out = append(out, httpListener(addrV6, co, &tc)...)
return strings.Join(out, "\n")
}
func buildHTTPSListener(t interface{}, s interface{}) string {
func buildHTTPSListener(t, s interface{}) string {
var out []string
tc, ok := t.(config.TemplateConfig)
@ -1456,14 +1468,14 @@ func buildHTTPSListener(t interface{}, s interface{}) string {
return ""
}
co := commonListenOptions(tc, hostname)
co := commonListenOptions(&tc, hostname)
addrV4 := []string{""}
if len(tc.Cfg.BindAddressIpv4) > 0 {
addrV4 = tc.Cfg.BindAddressIpv4
}
out = append(out, httpsListener(addrV4, co, tc)...)
out = append(out, httpsListener(addrV4, co, &tc)...)
if !tc.IsIPV6Enabled {
return strings.Join(out, "\n")
@ -1474,12 +1486,12 @@ func buildHTTPSListener(t interface{}, s interface{}) string {
addrV6 = tc.Cfg.BindAddressIpv6
}
out = append(out, httpsListener(addrV6, co, tc)...)
out = append(out, httpsListener(addrV6, co, &tc)...)
return strings.Join(out, "\n")
}
func commonListenOptions(template config.TemplateConfig, hostname string) string {
func commonListenOptions(template *config.TemplateConfig, hostname string) string {
var out []string
if template.Cfg.UseProxyProtocol {
@ -1503,7 +1515,7 @@ func commonListenOptions(template config.TemplateConfig, hostname string) string
return strings.Join(out, " ")
}
func httpListener(addresses []string, co string, tc config.TemplateConfig) []string {
func httpListener(addresses []string, co string, tc *config.TemplateConfig) []string {
out := make([]string, 0)
for _, address := range addresses {
lo := []string{"listen"}
@ -1514,15 +1526,14 @@ func httpListener(addresses []string, co string, tc config.TemplateConfig) []str
lo = append(lo, fmt.Sprintf("%v:%v", address, tc.ListenPorts.HTTP))
}
lo = append(lo, co)
lo = append(lo, ";")
lo = append(lo, co, ";")
out = append(out, strings.Join(lo, " "))
}
return out
}
func httpsListener(addresses []string, co string, tc config.TemplateConfig) []string {
func httpsListener(addresses []string, co string, tc *config.TemplateConfig) []string {
out := make([]string, 0)
for _, address := range addresses {
lo := []string{"listen"}
@ -1545,8 +1556,7 @@ func httpsListener(addresses []string, co string, tc config.TemplateConfig) []st
}
}
lo = append(lo, co)
lo = append(lo, "ssl")
lo = append(lo, co, "ssl")
if tc.Cfg.UseHTTP2 {
lo = append(lo, "http2")
@ -1559,7 +1569,7 @@ func httpsListener(addresses []string, co string, tc config.TemplateConfig) []st
return out
}
func buildOpentracingForLocation(isOTEnabled bool, isOTTrustSet bool, location *ingress.Location) string {
func buildOpentracingForLocation(isOTEnabled, isOTTrustSet bool, location *ingress.Location) string {
isOTEnabledInLoc := location.Opentracing.Enabled
isOTSetInLoc := location.Opentracing.Set
@ -1578,13 +1588,13 @@ func buildOpentracingForLocation(isOTEnabled bool, isOTTrustSet bool, location *
if (!isOTTrustSet && !location.Opentracing.TrustSet) ||
(location.Opentracing.TrustSet && !location.Opentracing.TrustEnabled) {
opc = opc + "\nopentracing_trust_incoming_span off;"
opc += "\nopentracing_trust_incoming_span off;"
}
return opc
}
func buildOpentelemetryForLocation(isOTEnabled bool, isOTTrustSet bool, location *ingress.Location) string {
func buildOpentelemetryForLocation(isOTEnabled, isOTTrustSet bool, location *ingress.Location) string {
isOTEnabledInLoc := location.Opentelemetry.Enabled
isOTSetInLoc := location.Opentelemetry.Set
@ -1602,14 +1612,14 @@ func buildOpentelemetryForLocation(isOTEnabled bool, isOTTrustSet bool, location
}
if location.Opentelemetry.OperationName != "" {
opc = opc + "\nopentelemetry_operation_name " + location.Opentelemetry.OperationName + ";"
opc += "\nopentelemetry_operation_name " + location.Opentelemetry.OperationName + ";"
}
if (!isOTTrustSet && !location.Opentelemetry.TrustSet) ||
(location.Opentelemetry.TrustSet && !location.Opentelemetry.TrustEnabled) {
opc = opc + "\nopentelemetry_trust_incoming_spans off;"
opc += "\nopentelemetry_trust_incoming_spans off;"
} else {
opc = opc + "\nopentelemetry_trust_incoming_spans on;"
opc += "\nopentelemetry_trust_incoming_spans on;"
}
return opc
}
@ -1617,7 +1627,7 @@ func buildOpentelemetryForLocation(isOTEnabled bool, isOTTrustSet bool, location
// shouldLoadOpentracingModule determines whether or not the Opentracing module needs to be loaded.
// First, it checks if `enable-opentracing` is set in the ConfigMap. If it is not, it iterates over all locations to
// check if Opentracing is enabled by the annotation `nginx.ingress.kubernetes.io/enable-opentracing`.
func shouldLoadOpentracingModule(c interface{}, s interface{}) bool {
func shouldLoadOpentracingModule(c, s interface{}) bool {
cfg, ok := c.(config.Configuration)
if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
@ -1647,7 +1657,7 @@ func shouldLoadOpentracingModule(c interface{}, s interface{}) bool {
// shouldLoadOpentelemetryModule determines whether or not the Opentelemetry module needs to be loaded.
// It checks if `enable-opentelemetry` is set in the ConfigMap.
func shouldLoadOpentelemetryModule(c interface{}, s interface{}) bool {
func shouldLoadOpentelemetryModule(c, s interface{}) bool {
cfg, ok := c.(config.Configuration)
if !ok {
klog.Errorf("expected a 'config.Configuration' type but %T was returned", c)
@ -1674,6 +1684,7 @@ func shouldLoadOpentelemetryModule(c interface{}, s interface{}) bool {
return false
}
//nolint:gocritic // Ignore passing cfg by pointer error
func buildModSecurityForLocation(cfg config.Configuration, location *ingress.Location) string {
isMSEnabledInLoc := location.ModSecurity.Enable
isMSEnableSetInLoc := location.ModSecurity.EnableSet
@ -1807,7 +1818,7 @@ func convertGoSliceIntoLuaTable(goSliceInterface interface{}, emptyStringAsNil b
switch kind {
case reflect.String:
if emptyStringAsNil && len(goSlice.Interface().(string)) == 0 {
if emptyStringAsNil && goSlice.Interface().(string) == "" {
return "nil", nil
}
return fmt.Sprintf(`"%v"`, goSlice.Interface()), nil
@ -1840,17 +1851,17 @@ func buildCorsOriginRegex(corsOrigins []string) string {
return "set $http_origin *;\nset $cors 'true';"
}
var originsRegex string = "if ($http_origin ~* ("
originsRegex := "if ($http_origin ~* ("
for i, origin := range corsOrigins {
originTrimmed := strings.TrimSpace(origin)
if len(originTrimmed) > 0 {
builtOrigin := buildOriginRegex(originTrimmed)
originsRegex += builtOrigin
if i != len(corsOrigins)-1 {
originsRegex = originsRegex + "|"
originsRegex += "|"
}
}
}
originsRegex = originsRegex + ")$ ) { set $cors 'true'; }"
originsRegex += ")$ ) { set $cors 'true'; }"
return originsRegex
}

View file

@ -48,9 +48,9 @@ import (
func init() {
// the default value of nginx.TemplatePath assumes the template exists in
// the root filesystem and not in the rootfs directory
path, err := filepath.Abs(filepath.Join("../../../../rootfs/", nginx.TemplatePath))
absPath, err := filepath.Abs(filepath.Join("..", "..", "..", "..", "rootfs", nginx.TemplatePath))
if err == nil {
nginx.TemplatePath = path
nginx.TemplatePath = absPath
}
}
@ -63,7 +63,7 @@ var (
Target string
Location string
ProxyPass string
AutoHttpProxyPass string
AutoHTTPProxyPass string
Sticky bool
XForwardedPrefix string
SecureBackend bool
@ -200,6 +200,12 @@ proxy_pass $scheme://upstream_balancer;`,
}
)
const (
defaultBackend = "upstream-name"
defaultHost = "example.com"
fooAuthHost = "foo.com/auth"
)
func getTestDataDir() (string, error) {
pwd, err := os.Getwd()
if err != nil {
@ -326,9 +332,6 @@ func TestBuildLocation(t *testing.T) {
}
func TestBuildProxyPass(t *testing.T) {
defaultBackend := "upstream-name"
defaultHost := "example.com"
for k, tc := range tmplFuncTestcases {
loc := &ingress.Location{
Path: tc.Path,
@ -339,7 +342,7 @@ func TestBuildProxyPass(t *testing.T) {
}
if tc.SecureBackend {
loc.BackendProtocol = "HTTPS"
loc.BackendProtocol = httpsProtocol
}
backend := &ingress.Backend{
@ -367,9 +370,6 @@ func TestBuildProxyPass(t *testing.T) {
}
func TestBuildProxyPassAutoHttp(t *testing.T) {
defaultBackend := "upstream-name"
defaultHost := "example.com"
for k, tc := range tmplFuncTestcases {
loc := &ingress.Location{
Path: tc.Path,
@ -379,9 +379,9 @@ func TestBuildProxyPassAutoHttp(t *testing.T) {
}
if tc.SecureBackend {
loc.BackendProtocol = "HTTPS"
loc.BackendProtocol = httpsProtocol
} else {
loc.BackendProtocol = "AUTO_HTTP"
loc.BackendProtocol = autoHTTPProtocol
}
backend := &ingress.Backend{
@ -402,7 +402,7 @@ func TestBuildProxyPassAutoHttp(t *testing.T) {
backends := []*ingress.Backend{backend}
pp := buildProxyPass(defaultHost, backends, loc)
if !strings.EqualFold(tc.AutoHttpProxyPass, pp) {
if !strings.EqualFold(tc.AutoHTTPProxyPass, pp) {
t.Errorf("%s: expected \n'%v'\nbut returned \n'%v'", k, tc.ProxyPass, pp)
}
}
@ -417,7 +417,7 @@ func TestBuildAuthLocation(t *testing.T) {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
authURL := "foo.com/auth"
authURL := fooAuthHost
globalAuthURL := "foo.com/global-auth"
loc := &ingress.Location{
@ -428,7 +428,7 @@ func TestBuildAuthLocation(t *testing.T) {
EnableGlobalAuth: true,
}
encodedAuthURL := strings.Replace(base64.URLEncoding.EncodeToString([]byte(loc.Path)), "=", "", -1)
encodedAuthURL := strings.ReplaceAll(base64.URLEncoding.EncodeToString([]byte(loc.Path)), "=", "")
externalAuthPath := fmt.Sprintf("/_external-auth-%v-default", encodedAuthURL)
testCases := []struct {
@ -460,8 +460,7 @@ func TestBuildAuthLocation(t *testing.T) {
}
func TestShouldApplyGlobalAuth(t *testing.T) {
authURL := "foo.com/auth"
authURL := fooAuthHost
globalAuthURL := "foo.com/global-auth"
loc := &ingress.Location{
@ -579,12 +578,12 @@ func TestBuildAuthUpstreamName(t *testing.T) {
loc := &ingress.Location{
ExternalAuth: authreq.Config{
URL: "foo.com/auth",
URL: fooAuthHost,
},
Path: "/cat",
}
encodedAuthURL := strings.Replace(base64.URLEncoding.EncodeToString([]byte(loc.Path)), "=", "", -1)
encodedAuthURL := strings.ReplaceAll(base64.URLEncoding.EncodeToString([]byte(loc.Path)), "=", "")
externalAuthPath := fmt.Sprintf("external-auth-%v-default", encodedAuthURL)
testCases := []struct {
@ -606,7 +605,7 @@ func TestBuildAuthUpstreamName(t *testing.T) {
}
func TestShouldApplyAuthUpstream(t *testing.T) {
authURL := "foo.com/auth"
authURL := fooAuthHost
loc := &ingress.Location{
ExternalAuth: authreq.Config{
@ -702,7 +701,10 @@ func TestChangeHostPort(t *testing.T) {
}
func TestTemplateWithData(t *testing.T) {
pwd, _ := os.Getwd()
pwd, err := os.Getwd()
if err != nil {
t.Errorf("unexpected error: %v", err)
}
f, err := os.Open(path.Join(pwd, "../../../../test/data/config.json"))
if err != nil {
t.Errorf("unexpected error reading json file: %v", err)
@ -727,7 +729,7 @@ func TestTemplateWithData(t *testing.T) {
dat.Cfg.DefaultSSLCertificate = &ingress.SSLCert{}
rt, err := ngxTpl.Write(dat)
rt, err := ngxTpl.Write(&dat)
if err != nil {
t.Errorf("invalid NGINX template: %v", err)
}
@ -746,7 +748,10 @@ func TestTemplateWithData(t *testing.T) {
}
func BenchmarkTemplateWithData(b *testing.B) {
pwd, _ := os.Getwd()
pwd, err := os.Getwd()
if err != nil {
b.Errorf("unexpected error: %v", err)
}
f, err := os.Open(path.Join(pwd, "../../../../test/data/config.json"))
if err != nil {
b.Errorf("unexpected error reading json file: %v", err)
@ -767,7 +772,7 @@ func BenchmarkTemplateWithData(b *testing.B) {
}
for i := 0; i < b.N; i++ {
if _, err := ngxTpl.Write(dat); err != nil {
if _, err := ngxTpl.Write(&dat); err != nil {
b.Errorf("unexpected error writing template: %v", err)
}
}
@ -1066,9 +1071,6 @@ func TestBuildUpstreamName(t *testing.T) {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
defaultBackend := "upstream-name"
defaultHost := "example.com"
for k, tc := range tmplFuncTestcases {
loc := &ingress.Location{
Path: tc.Path,
@ -1079,7 +1081,7 @@ func TestBuildUpstreamName(t *testing.T) {
}
if tc.SecureBackend {
loc.BackendProtocol = "HTTPS"
loc.BackendProtocol = httpsProtocol
}
backend := &ingress.Backend{
@ -1134,13 +1136,13 @@ func TestEscapeLiteralDollar(t *testing.T) {
func TestOpentracingPropagateContext(t *testing.T) {
tests := map[*ingress.Location]string{
{BackendProtocol: "HTTP"}: "opentracing_propagate_context;",
{BackendProtocol: "HTTPS"}: "opentracing_propagate_context;",
{BackendProtocol: "AUTO_HTTP"}: "opentracing_propagate_context;",
{BackendProtocol: "GRPC"}: "opentracing_grpc_propagate_context;",
{BackendProtocol: "GRPCS"}: "opentracing_grpc_propagate_context;",
{BackendProtocol: "FCGI"}: "opentracing_propagate_context;",
nil: "",
{BackendProtocol: httpProtocol}: "opentracing_propagate_context;",
{BackendProtocol: httpsProtocol}: "opentracing_propagate_context;",
{BackendProtocol: autoHTTPProtocol}: "opentracing_propagate_context;",
{BackendProtocol: grpcProtocol}: "opentracing_grpc_propagate_context;",
{BackendProtocol: grpcsProtocol}: "opentracing_grpc_propagate_context;",
{BackendProtocol: fcgiProtocol}: "opentracing_propagate_context;",
nil: "",
}
for loc, expectedDirective := range tests {
@ -1153,13 +1155,13 @@ func TestOpentracingPropagateContext(t *testing.T) {
func TestOpentelemetryPropagateContext(t *testing.T) {
tests := map[*ingress.Location]string{
{BackendProtocol: "HTTP"}: "opentelemetry_propagate;",
{BackendProtocol: "HTTPS"}: "opentelemetry_propagate;",
{BackendProtocol: "AUTO_HTTP"}: "opentelemetry_propagate;",
{BackendProtocol: "GRPC"}: "opentelemetry_propagate;",
{BackendProtocol: "GRPCS"}: "opentelemetry_propagate;",
{BackendProtocol: "FCGI"}: "opentelemetry_propagate;",
nil: "",
{BackendProtocol: httpProtocol}: "opentelemetry_propagate;",
{BackendProtocol: httpsProtocol}: "opentelemetry_propagate;",
{BackendProtocol: autoHTTPProtocol}: "opentelemetry_propagate;",
{BackendProtocol: grpcProtocol}: "opentelemetry_propagate;",
{BackendProtocol: grpcsProtocol}: "opentelemetry_propagate;",
{BackendProtocol: fcgiProtocol}: "opentelemetry_propagate;",
nil: "",
}
for loc, expectedDirective := range tests {
@ -1171,7 +1173,6 @@ func TestOpentelemetryPropagateContext(t *testing.T) {
}
func TestGetIngressInformation(t *testing.T) {
testcases := map[string]struct {
Ingress interface{}
Host string
@ -1625,7 +1626,7 @@ func TestProxySetHeader(t *testing.T) {
{
name: "gRPC backend",
loc: &ingress.Location{
BackendProtocol: "GRPC",
BackendProtocol: grpcProtocol,
},
expected: "grpc_set_header",
},
@ -1716,7 +1717,6 @@ func TestBuildOpenTracing(t *testing.T) {
if expected != actual {
t.Errorf("Expected '%v' but returned '%v'", expected, actual)
}
}
func TestBuildOpenTelemetry(t *testing.T) {
@ -1777,6 +1777,7 @@ func TestEnforceRegexModifier(t *testing.T) {
}
}
//nolint:dupl // Ignore dupl errors for similar test case
func TestShouldLoadModSecurityModule(t *testing.T) {
// ### Invalid argument type tests ###
// The first tests should return false.
@ -1877,6 +1878,7 @@ opentracing_trust_incoming_span off;`
}
}
//nolint:dupl // Ignore dupl errors for similar test case
func TestShouldLoadOpentracingModule(t *testing.T) {
// ### Invalid argument type tests ###
// The first tests should return false.
@ -1978,6 +1980,7 @@ opentelemetry_trust_incoming_spans off;`
}
}
//nolint:dupl // Ignore dupl errors for similar test case
func TestShouldLoadOpentelemetryModule(t *testing.T) {
// ### Invalid argument type tests ###
// The first tests should return false.
@ -2104,7 +2107,6 @@ func TestModSecurityForLocation(t *testing.T) {
}
func TestBuildServerName(t *testing.T) {
testCases := []struct {
title string
hostname string

View file

@ -135,11 +135,13 @@ func (nc NginxCommand) ExecCommand(args ...string) *exec.Cmd {
cmdArgs = append(cmdArgs, "-c", cfgPath)
cmdArgs = append(cmdArgs, args...)
//nolint:gosec // Ignore G204 error
return exec.Command(nc.Binary, cmdArgs...)
}
// Test checks if config file is a syntax valid nginx configuration
func (nc NginxCommand) Test(cfg string) ([]byte, error) {
//nolint:gosec // Ignore G204 error
return exec.Command(nc.Binary, "-c", cfg, "-t").CombinedOutput()
}