Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split implementations from generic code #15

Merged
merged 5 commits into from
Nov 24, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ script:
# enable kubernetes/ingress in
# coveralls.io and add cover task
- make fmt lint vet test
- make controllers controllers-images
#- make controllers controllers-images
#- make test-e2e
73 changes: 39 additions & 34 deletions controllers/nginx/pkg/cmd/controller/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ import (

"github.com/golang/glog"

"k8s.io/kubernetes/pkg/api"

"k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/ingress/defaults"

"errors"

"k8s.io/ingress/controllers/nginx/pkg/config"
ngx_template "k8s.io/ingress/controllers/nginx/pkg/template"
"k8s.io/ingress/controllers/nginx/pkg/version"

"k8s.io/kubernetes/pkg/api"
)

var (
Expand Down Expand Up @@ -75,6 +77,8 @@ Error loading new template : %v
}

n.t = ngxTpl
go n.Start()

return n
}

Expand All @@ -85,7 +89,7 @@ type NGINXController struct {
binary string
}

// Start ...
// Start start a new NGINX master process running in foreground.
func (n NGINXController) Start() {
glog.Info("starting NGINX process...")
cmd := exec.Command(n.binary, "-c", cfgPath)
Expand All @@ -99,14 +103,13 @@ func (n NGINXController) Start() {
}
}

