Avoid replacing nginx.conf file if the new configuration is invalid

This commit is contained in:
Manuel de Brito Fontes 2016-09-22 14:08:35 -03:00
parent e74b8039a5
commit db3388e777
2 changed files with 38 additions and 7 deletions

View file

@ -18,6 +18,7 @@ package nginx
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
@ -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)
}
@ -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
}

View file

@ -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 {
@ -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
}
@ -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
}
return buffer.Bytes(), err
err = isValidTemplate(buffer.Bytes())
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
func fixKeyNames(data map[string]interface{}) map[string]interface{} {
@ -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)
}
}