Skip to content

Commit

Permalink
Merge pull request #26 from nginxinc/fix-default-backend-and-no-host
Browse files Browse the repository at this point in the history
Support for default backend and empty host fields
  • Loading branch information
pleshakov committed May 12, 2016
2 parents a0681be + 6d94990 commit 3f49360
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 95 deletions.
2 changes: 1 addition & 1 deletion examples/nginx-ingress-rc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ spec:
app: nginx-ingress
spec:
containers:
- image: nginxdemos/nginx-ingress:0.1
- image: nginxdemos/nginx-ingress:0.2
imagePullPolicy: Always
name: nginx-ingress
ports:
Expand Down
3 changes: 1 addition & 2 deletions examples/nginx-plus-ingress-rc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ spec:
app: nginx-plus-ingress
spec:
containers:
- image: gcr.io/nginx-ingress/nginx-plus-ingress:0.1
- image: gcr.io/nginx-dev-ingress/nginx-plus-ingress:0.2
imagePullPolicy: Always
name: nginx-plus-ingress
ports:
Expand All @@ -24,4 +24,3 @@ spec:
hostPort: 443
- containerPort: 8080
hostPort: 8080

2 changes: 1 addition & 1 deletion nginx-controller/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
all: push

TAG = 0.1
TAG = 0.2
PREFIX = nginxdemos/nginx-ingress

nginx-ingress:
Expand Down
144 changes: 101 additions & 43 deletions nginx-controller/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ type LoadBalancerController struct {
nginx *nginx.NGINXController
}

const (
emptyHost = ""
)

var keyFunc = framework.DeletionHandlingMetaNamespaceKeyFunc

// NewLoadBalancerController creates a controller
Expand Down Expand Up @@ -203,7 +207,11 @@ func (lbc *LoadBalancerController) syncIng(key string) {
lbc.nginx.DeleteIngress(name)
} else {
ing := obj.(*extensions.Ingress)
lbc.updateNGINX(name, ing)

pems := lbc.updateCertificates(ing)

nginxCfg := lbc.generateNGINXCfg(ing, pems)
lbc.nginx.AddOrUpdateIngress(name, nginxCfg)
}

lbc.nginx.Reload()
Expand Down Expand Up @@ -234,7 +242,7 @@ func (lbc *LoadBalancerController) enqueueIngressForEndpoints(obj interface{}) {
}
}

