Skip to content

Commit

Permalink
Refactoring of nginx configuration deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
aledbf committed Jan 2, 2017
1 parent 5cdb8fe commit c0b5be6
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 128 deletions.
62 changes: 31 additions & 31 deletions controllers/nginx/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,145 +76,145 @@ var (

// Configuration represents the content of nginx.conf file
type Configuration struct {
defaults.Backend
defaults.Backend `json:",squash"`

// http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size
// Sets the maximum allowed size of the client request body
BodySize string `structs:"body-size,omitempty"`
BodySize string `json:"body-size,omitempty"`

// EnableDynamicTLSRecords enables dynamic TLS record sizes
// https://blog.cloudflare.com/optimizing-tls-over-tcp-to-reduce-latency
// By default this is enabled
EnableDynamicTLSRecords bool `structs:"enable-dynamic-tls-records"`
EnableDynamicTLSRecords bool `json:"enable-dynamic-tls-records"`

// EnableSPDY enables spdy and use ALPN and NPN to advertise the availability of the two protocols
// https://blog.cloudflare.com/open-sourcing-our-nginx-http-2-spdy-code
// By default this is enabled
EnableSPDY bool `structs:"enable-spdy"`
EnableSPDY bool `json:"enable-spdy"`

// EnableStickySessions enabled sticky sessions using cookies
// https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng
// By default this is disabled
EnableStickySessions bool `structs:"enable-sticky-sessions,omitempty"`
EnableStickySessions bool `json:"enable-sticky-sessions,omitempty"`

// EnableVtsStatus allows the replacement of the default status page with a third party module named
// nginx-module-vts - https://github.com/vozlt/nginx-module-vts
// By default this is disabled
EnableVtsStatus bool `structs:"enable-vts-status,omitempty"`
EnableVtsStatus bool `json:"enable-vts-status,omitempty"`

VtsStatusZoneSize string `structs:"vts-status-zone-size,omitempty"`
VtsStatusZoneSize string `json:"vts-status-zone-size,omitempty"`

// RetryNonIdempotent since 1.9.13 NGINX will not retry non-idempotent requests (POST, LOCK, PATCH)
// in case of an error. The previous behavior can be restored using the value true
RetryNonIdempotent bool `structs:"retry-non-idempotent"`
RetryNonIdempotent bool `json:"retry-non-idempotent"`

// http://nginx.org/en/docs/ngx_core_module.html#error_log
// Configures logging level [debug | info | notice | warn | error | crit | alert | emerg]
// Log levels above are listed in the order of increasing severity
ErrorLogLevel string `structs:"error-log-level,omitempty"`
ErrorLogLevel string `json:"error-log-level,omitempty"`

// Enables or disables the header HSTS in servers running SSL
HSTS bool `structs:"hsts,omitempty"`
HSTS bool `json:"hsts,omitempty"`

// Enables or disables the use of HSTS in all the subdomains of the servername
// Default: true
HSTSIncludeSubdomains bool `structs:"hsts-include-subdomains,omitempty"`
HSTSIncludeSubdomains bool `json:"hsts-include-subdomains,omitempty"`

// HTTP Strict Transport Security (often abbreviated as HSTS) is a security feature (HTTP header)
// that tell browsers that it should only be communicated with using HTTPS, instead of using HTTP.
// https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security
// max-age is the time, in seconds, that the browser should remember that this site is only to be
// accessed using HTTPS.
HSTSMaxAge string `structs:"hsts-max-age,omitempty"`
HSTSMaxAge string `json:"hsts-max-age,omitempty"`

// Time during which a keep-alive client connection will stay open on the server side.
// The zero value disables keep-alive client connections
// http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout
KeepAlive int `structs:"keep-alive,omitempty"`
KeepAlive int `json:"keep-alive,omitempty"`

// Maximum number of simultaneous connections that can be opened by each worker process
// http://nginx.org/en/docs/ngx_core_module.html#worker_connections
MaxWorkerConnections int `structs:"max-worker-connections,omitempty"`
MaxWorkerConnections int `json:"max-worker-connections,omitempty"`

// Sets the bucket size for the map variables hash tables.
// Default value depends on the processor’s cache line size.
// http://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_bucket_size
MapHashBucketSize int `structs:"map-hash-bucket-size,omitempty"`
MapHashBucketSize int `json:"map-hash-bucket-size,omitempty"`

// If UseProxyProtocol is enabled ProxyRealIPCIDR defines the default the IP/network address
// of your external load balancer
ProxyRealIPCIDR string `structs:"proxy-real-ip-cidr,omitempty"`
ProxyRealIPCIDR string `json:"proxy-real-ip-cidr,omitempty"`

// Maximum size of the server names hash tables used in server names, map directive’s values,
// MIME types, names of request header strings, etcd.
// http://nginx.org/en/docs/hash.html
// http://nginx.org/en/docs/http/ngx_http_core_module.html#server_names_hash_max_size
ServerNameHashMaxSize int `structs:"server-name-hash-max-size,omitempty"`
ServerNameHashMaxSize int `json:"server-name-hash-max-size,omitempty"`

// Size of the bucket for the server names hash tables
// http://nginx.org/en/docs/hash.html
// http://nginx.org/en/docs/http/ngx_http_core_module.html#server_names_hash_bucket_size
ServerNameHashBucketSize int `structs:"server-name-hash-bucket-size,omitempty"`
ServerNameHashBucketSize int `json:"server-name-hash-bucket-size,omitempty"`

// Enabled ciphers list to enabled. The ciphers are specified in the format understood by
// the OpenSSL library
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers
SSLCiphers string `structs:"ssl-ciphers,omitempty"`
SSLCiphers string `json:"ssl-ciphers,omitempty"`

// Base64 string that contains Diffie-Hellman key to help with "Perfect Forward Secrecy"
// https://www.openssl.org/docs/manmaster/apps/dhparam.html
// https://wiki.mozilla.org/Security/Server_Side_TLS#DHE_handshake_and_dhparam
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam
SSLDHParam string `structs:"ssl-dh-param,omitempty"`
SSLDHParam string `json:"ssl-dh-param,omitempty"`

// SSL enabled protocols to use
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols
SSLProtocols string `structs:"ssl-protocols,omitempty"`
SSLProtocols string `json:"ssl-protocols,omitempty"`

// Enables or disables the use of shared SSL cache among worker processes.
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache
SSLSessionCache bool `structs:"ssl-session-cache,omitempty"`
SSLSessionCache bool `json:"ssl-session-cache,omitempty"`

// Size of the SSL shared cache between all worker processes.
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache
SSLSessionCacheSize string `structs:"ssl-session-cache-size,omitempty"`
SSLSessionCacheSize string `json:"ssl-session-cache-size,omitempty"`

// Enables or disables session resumption through TLS session tickets.
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets
SSLSessionTickets bool `structs:"ssl-session-tickets,omitempty"`
SSLSessionTickets bool `json:"ssl-session-tickets,omitempty"`

// Time during which a client may reuse the session parameters stored in a cache.
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_timeout
SSLSessionTimeout string `structs:"ssl-session-timeout,omitempty"`
SSLSessionTimeout string `json:"ssl-session-timeout,omitempty"`

// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_buffer_size
// Sets the size of the buffer used for sending data.
// 4k helps NGINX to improve TLS Time To First Byte (TTTFB)
// https://www.igvita.com/2013/12/16/optimizing-nginx-tls-time-to-first-byte/
SSLBufferSize string `structs:"ssl-buffer-size,omitempty"`
SSLBufferSize string `json:"ssl-buffer-size,omitempty"`

// Enables or disables the use of the PROXY protocol to receive client connection
// (real IP address) information passed through proxy servers and load balancers
// such as HAproxy and Amazon Elastic Load Balancer (ELB).
// https://www.nginx.com/resources/admin-guide/proxy-protocol/
UseProxyProtocol bool `structs:"use-proxy-protocol,omitempty"`
UseProxyProtocol bool `json:"use-proxy-protocol,omitempty"`

// Enables or disables the use of the nginx module that compresses responses using the "gzip" method
// http://nginx.org/en/docs/http/ngx_http_gzip_module.html
UseGzip bool `structs:"use-gzip,omitempty"`
UseGzip bool `json:"use-gzip,omitempty"`

// Enables or disables the HTTP/2 support in secure connections
// http://nginx.org/en/docs/http/ngx_http_v2_module.html
// Default: true
UseHTTP2 bool `structs:"use-http2,omitempty"`
UseHTTP2 bool `json:"use-http2,omitempty"`

// MIME types in addition to "text/html" to compress. The special value “*” matches any MIME type.
// Responses with the “text/html” type are always compressed if UseGzip is enabled
GzipTypes string `structs:"gzip-types,omitempty"`
GzipTypes string `json:"gzip-types,omitempty"`

// Defines the number of worker processes. By default auto means number of available CPU cores
// http://nginx.org/en/docs/ngx_core_module.html#worker_processes
WorkerProcesses int `structs:"worker-processes,omitempty"`
WorkerProcesses int `json:"worker-processes,omitempty"`
}

// NewDefault returns the default nginx configuration
Expand Down
54 changes: 13 additions & 41 deletions controllers/nginx/pkg/template/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,11 @@ import (
"strings"

"github.com/golang/glog"
"github.com/imdario/mergo"

"github.com/fatih/structs"
"github.com/mitchellh/mapstructure"
go_camelcase "github.com/segmentio/go-camelcase"

"k8s.io/kubernetes/pkg/api"

"k8s.io/ingress/controllers/nginx/pkg/config"
"k8s.io/ingress/core/pkg/ingress/defaults"
"k8s.io/ingress/core/pkg/net/dns"
)

const (
Expand All @@ -40,11 +34,6 @@ const (
whitelistSourceRange = "whitelist-source-range"
)

// StandarizeKeyNames ...
func StandarizeKeyNames(data interface{}) map[string]interface{} {
return fixKeyNames(structs.Map(data))
}

// ReadConfig obtains the configuration defined by the user merged with the defaults.
func ReadConfig(conf *api.ConfigMap) config.Configuration {
if len(conf.Data) == 0 {
Expand Down Expand Up @@ -75,35 +64,26 @@ func ReadConfig(conf *api.ConfigMap) config.Configuration {
whitelist = append(whitelist, strings.Split(val, ",")...)
}

to := config.Configuration{}
to.Backend = defaults.Backend{
CustomHTTPErrors: filterErrors(errors),
SkipAccessLogURLs: skipUrls,
WhitelistSourceRange: whitelist,
}
def := config.NewDefault()
if err := mergo.Merge(&to, def); err != nil {
glog.Warningf("unexpected error merging defaults: %v", err)
}
to := config.NewDefault()
to.CustomHTTPErrors = filterErrors(errors)
to.SkipAccessLogURLs = skipUrls
to.WhitelistSourceRange = whitelist

metadata := &mapstructure.Metadata{}
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
TagName: "structs",
Result: &to,
config := &mapstructure.DecoderConfig{
Metadata: nil,
WeaklyTypedInput: true,
Metadata: metadata,
})
Result: &to,
TagName: "json",
}

err = decoder.Decode(conf.Data)
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
glog.Infof("%v", err)
glog.Warningf("unexpected error merging defaults: %v", err)
}

nss, err := dns.GetSystemNameServers()
err = decoder.Decode(conf.Data)
if err != nil {
glog.Infof("unexpected error reading /etc/resolv.conf file: %v", err)
glog.Warningf("unexpected error merging defaults: %v", err)
}
to.Resolver = nss

return to
}
Expand All @@ -120,11 +100,3 @@ func filterErrors(codes []int) []int {

return fa
}

func fixKeyNames(data map[string]interface{}) map[string]interface{} {
fixed := make(map[string]interface{})
for k, v := range data {
fixed[go_camelcase.Camelcase(k)] = v
}
return fixed
}
69 changes: 23 additions & 46 deletions controllers/nginx/pkg/template/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,67 +17,44 @@ limitations under the License.
package template

import (
"reflect"
"testing"

"k8s.io/ingress/controllers/nginx/pkg/config"
"k8s.io/kubernetes/pkg/api"
)

func TestStandarizeKeyNames(t *testing.T) {
}

func TestFilterErrors(t *testing.T) {
e := filterErrors([]int{200, 300, 345, 500, 555, 999})
if len(e) != 4 {
t.Errorf("expected 4 elements but %v returned", len(e))
}
}

func TestFixKeyNames(t *testing.T) {
d := map[string]interface{}{
"one": "one",
"one-example": "oneExample",
"aMore-complex_example": "aMoreComplexExample",
"a": "a",
}

fixed := fixKeyNames(d)
for k, v := range fixed {
if k != v {
t.Errorf("expected %v but retuned %v", v, k)
}
}
}

type testStruct struct {
ProxyReadTimeout int `structs:"proxy-read-timeout,omitempty"`
ProxySendTimeout int `structs:"proxy-send-timeout,omitempty"`
CustomHTTPErrors []int `structs:"custom-http-errors"`
SkipAccessLogURLs []string `structs:"skip-access-log-urls,-"`
NoTag string
}

var decodedData = &testStruct{
1,
2,
[]int{300, 400},
[]string{"/log"},
"",
}

func TestMergeConfigMapToStruct(t *testing.T) {
/*conf := &api.ConfigMap{
conf := &api.ConfigMap{
Data: map[string]string{
"custom-http-errors": "300,400",
"proxy-read-timeout": "1",
"proxy-send-timeout": "2",
"skip-access-log-urls": "/log",
"custom-http-errors": "300,400",
"proxy-read-timeout": "1",
"proxy-send-timeout": "2",
"skip-access-log-urls": "/log,/demo,/test",
"use-proxy-protocol": "true",
"use-gzip": "true",
"enable-dynamic-tls-records": "false",
"gzip-types": "text/html",
},
}*/
}
def := config.NewDefault()
def.CustomHTTPErrors = []int{300, 400}
def.SkipAccessLogURLs = []string{"/log"}
//to := ReadConfig(conf)
//if !reflect.DeepEqual(def, to) {
// t.Errorf("expected %v but retuned %v", def, to)
//}
def.SkipAccessLogURLs = []string{"/log", "/demo", "/test"}
def.ProxyReadTimeout = 1
def.ProxySendTimeout = 2
def.EnableDynamicTLSRecords = false
def.UseProxyProtocol = true
def.GzipTypes = "text/html"

to := ReadConfig(conf)
if !reflect.DeepEqual(def, to) {
t.Errorf("expected %v but retuned %v", def, to)
}
}
Loading

0 comments on commit c0b5be6

Please sign in to comment.