// Stop ...
func (n NGINXController) Stop() error {
n.t.Close()
return exec.Command(n.binary, "-s", "stop").Run()
}
// Reload checks if the running configuration file is different
// to the specified and reload nginx if required
func (n NGINXController) Reload(data []byte) ([]byte, error) {
if !n.isReloadRequired(data) {
return nil, fmt.Errorf("Reload not required")
}

// Restart ...
func (n NGINXController) Restart(data []byte) ([]byte, error) {
err := ioutil.WriteFile(cfgPath, data, 0644)
if err != nil {
return nil, err
Expand All @@ -120,15 +123,15 @@ func (n NGINXController) Test(file string) *exec.Cmd {
return exec.Command(n.binary, "-t", "-c", file)
}

// UpstreamDefaults returns the nginx defaults
func (n NGINXController) UpstreamDefaults() defaults.Backend {
// BackendDefaults returns the nginx defaults
func (n NGINXController) BackendDefaults() defaults.Backend {
d := config.NewDefault()
return d.Backend
}

// IsReloadRequired check if the new configuration file is different
// from the current one.
func (n NGINXController) IsReloadRequired(data []byte) bool {
func (n NGINXController) isReloadRequired(data []byte) bool {
in, err := os.Open(cfgPath)
if err != nil {
return false
Expand Down Expand Up @@ -167,8 +170,13 @@ func (n NGINXController) IsReloadRequired(data []byte) bool {
}

// Info return build information
func (n NGINXController) Info() string {
return fmt.Sprintf("build version %v from repo %v commit %v", version.RELEASE, version.REPO, version.COMMIT)
func (n NGINXController) Info() *ingress.BackendInfo {
return &ingress.BackendInfo{
Name: "NGINX",
Release: version.RELEASE,
Build: version.COMMIT,
Repository: version.REPO,
}
}

// testTemplate checks if the NGINX configuration inside the byte array is valid
Expand All @@ -183,12 +191,13 @@ func (n NGINXController) testTemplate(cfg []byte) error {
out, err := n.Test(tmpfile.Name()).CombinedOutput()
if err != nil {
// this error is different from the rest because it must be clear why nginx is not working
return fmt.Errorf(`
oe := fmt.Sprintf(`
-------------------------------------------------------------------------------
Error: %v
%v
-------------------------------------------------------------------------------
`, err, string(out))
return errors.New(oe)
}

os.Remove(tmpfile.Name())
Expand All @@ -207,9 +216,9 @@ func (n NGINXController) OnUpdate(cmap *api.ConfigMap, ingressCfg ingress.Config
var longestName int
var serverNames int
for _, srv := range ingressCfg.Servers {
serverNames += len([]byte(srv.Name))
if longestName < len(srv.Name) {
longestName = len(srv.Name)
serverNames += len([]byte(srv.Hostname))
if longestName < len(srv.Hostname) {
longestName = len(srv.Hostname)
}
}

Expand All @@ -234,21 +243,17 @@ func (n NGINXController) OnUpdate(cmap *api.ConfigMap, ingressCfg ingress.Config
cfg.ServerNameHashMaxSize = serverNameHashMaxSize
}

conf := make(map[string]interface{})
// adjust the size of the backlog
conf["backlogSize"] = sysctlSomaxconn()
conf["upstreams"] = ingressCfg.Upstreams
conf["passthroughUpstreams"] = ingressCfg.PassthroughUpstreams
conf["servers"] = ingressCfg.Servers
conf["tcpUpstreams"] = ingressCfg.TCPEndpoints
conf["udpUpstreams"] = ingressCfg.UPDEndpoints
conf["healthzURL"] = ingressCfg.HealthzURL
conf["defResolver"] = cfg.Resolver
conf["sslDHParam"] = ""
conf["customErrors"] = len(cfg.CustomHTTPErrors) > 0
conf["cfg"] = ngx_template.StandarizeKeyNames(cfg)

return n.t.Write(conf, n.testTemplate)
return n.t.Write(config.TemplateConfig{
BacklogSize: sysctlSomaxconn(),
Backends: ingressCfg.Backends,
PassthrougBackends: ingressCfg.PassthroughBackends,
Servers: ingressCfg.Servers,
TCPBackends: ingressCfg.TCPEndpoints,
UDPBackends: ingressCfg.UPDEndpoints,
HealthzURI: "/healthz",
CustomErrors: len(cfg.CustomHTTPErrors) > 0,
Cfg: cfg,
}, n.testTemplate)
}

// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
Expand Down
20 changes: 16 additions & 4 deletions controllers/nginx/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ package config
import (
"runtime"

"k8s.io/ingress/core/pkg/ingress/defaults"

"github.com/golang/glog"

"k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/ingress/defaults"
)

const (
Expand Down Expand Up @@ -216,8 +217,7 @@ type Configuration struct {
WorkerProcesses int `structs:"worker-processes,omitempty"`
}

// NewDefault returns the default configuration contained
// in the file default-conf.json
// NewDefault returns the default nginx configuration
func NewDefault() Configuration {
cfg := Configuration{
BodySize: bodySize,
Expand Down Expand Up @@ -264,3 +264,15 @@ func NewDefault() Configuration {

return cfg
}

type TemplateConfig struct {
BacklogSize int
Backends []*ingress.Backend
PassthrougBackends []*ingress.SSLPassthroughBackend
Servers []*ingress.Server
TCPBackends []*ingress.Location
UDPBackends []*ingress.Location
HealthzURI string
CustomErrors bool
Cfg Configuration
}
10 changes: 5 additions & 5 deletions controllers/nginx/pkg/template/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import (
"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/kubernetes/pkg/api"
)

const (
Expand All @@ -50,9 +50,9 @@ func ReadConfig(conf *api.ConfigMap) config.Configuration {
return config.NewDefault()
}

var errors []int
var skipUrls []string
var whitelist []string
errors := make([]int, 0)
skipUrls := make([]string, 0)
whitelist := make([]string, 0)

if val, ok := conf.Data[customHTTPErrors]; ok {
delete(conf.Data, customHTTPErrors)
Expand Down
86 changes: 58 additions & 28 deletions controllers/nginx/pkg/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/golang/glog"

"k8s.io/ingress/controllers/nginx/pkg/config"
"k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/watch"
)
Expand Down Expand Up @@ -73,12 +74,19 @@ 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(conf map[string]interface{},
isValidTemplate func([]byte) error) ([]byte, error) {

func (t *Template) Write(conf config.TemplateConfig, isValidTemplate func([]byte) error) ([]byte, error) {
defer t.tmplBuf.Reset()
defer t.outCmdBuf.Reset()

defer func() {
if t.s < t.tmplBuf.Cap() {
glog.V(2).Infof("adjusting template buffer size from %v to %v", t.s, t.tmplBuf.Cap())
t.s = t.tmplBuf.Cap()
t.tmplBuf = bytes.NewBuffer(make([]byte, 0, t.tmplBuf.Cap()))
t.outCmdBuf = bytes.NewBuffer(make([]byte, 0, t.outCmdBuf.Cap()))
}
}()

if glog.V(3) {
b, err := json.Marshal(conf)
if err != nil {
Expand All @@ -88,12 +96,8 @@ func (t *Template) Write(conf map[string]interface{},
}

err := t.tmpl.Execute(t.tmplBuf, conf)

if t.s < t.tmplBuf.Cap() {
glog.V(2).Infof("adjusting template buffer size from %v to %v", t.s, t.tmplBuf.Cap())
t.s = t.tmplBuf.Cap()
t.tmplBuf = bytes.NewBuffer(make([]byte, 0, t.tmplBuf.Cap()))
t.outCmdBuf = bytes.NewBuffer(make([]byte, 0, t.outCmdBuf.Cap()))
if err != nil {
return nil, err
}

// squeezes multiple adjacent empty lines to be single
Expand Down Expand Up @@ -124,12 +128,12 @@ var (
}
return true
},
"buildLocation": buildLocation,
"buildAuthLocation": buildAuthLocation,
"buildProxyPass": buildProxyPass,
"buildRateLimitZones": buildRateLimitZones,
"buildRateLimit": buildRateLimit,
"getSSPassthroughUpstream": getSSPassthroughUpstream,
"buildLocation": buildLocation,
"buildAuthLocation": buildAuthLocation,
"buildProxyPass": buildProxyPass,
"buildRateLimitZones": buildRateLimitZones,
"buildRateLimit": buildRateLimit,
"buildSSPassthroughUpstreams": buildSSPassthroughUpstreams,

"contains": strings.Contains,
"hasPrefix": strings.HasPrefix,
Expand All @@ -139,13 +143,32 @@ var (
}
)

func getSSPassthroughUpstream(input interface{}) string {
s, ok := input.(*ingress.Server)
if !ok {
return ""
func buildSSPassthroughUpstreams(b interface{}, sslb interface{}) string {
backends := b.([]*ingress.Backend)
sslBackends := sslb.([]*ingress.SSLPassthroughBackend)
buf := bytes.NewBuffer(make([]byte, 0, 10))

// multiple services can use the same upstream.
// avoid duplications using a map[name]=true
u := make(map[string]bool)
for _, passthrough := range sslBackends {
if u[passthrough.Backend] {
continue
}
u[passthrough.Backend] = true
fmt.Fprintf(buf, "upstream %v {\n", passthrough.Backend)
for _, backend := range backends {
if backend.Name == passthrough.Backend {
for _, server := range backend.Endpoints {
fmt.Fprintf(buf, "\t\tserver %v:%v;\n", server.Address, server.Port)
}
break
}
}
fmt.Fprint(buf, "\t}\n\n")
}

return s.Name
return buf.String()
}

// buildLocation produces the location string, if the ingress has redirects
Expand Down Expand Up @@ -184,20 +207,27 @@ func buildAuthLocation(input interface{}) string {
// (specified through the ingress.kubernetes.io/rewrite-to annotation)
// If the annotation 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(input interface{}) string {
location, ok := input.(*ingress.Location)
func buildProxyPass(b interface{}, loc interface{}) string {
backends := b.([]*ingress.Backend)
location, ok := loc.(*ingress.Location)
if !ok {
return ""
}

path := location.Path

proto := "http"
if location.SecureUpstream {
proto = "https"

for _, backend := range backends {
if backend.Name == location.Backend {
if backend.Secure {
proto = "https"
}
break
}
}

// defProxyPass returns the default proxy_pass, just the name of the upstream
defProxyPass := fmt.Sprintf("proxy_pass %s://%s;", proto, location.Backend.Name)
defProxyPass := fmt.Sprintf("proxy_pass %s://%s;", proto, location.Backend)
// if the path in the ingress rule is equals to the target: no special rewrite
if path == location.Redirect.Target {
return defProxyPass
Expand Down Expand Up @@ -227,13 +257,13 @@ func buildProxyPass(input interface{}) string {
rewrite %s(.*) /$1 break;
rewrite %s / break;
proxy_pass %s://%s;
%v`, path, location.Path, proto, location.Backend.Name, abu)
%v`, path, location.Path, proto, location.Backend, abu)
}

return fmt.Sprintf(`
rewrite %s(.*) %s/$1 break;
proxy_pass %s://%s;
%v`, path, location.Redirect.Target, proto, location.Backend.Name, abu)
%v`, path, location.Redirect.Target, proto, location.Backend, abu)
}

// default proxy_pass
Expand Down
Loading