func (lbc *LoadBalancerController) updateNGINX(name string, ing *extensions.Ingress) {
func (lbc *LoadBalancerController) updateCertificates(ing *extensions.Ingress) map[string]string {
pems := make(map[string]string)

for _, tls := range ing.Spec.TLS {
Expand All @@ -260,77 +268,127 @@ func (lbc *LoadBalancerController) updateNGINX(name string, ing *extensions.Ingr
for _, host := range tls.Hosts {
pems[host] = pemFileName
}
if len(tls.Hosts) == 0 {
pems[emptyHost] = pemFileName
}
}

return pems
}

func (lbc *LoadBalancerController) generateNGINXCfg(ing *extensions.Ingress, pems map[string]string) nginx.IngressNGINXConfig {
upstreams := make(map[string]nginx.Upstream)

if ing.Spec.Backend != nil {
name := getNameForUpstream(ing, emptyHost, ing.Spec.Backend.ServiceName)
upstream := lbc.createUpstream(name, ing.Spec.Backend, ing.Namespace)
upstreams[name] = upstream
}

var servers []nginx.Server

for _, rule := range ing.Spec.Rules {
if rule.IngressRuleValue.HTTP == nil {
continue
}

for _, path := range rule.HTTP.Paths {
name := getNameForUpstream(ing, rule.Host, path.Backend.ServiceName)
if _, exists := upstreams[name]; exists {
continue
}
ups := nginx.NewUpstreamWithDefaultServer(name)

svcKey := ing.Namespace + "/" + path.Backend.ServiceName
svcObj, svcExists, err := lbc.svcLister.Store.GetByKey(svcKey)
if err != nil {
glog.Infof("error getting service %v from the cache: %v", svcKey, err)
} else {
if svcExists {
svc := svcObj.(*api.Service)
if svc.Spec.ClusterIP != "None" && svc.Spec.ClusterIP != "" {
upsServer := nginx.UpstreamServer{Address: svc.Spec.ClusterIP, Port: path.Backend.ServicePort.String()}
ups.UpstreamServers = []nginx.UpstreamServer{upsServer}
} else if svc.Spec.ClusterIP == "None" {
endps, err := lbc.endpLister.GetServiceEndpoints(svc)
if err != nil {
glog.Infof("error getting endpoints for service %v from the cache: %v", svc, err)
} else {
upsServers := endpointsToUpstreamServers(endps, path.Backend.ServicePort.IntValue())
if len(upsServers) > 0 {
ups.UpstreamServers = upsServers
}
}
}
}
}
upstreams[name] = ups
serverName := rule.Host

if rule.Host == emptyHost {
glog.Warningf("Host field of ingress rule in %v/%v is empty", ing.Namespace, ing.Name)
}
}

var servers []nginx.Server
for _, rule := range ing.Spec.Rules {
server := nginx.Server{Name: rule.Host}
server := nginx.Server{Name: serverName}

if pemFile, ok := pems[rule.Host]; ok {
if pemFile, ok := pems[serverName]; ok {
server.SSL = true
server.SSLCertificate = pemFile
server.SSLCertificateKey = pemFile
}

var locations []nginx.Location
rootLocation := false

for _, path := range rule.HTTP.Paths {
loc := nginx.Location{Path: pathOrDefault(path.Path)}
upsName := getNameForUpstream(ing, rule.Host, path.Backend.ServiceName)

if ups, ok := upstreams[upsName]; ok {
loc.Upstream = ups
locations = append(locations, loc)
if _, exists := upstreams[upsName]; !exists {
upstream := lbc.createUpstream(upsName, &path.Backend, ing.Namespace)
upstreams[upsName] = upstream
}
loc := nginx.Location{Path: pathOrDefault(path.Path)}

loc.Upstream = upstreams[upsName]
locations = append(locations, loc)

if loc.Path == "/" {
rootLocation = true
}
}

if rootLocation == false && ing.Spec.Backend != nil {
upsName := getNameForUpstream(ing, emptyHost, ing.Spec.Backend.ServiceName)
loc := nginx.Location{Path: pathOrDefault("/")}
loc.Upstream = upstreams[upsName]
locations = append(locations, loc)
}

server.Locations = locations
servers = append(servers, server)
}

lbc.nginx.AddOrUpdateIngress(name, nginx.IngressNGINXConfig{Upstreams: upstreamMapToSlice(upstreams), Servers: servers})
if len(ing.Spec.Rules) == 0 && ing.Spec.Backend != nil {
server := nginx.Server{Name: emptyHost}

if pemFile, ok := pems[emptyHost]; ok {
server.SSL = true
server.SSLCertificate = pemFile
server.SSLCertificateKey = pemFile
}

var locations []nginx.Location

upsName := getNameForUpstream(ing, emptyHost, ing.Spec.Backend.ServiceName)

loc := nginx.Location{Path: "/"}
loc.Upstream = upstreams[upsName]
locations = append(locations, loc)

server.Locations = locations
servers = append(servers, server)
}

return nginx.IngressNGINXConfig{Upstreams: upstreamMapToSlice(upstreams), Servers: servers}
}

func (lbc *LoadBalancerController) createUpstream(name string, backend *extensions.IngressBackend, namespace string) nginx.Upstream {
ups := nginx.NewUpstreamWithDefaultServer(name)

svcKey := namespace + "/" + backend.ServiceName
svcObj, svcExists, err := lbc.svcLister.Store.GetByKey(svcKey)
if err != nil {
glog.Infof("error getting service %v from the cache: %v", svcKey, err)
} else {
if svcExists {
svc := svcObj.(*api.Service)
if svc.Spec.ClusterIP != "None" && svc.Spec.ClusterIP != "" {
upsServer := nginx.UpstreamServer{Address: svc.Spec.ClusterIP, Port: backend.ServicePort.String()}
ups.UpstreamServers = []nginx.UpstreamServer{upsServer}
} else if svc.Spec.ClusterIP == "None" {
endps, err := lbc.endpLister.GetServiceEndpoints(svc)
if err != nil {
glog.Infof("error getting endpoints for service %v from the cache: %v", svc, err)
} else {
upsServers := endpointsToUpstreamServers(endps, backend.ServicePort.IntValue())
if len(upsServers) > 0 {
ups.UpstreamServers = upsServers
}
}
}
}
}

return ups
}

func pathOrDefault(path string) string {
Expand Down
22 changes: 12 additions & 10 deletions nginx-controller/nginx/ingress.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ server {
ssl_certificate_key {{$server.SSLCertificateKey}};
{{end}}

server_name {{$server.Name}};
{{if $server.Name}}
server_name {{$server.Name}};
{{end}}

{{if $server.SSL}}
if ($scheme = http) {
Expand All @@ -22,13 +24,13 @@ server {
{{end}}

{{range $location := $server.Locations}}
location {{$location.Path}} {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://{{$location.Upstream.Name}};
}{{end}}
location {{$location.Path}} {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://{{$location.Upstream.Name}};
}{{end}}
}{{end}}
4 changes: 2 additions & 2 deletions nginx-plus-controller/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
all: push

TAG = 0.1
PREFIX = gcr.io/nginx-ingress/nginx-plus-ingress
TAG = 0.2
PREFIX = gcr.io/nginx-dev-ingress/nginx-plus-ingress

nginx-plus-ingress:
CGO_ENABLED=0 GOOS=linux godep go build -a -installsuffix cgo -ldflags '-w' -o nginx-plus-ingress *.go
Expand Down
Loading

0 comments on commit 3f49360

Please sign in to comment.