Merge pull request #926 from aledbf/configure-errors
[nginx-ingress-controller] Custom errors should be optional
This commit is contained in:
commit
a38fcda255
4 changed files with 63 additions and 85 deletions
|
@ -123,18 +123,14 @@ http {
|
||||||
ssl_dhparam {{ .sslDHParam }};
|
ssl_dhparam {{ .sslDHParam }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{- if .customErrors }}
|
||||||
# Custom error pages
|
# Custom error pages
|
||||||
proxy_intercept_errors on;
|
proxy_intercept_errors on;
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
error_page 403 = @custom_403;
|
{{- range $errCode := $cfg.customHttpErrors }}
|
||||||
error_page 404 = @custom_404;
|
error_page {{ $errCode }} = @custom_{{ $errCode }};
|
||||||
error_page 405 = @custom_405;
|
{{ end }}
|
||||||
error_page 408 = @custom_408;
|
|
||||||
error_page 413 = @custom_413;
|
|
||||||
error_page 501 = @custom_501;
|
|
||||||
error_page 502 = @custom_502;
|
|
||||||
error_page 503 = @custom_503;
|
|
||||||
error_page 504 = @custom_504;
|
|
||||||
|
|
||||||
# In case of errors try the next upstream server before returning an error
|
# In case of errors try the next upstream server before returning an error
|
||||||
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504 {{ if $cfg.retryNonIdempotent }}non_idempotent{{ end }};
|
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504 {{ if $cfg.retryNonIdempotent }}non_idempotent{{ end }};
|
||||||
|
@ -153,6 +149,7 @@ http {
|
||||||
|
|
||||||
{{ range $server := .servers }}
|
{{ range $server := .servers }}
|
||||||
server {
|
server {
|
||||||
|
server_name {{ $server.Name }};
|
||||||
listen 80{{ if $cfg.useProxyProtocol }} proxy_protocol{{ end }};
|
listen 80{{ if $cfg.useProxyProtocol }} proxy_protocol{{ end }};
|
||||||
{{ if $server.SSL }}listen 443 {{ if $cfg.useProxyProtocol }}proxy_protocol{{ end }} ssl {{ if $cfg.useHttp2 }}http2{{ end }};
|
{{ if $server.SSL }}listen 443 {{ if $cfg.useProxyProtocol }}proxy_protocol{{ end }} ssl {{ if $cfg.useHttp2 }}http2{{ end }};
|
||||||
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
|
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
|
||||||
|
@ -160,8 +157,6 @@ http {
|
||||||
ssl_certificate {{ $server.SSLCertificate }};
|
ssl_certificate {{ $server.SSLCertificate }};
|
||||||
ssl_certificate_key {{ $server.SSLCertificateKey }};{{ end }}
|
ssl_certificate_key {{ $server.SSLCertificateKey }};{{ end }}
|
||||||
|
|
||||||
server_name {{ $server.Name }};
|
|
||||||
|
|
||||||
{{ if (and $server.SSL $cfg.hsts) }}
|
{{ if (and $server.SSL $cfg.hsts) }}
|
||||||
if ($scheme = http) {
|
if ($scheme = http) {
|
||||||
return 301 https://$host$request_uri;
|
return 301 https://$host$request_uri;
|
||||||
|
@ -236,7 +231,7 @@ http {
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://upstream-default-backend;
|
proxy_pass http://upstream-default-backend;
|
||||||
}
|
}
|
||||||
{{ template "CUSTOM_ERRORS" $cfg }}
|
{{- template "CUSTOM_ERRORS" $cfg }}
|
||||||
}
|
}
|
||||||
|
|
||||||
# default server for services without endpoints
|
# default server for services without endpoints
|
||||||
|
@ -244,9 +239,13 @@ http {
|
||||||
listen 8181;
|
listen 8181;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
{{ if .customErrors }}
|
||||||
content_by_lua_block {
|
content_by_lua_block {
|
||||||
openURL(503)
|
openURL(503)
|
||||||
}
|
}
|
||||||
|
{{ else }}
|
||||||
|
return 503;
|
||||||
|
{{ end }}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,59 +284,12 @@ stream {
|
||||||
|
|
||||||
{{/* definition of templates to avoid repetitions */}}
|
{{/* definition of templates to avoid repetitions */}}
|
||||||
{{ define "CUSTOM_ERRORS" }}
|
{{ define "CUSTOM_ERRORS" }}
|
||||||
location @custom_403 {
|
{{ range $errCode := .customHttpErrors }}
|
||||||
|
location @custom_{{ $errCode }} {
|
||||||
internal;
|
internal;
|
||||||
content_by_lua_block {
|
content_by_lua_block {
|
||||||
openURL(403)
|
openURL({{ $errCode }})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{{ end }}
|
||||||
location @custom_404 {
|
|
||||||
internal;
|
|
||||||
content_by_lua_block {
|
|
||||||
openURL(404)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
location @custom_405 {
|
|
||||||
internal;
|
|
||||||
content_by_lua_block {
|
|
||||||
openURL(405)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
location @custom_408 {
|
|
||||||
internal;
|
|
||||||
content_by_lua_block {
|
|
||||||
openURL(408)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
location @custom_413 {
|
|
||||||
internal;
|
|
||||||
content_by_lua_block {
|
|
||||||
openURL(413)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
location @custom_502 {
|
|
||||||
internal;
|
|
||||||
content_by_lua_block {
|
|
||||||
openURL(502)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
location @custom_503 {
|
|
||||||
internal;
|
|
||||||
content_by_lua_block {
|
|
||||||
openURL(503)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
location @custom_504 {
|
|
||||||
internal;
|
|
||||||
content_by_lua_block {
|
|
||||||
openURL(504)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
@ -124,6 +124,12 @@ type nginxConfiguration struct {
|
||||||
// accessed using HTTPS.
|
// accessed using HTTPS.
|
||||||
HSTSMaxAge string `structs:"hsts-max-age,omitempty"`
|
HSTSMaxAge string `structs:"hsts-max-age,omitempty"`
|
||||||
|
|
||||||
|
// enables which HTTP codes should be passed for processing with the error_page directive
|
||||||
|
// http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
|
||||||
|
// http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page
|
||||||
|
// By default this is disabled
|
||||||
|
CustomHTTPErrors []int
|
||||||
|
|
||||||
// Time during which a keep-alive client connection will stay open on the server side.
|
// Time during which a keep-alive client connection will stay open on the server side.
|
||||||
// The zero value disables keep-alive client connections
|
// The zero value disables keep-alive client connections
|
||||||
// http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout
|
// http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout
|
||||||
|
@ -276,6 +282,7 @@ func newDefaultNginxCfg() nginxConfiguration {
|
||||||
WorkerProcesses: strconv.Itoa(runtime.NumCPU()),
|
WorkerProcesses: strconv.Itoa(runtime.NumCPU()),
|
||||||
VtsStatusZoneSize: "10m",
|
VtsStatusZoneSize: "10m",
|
||||||
UseHTTP2: true,
|
UseHTTP2: true,
|
||||||
|
CustomHTTPErrors: []int{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if glog.V(5) {
|
if glog.V(5) {
|
||||||
|
|
|
@ -56,15 +56,9 @@ func (ngx *Manager) writeCfg(cfg nginxConfiguration, ingressCfg IngressConfig) (
|
||||||
conf["udpUpstreams"] = ingressCfg.UDPUpstreams
|
conf["udpUpstreams"] = ingressCfg.UDPUpstreams
|
||||||
conf["defResolver"] = ngx.defResolver
|
conf["defResolver"] = ngx.defResolver
|
||||||
conf["sslDHParam"] = ngx.sslDHParam
|
conf["sslDHParam"] = ngx.sslDHParam
|
||||||
|
conf["customErrors"] = len(cfg.CustomHTTPErrors) > 0
|
||||||
conf["cfg"] = fixKeyNames(structs.Map(cfg))
|
conf["cfg"] = fixKeyNames(structs.Map(cfg))
|
||||||
|
|
||||||
buffer := new(bytes.Buffer)
|
|
||||||
err := ngx.template.Execute(buffer, conf)
|
|
||||||
if err != nil {
|
|
||||||
glog.Infof("NGINX error: %v", err)
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if glog.V(3) {
|
if glog.V(3) {
|
||||||
b, err := json.Marshal(conf)
|
b, err := json.Marshal(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -73,6 +67,13 @@ func (ngx *Manager) writeCfg(cfg nginxConfiguration, ingressCfg IngressConfig) (
|
||||||
glog.Infof("NGINX configuration: %v", string(b))
|
glog.Infof("NGINX configuration: %v", string(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer := new(bytes.Buffer)
|
||||||
|
err := ngx.template.Execute(buffer, conf)
|
||||||
|
if err != nil {
|
||||||
|
glog.Infof("NGINX error: %v", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
changed, err := ngx.needsReload(buffer)
|
changed, err := ngx.needsReload(buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
@ -30,6 +31,10 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
customHTTPErrors = "custom-http-errors"
|
||||||
|
)
|
||||||
|
|
||||||
// getDNSServers returns the list of nameservers located in the file /etc/resolv.conf
|
// getDNSServers returns the list of nameservers located in the file /etc/resolv.conf
|
||||||
func getDNSServers() []string {
|
func getDNSServers() []string {
|
||||||
file, err := ioutil.ReadFile("/etc/resolv.conf")
|
file, err := ioutil.ReadFile("/etc/resolv.conf")
|
||||||
|
@ -91,6 +96,19 @@ func (ngx *Manager) ReadConfig(config *api.ConfigMap) nginxConfiguration {
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
cErrors := make([]int, 0)
|
||||||
|
if val, ok := config.Data[customHTTPErrors]; ok {
|
||||||
|
delete(config.Data, customHTTPErrors)
|
||||||
|
for _, i := range strings.Split(val, ",") {
|
||||||
|
j, err := strconv.Atoi(i)
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("%v is not a valid http code", i)
|
||||||
|
} else {
|
||||||
|
cErrors = append(cErrors, j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = decoder.Decode(config.Data)
|
err = decoder.Decode(config.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Infof("%v", err)
|
glog.Infof("%v", err)
|
||||||
|
@ -115,9 +133,23 @@ func (ngx *Manager) ReadConfig(config *api.ConfigMap) nginxConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfgDefault.CustomHTTPErrors = ngx.filterErrors(cErrors)
|
||||||
return cfgDefault
|
return cfgDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ngx *Manager) filterErrors(errCodes []int) []int {
|
||||||
|
fa := make([]int, 0)
|
||||||
|
for _, errCode := range errCodes {
|
||||||
|
if errCode > 299 && errCode < 600 {
|
||||||
|
fa = append(fa, errCode)
|
||||||
|
} else {
|
||||||
|
glog.Warningf("error code %v is not valid for custom error pages", errCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fa
|
||||||
|
}
|
||||||
|
|
||||||
func (ngx *Manager) needsReload(data *bytes.Buffer) (bool, error) {
|
func (ngx *Manager) needsReload(data *bytes.Buffer) (bool, error) {
|
||||||
filename := ngx.ConfigFile
|
filename := ngx.ConfigFile
|
||||||
in, err := os.Open(filename)
|
in, err := os.Open(filename)
|
||||||
|
@ -179,17 +211,3 @@ func diff(b1, b2 []byte) (data []byte, err error) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func toMap(iface interface{}) (map[string]interface{}, bool) {
|
|
||||||
value := reflect.ValueOf(iface)
|
|
||||||
if value.Kind() == reflect.Map {
|
|
||||||
m := map[string]interface{}{}
|
|
||||||
for _, k := range value.MapKeys() {
|
|
||||||
m[k.String()] = value.MapIndex(k).Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{}, false
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue