This commit is contained in:
Winfield Chen 2017-08-09 00:24:32 +00:00 committed by GitHub
commit 2c4b0be226
8 changed files with 122 additions and 0 deletions

View file

@ -50,6 +50,7 @@ The following annotations are supported:
|[ingress.kubernetes.io/auth-tls-verify-depth](#certificate-authentication)|number|
|[ingress.kubernetes.io/configuration-snippet](#configuration-snippet)|string|
|[ingress.kubernetes.io/enable-cors](#enable-cors)|true or false|
|[ingress.kubernetes.io/eventsource](#eventsource)|true or false|
|[ingress.kubernetes.io/force-ssl-redirect](#server-side-https-enforcement-through-redirect)|true or false|
|[ingress.kubernetes.io/limit-connections](#rate-limiting)|number|
|[ingress.kubernetes.io/limit-rps](#rate-limiting)|number|
@ -228,6 +229,10 @@ If the `service-upstream` annotation is specified the following things should be
* Sticky Sessions will not work as only round-robin load balancing is supported.
* The `proxy_next_upstream` directive will not have any effect meaning on error the request will not be dispatched to another upstream.
### Eventsource
The annotation `ingress.kubernetes.io/eventsource` sets headers to be compatible with Server Sent Events.
### Server-side HTTPS enforcement through redirect
By default the controller redirects (301) to `HTTPS` if TLS is enabled for that ingress. If you want to disable that behaviour globally, you can use `ssl-redirect: "false"` in the NGINX config map.

View file

@ -420,9 +420,16 @@ http {
proxy_set_header ssl-client-cert $ssl_client_cert;
{{ end }}
{{ if $location.Eventsource }}
# Allow server sent events
proxy_set_header Connection '';
proxy_cache off;
chunked_transfer_encoding off;
{{ else }}
# Allow websocket connections
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{{ end }}
proxy_set_header X-Real-IP $the_real_ip;
proxy_set_header X-Forwarded-For $the_real_ip;

View file

@ -0,0 +1,38 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package eventsource
import (
extensions "k8s.io/api/extensions/v1beta1"
"k8s.io/ingress/core/pkg/ingress/annotations/parser"
)
const (
annotation = "ingress.kubernetes.io/eventsource"
)
type eventsource struct {
}
func NewParser() parser.IngressAnnotation {
return eventsource{}
}
func (a eventsource) Parse(ing *extensions.Ingress) (interface{}, error) {
return parser.GetBoolAnnotation(annotation, ing)
}

View file

@ -0,0 +1,63 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package eventsource
import (
"testing"
api "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
notEventsourceAnnotation = "ingress.kubernetes.io/not-eventsource"
)
func TestParse(t *testing.T) {
ap := NewParser()
if ap == nil {
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
}
testCases := []struct {
annotations map[string]string
expected bool
}{
{map[string]string{annotation: "true"}, true},
{map[string]string{annotation: "false"}, false},
{map[string]string{notEventsourceAnnotation: "true"}, false},
{map[string]string{}, false},
{nil, false},
}
ing := &extensions.Ingress{
ObjectMeta: meta_v1.ObjectMeta{
Name: "foo",
Namespace: api.NamespaceDefault,
},
Spec: extensions.IngressSpec{},
}
for _, testCase := range testCases {
ing.SetAnnotations(testCase.annotations)
result, _ := ap.Parse(ing)
if result != testCase.expected {
t.Errorf("expected %t but returned %t, annotations: %s", testCase.expected, result, testCase.annotations)
}
}
}

View file

@ -23,6 +23,7 @@ import (
"k8s.io/ingress/core/pkg/ingress/annotations/authreq"
"k8s.io/ingress/core/pkg/ingress/annotations/authtls"
"k8s.io/ingress/core/pkg/ingress/annotations/cors"
"k8s.io/ingress/core/pkg/ingress/annotations/eventsource"
"k8s.io/ingress/core/pkg/ingress/annotations/healthcheck"
"k8s.io/ingress/core/pkg/ingress/annotations/ipwhitelist"
"k8s.io/ingress/core/pkg/ingress/annotations/parser"
@ -58,6 +59,7 @@ func newAnnotationExtractor(cfg extractorConfig) annotationExtractor {
"ExternalAuth": authreq.NewParser(),
"CertificateAuth": authtls.NewParser(cfg),
"EnableCORS": cors.NewParser(),
"Eventsource": eventsource.NewParser(),
"HealthCheck": healthcheck.NewParser(cfg),
"Whitelist": ipwhitelist.NewParser(cfg),
"UsePortInRedirects": portinredirect.NewParser(cfg),

View file

@ -97,6 +97,7 @@ func TestMergeLocationAnnotations(t *testing.T) {
"BasicDigestAuth": auth.BasicDigest{},
DeniedKeyName: &fakeError{},
"EnableCORS": true,
"Eventsource": true,
"ExternalAuth": authreq.External{},
"RateLimit": ratelimit.RateLimit{},
"Redirect": rewrite.Redirect{},

View file

@ -265,6 +265,9 @@ type Location struct {
// EnableCORS indicates if path must support CORS
// +optional
EnableCORS bool `json:"enableCors,omitempty"`
// Eventsource indicates the path is a server sent events endpoint
// +optional
Eventsource bool `json:"eventsource,omitempty"`
// ExternalAuth indicates the access to this location requires
// authentication using an external provider
// +optional

View file

@ -353,6 +353,9 @@ func (l1 *Location) Equal(l2 *Location) bool {
if l1.EnableCORS != l2.EnableCORS {
return false
}
if l1.Eventsource != l2.Eventsource {
return false
}
if !(&l1.ExternalAuth).Equal(&l2.ExternalAuth) {
return false
}