server-sent events support through new annotation
This commit is contained in:
parent
198c926bb9
commit
66f2e50c52
8 changed files with 122 additions and 0 deletions
|
@ -50,6 +50,7 @@ The following annotations are supported:
|
||||||
|[ingress.kubernetes.io/auth-tls-verify-depth](#certificate-authentication)|number|
|
|[ingress.kubernetes.io/auth-tls-verify-depth](#certificate-authentication)|number|
|
||||||
|[ingress.kubernetes.io/configuration-snippet](#configuration-snippet)|string|
|
|[ingress.kubernetes.io/configuration-snippet](#configuration-snippet)|string|
|
||||||
|[ingress.kubernetes.io/enable-cors](#enable-cors)|true or false|
|
|[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/force-ssl-redirect](#server-side-https-enforcement-through-redirect)|true or false|
|
||||||
|[ingress.kubernetes.io/limit-connections](#rate-limiting)|number|
|
|[ingress.kubernetes.io/limit-connections](#rate-limiting)|number|
|
||||||
|[ingress.kubernetes.io/limit-rps](#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.
|
* 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.
|
* 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
|
### 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.
|
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.
|
||||||
|
|
|
@ -420,9 +420,16 @@ http {
|
||||||
proxy_set_header ssl-client-cert $ssl_client_cert;
|
proxy_set_header ssl-client-cert $ssl_client_cert;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if $location.Eventsource }}
|
||||||
|
# Allow server sent events
|
||||||
|
proxy_set_header Connection '';
|
||||||
|
proxy_cache off;
|
||||||
|
chunked_transfer_encoding off;
|
||||||
|
{{ else }}
|
||||||
# Allow websocket connections
|
# Allow websocket connections
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection $connection_upgrade;
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
proxy_set_header X-Real-IP $the_real_ip;
|
proxy_set_header X-Real-IP $the_real_ip;
|
||||||
proxy_set_header X-Forwarded-For $the_real_ip;
|
proxy_set_header X-Forwarded-For $the_real_ip;
|
||||||
|
|
38
core/pkg/ingress/annotations/eventsource/main.go
Normal file
38
core/pkg/ingress/annotations/eventsource/main.go
Normal 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)
|
||||||
|
}
|
63
core/pkg/ingress/annotations/eventsource/main_test.go
Normal file
63
core/pkg/ingress/annotations/eventsource/main_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/authreq"
|
"k8s.io/ingress/core/pkg/ingress/annotations/authreq"
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/authtls"
|
"k8s.io/ingress/core/pkg/ingress/annotations/authtls"
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/cors"
|
"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/healthcheck"
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/ipwhitelist"
|
"k8s.io/ingress/core/pkg/ingress/annotations/ipwhitelist"
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/parser"
|
"k8s.io/ingress/core/pkg/ingress/annotations/parser"
|
||||||
|
@ -58,6 +59,7 @@ func newAnnotationExtractor(cfg extractorConfig) annotationExtractor {
|
||||||
"ExternalAuth": authreq.NewParser(),
|
"ExternalAuth": authreq.NewParser(),
|
||||||
"CertificateAuth": authtls.NewParser(cfg),
|
"CertificateAuth": authtls.NewParser(cfg),
|
||||||
"EnableCORS": cors.NewParser(),
|
"EnableCORS": cors.NewParser(),
|
||||||
|
"Eventsource": eventsource.NewParser(),
|
||||||
"HealthCheck": healthcheck.NewParser(cfg),
|
"HealthCheck": healthcheck.NewParser(cfg),
|
||||||
"Whitelist": ipwhitelist.NewParser(cfg),
|
"Whitelist": ipwhitelist.NewParser(cfg),
|
||||||
"UsePortInRedirects": portinredirect.NewParser(cfg),
|
"UsePortInRedirects": portinredirect.NewParser(cfg),
|
||||||
|
|
|
@ -97,6 +97,7 @@ func TestMergeLocationAnnotations(t *testing.T) {
|
||||||
"BasicDigestAuth": auth.BasicDigest{},
|
"BasicDigestAuth": auth.BasicDigest{},
|
||||||
DeniedKeyName: &fakeError{},
|
DeniedKeyName: &fakeError{},
|
||||||
"EnableCORS": true,
|
"EnableCORS": true,
|
||||||
|
"Eventsource": true,
|
||||||
"ExternalAuth": authreq.External{},
|
"ExternalAuth": authreq.External{},
|
||||||
"RateLimit": ratelimit.RateLimit{},
|
"RateLimit": ratelimit.RateLimit{},
|
||||||
"Redirect": rewrite.Redirect{},
|
"Redirect": rewrite.Redirect{},
|
||||||
|
|
|
@ -265,6 +265,9 @@ type Location struct {
|
||||||
// EnableCORS indicates if path must support CORS
|
// EnableCORS indicates if path must support CORS
|
||||||
// +optional
|
// +optional
|
||||||
EnableCORS bool `json:"enableCors,omitempty"`
|
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
|
// ExternalAuth indicates the access to this location requires
|
||||||
// authentication using an external provider
|
// authentication using an external provider
|
||||||
// +optional
|
// +optional
|
||||||
|
|
|
@ -353,6 +353,9 @@ func (l1 *Location) Equal(l2 *Location) bool {
|
||||||
if l1.EnableCORS != l2.EnableCORS {
|
if l1.EnableCORS != l2.EnableCORS {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if l1.Eventsource != l2.Eventsource {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if !(&l1.ExternalAuth).Equal(&l2.ExternalAuth) {
|
if !(&l1.ExternalAuth).Equal(&l2.ExternalAuth) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue