Skip to content
This repository has been archived by the owner on Apr 17, 2019. It is now read-only.

[nginx-ingress-controller] Avoid replacing nginx.conf file with invalid content #1772

Merged
merged 1 commit into from
Sep 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion ingress/controllers/nginx/nginx/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package nginx

import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
Expand Down Expand Up @@ -63,7 +64,7 @@ func (ngx *Manager) CheckAndReload(cfg config.Configuration, ingressCfg ingress.
ngx.reloadLock.Lock()
defer ngx.reloadLock.Unlock()

newCfg, err := ngx.template.Write(cfg, ingressCfg)
newCfg, err := ngx.template.Write(cfg, ingressCfg, ngx.testTemplate)
if err != nil {
return fmt.Errorf("failed to write new nginx configuration. Avoiding reload: %v", err)
}
Expand Down Expand Up @@ -118,3 +119,19 @@ func (ngx Manager) Check(_ *http.Request) error {

return nil
}

// testTemplate checks if the NGINX configuration inside the byte array is valid
// running the command "nginx -t" using a temporal file.
func (ngx Manager) testTemplate(cfg []byte) error {
tmpfile, err := ioutil.TempFile("", "nginx-cfg")
if err != nil {
return err
}
defer tmpfile.Close()
defer os.Remove(tmpfile.Name())
ioutil.WriteFile(tmpfile.Name(), cfg, 0644)
if err := ngx.shellOut(fmt.Sprintf("nginx -t -c %v", tmpfile.Name())); err != nil {
return fmt.Errorf("invalid nginx configuration: %v", err)
}
return nil
}
26 changes: 20 additions & 6 deletions ingress/controllers/nginx/nginx/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ func (t *Template) Close() {

// Write populates a buffer using a template with NGINX configuration
// and the servers and upstreams created by Ingress rules
func (t *Template) Write(cfg config.Configuration, ingressCfg ingress.Configuration) ([]byte, error) {
func (t *Template) Write(
cfg config.Configuration,
ingressCfg ingress.Configuration,
isValidTemplate func([]byte) error) ([]byte, error) {
var longestName int
var serverNames int
for _, srv := range ingressCfg.Servers {
Expand All @@ -109,12 +112,14 @@ func (t *Template) Write(cfg config.Configuration, ingressCfg ingress.Configurat
// https://trac.nginx.org/nginx/ticket/631
nameHashBucketSize := nextPowerOf2(longestName)
if nameHashBucketSize > cfg.ServerNameHashBucketSize {
glog.V(3).Infof("adjusting ServerNameHashBucketSize variable from %v to %v", cfg.ServerNameHashBucketSize, nameHashBucketSize)
glog.V(3).Infof("adjusting ServerNameHashBucketSize variable from %v to %v",
cfg.ServerNameHashBucketSize, nameHashBucketSize)
cfg.ServerNameHashBucketSize = nameHashBucketSize
}
serverNameHashMaxSize := nextPowerOf2(serverNames)
if serverNameHashMaxSize > cfg.ServerNameHashMaxSize {
glog.V(3).Infof("adjusting ServerNameHashMaxSize variable from %v to %v", cfg.ServerNameHashMaxSize, serverNameHashMaxSize)
glog.V(3).Infof("adjusting ServerNameHashMaxSize variable from %v to %v",
cfg.ServerNameHashMaxSize, serverNameHashMaxSize)
cfg.ServerNameHashMaxSize = serverNameHashMaxSize
}

Expand All @@ -141,9 +146,15 @@ func (t *Template) Write(cfg config.Configuration, ingressCfg ingress.Configurat
err := t.tmpl.Execute(buffer, conf)
if err != nil {
glog.V(3).Infof("%v", string(buffer.Bytes()))
return nil, err
}

err = isValidTemplate(buffer.Bytes())
if err != nil {
return nil, err
}

return buffer.Bytes(), err
return buffer.Bytes(), nil
}

func fixKeyNames(data map[string]interface{}) map[string]interface{} {
Expand Down Expand Up @@ -258,13 +269,16 @@ func buildRateLimitZones(input interface{}) []string {

if loc.RateLimit.Connections.Limit > 0 {
zone := fmt.Sprintf("limit_conn_zone $binary_remote_addr zone=%v:%vm;",
loc.RateLimit.Connections.Name, loc.RateLimit.Connections.SharedSize)
loc.RateLimit.Connections.Name,
loc.RateLimit.Connections.SharedSize)
zones = append(zones, zone)
}

if loc.RateLimit.RPS.Limit > 0 {
zone := fmt.Sprintf("limit_conn_zone $binary_remote_addr zone=%v:%vm rate=%vr/s;",
loc.RateLimit.Connections.Name, loc.RateLimit.Connections.SharedSize, loc.RateLimit.Connections.Limit)
loc.RateLimit.Connections.Name,
loc.RateLimit.Connections.SharedSize,
loc.RateLimit.Connections.Limit)
zones = append(zones, zone)
}
}
Expand Down