Merge pull request #3586 from Shopify/disable-catch-all

Add --disable-catch-all option to disable catch-all server
This commit is contained in:
Kubernetes Prow Robot 2019-01-07 07:16:26 -08:00 committed by GitHub
commit 8f57f9578d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 172 additions and 10 deletions

View file

@ -158,6 +158,9 @@ Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not en
sslProxyPort = flags.Int("ssl-passthrough-proxy-port", 442, `Port to use internally for SSL Passthrough.`)
defServerPort = flags.Int("default-server-port", 8181, `Port to use for exposing the default server (catch-all).`)
healthzPort = flags.Int("healthz-port", 10254, "Port to use for the healthz endpoint.")
disableCatchAll = flags.Bool("disable-catch-all", false,
`Disable support for catch-all Ingresses`)
)
flag.Set("logtostderr", "true")
@ -257,6 +260,7 @@ Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not en
SSLProxy: *sslProxyPort,
Status: *statusPort,
},
DisableCatchAll: *disableCatchAll,
}
return false, config, nil

View file

@ -46,3 +46,4 @@ They are set in the container spec of the `nginx-ingress-controller` Deployment
| `--version` | Show release information about the NGINX Ingress controller and exit. |
| `--vmodule moduleSpec` | comma-separated list of pattern=N settings for file-filtered logging |
| `--watch-namespace string` | Namespace the controller watches for updates to Kubernetes objects. This includes Ingresses, Services and all configuration resources. All namespaces are watched if this parameter is left empty. |
| `--disable-catch-all` | Disable support for catch-all Ingresses. |

View file

@ -98,6 +98,8 @@ type Configuration struct {
SyncRateLimit float32
DynamicCertificatesEnabled bool
DisableCatchAll bool
}
// GetPublishService returns the Service used to set the load-balancer status of Ingresses.

View file

@ -915,7 +915,8 @@ func newNGINXController(t *testing.T) *NGINXController {
fs,
channels.NewRingChannel(10),
false,
pod)
pod,
false)
config := &Configuration{
ListenPorts: &ngx_config.ListenPorts{

View file

@ -128,7 +128,8 @@ func NewNGINXController(config *Configuration, mc metric.Collector, fs file.File
fs,
n.updateCh,
config.DynamicCertificatesEnabled,
pod)
pod,
config.DisableCatchAll)
n.syncQueue = task.NewTaskQueue(n.syncIngress)

View file

@ -233,7 +233,8 @@ func New(checkOCSP bool,
fs file.Filesystem,
updateCh *channels.RingChannel,
isDynamicCertificatesEnabled bool,
pod *k8s.PodInfo) Storer {
pod *k8s.PodInfo,
disableCatchAll bool) Storer {
store := &k8sStore{
isOCSPCheckEnabled: checkOCSP,
@ -311,6 +312,10 @@ func New(checkOCSP bool,
klog.Infof("ignoring add for ingress %v based on annotation %v with value %v", ing.Name, class.IngressKey, a)
return
}
if ing.Spec.Backend != nil && disableCatchAll {
klog.Infof("ignoring add for catch-all ingress %v/%v because of --disable-catch-all", ing.Namespace, ing.Name)
return
}
recorder.Eventf(ing, corev1.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", ing.Namespace, ing.Name))
store.syncIngress(ing)
@ -341,6 +346,10 @@ func New(checkOCSP bool,
klog.Infof("ignoring delete for ingress %v based on annotation %v", ing.Name, class.IngressKey)
return
}
if ing.Spec.Backend != nil && disableCatchAll {
klog.Infof("ignoring delete for catch-all ingress %v/%v because of --disable-catch-all", ing.Namespace, ing.Name)
return
}
recorder.Eventf(ing, corev1.EventTypeNormal, "DELETE", fmt.Sprintf("Ingress %s/%s", ing.Namespace, ing.Name))
store.listers.IngressWithAnnotation.Delete(ing)
@ -359,13 +368,27 @@ func New(checkOCSP bool,
validOld := class.IsValid(oldIng)
validCur := class.IsValid(curIng)
if !validOld && validCur {
if curIng.Spec.Backend != nil && disableCatchAll {
klog.Infof("ignoring update for catch-all ingress %v/%v because of --disable-catch-all", curIng.Namespace, curIng.Name)
return
}
klog.Infof("creating ingress %v based on annotation %v", curIng.Name, class.IngressKey)
recorder.Eventf(curIng, corev1.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
} else if validOld && !validCur {
klog.Infof("removing ingress %v based on annotation %v", curIng.Name, class.IngressKey)
// FIXME: this does not actually delete the Ingress resource.
// The existing one will be updated with latest changes and invalid ingress.class will be missed.
recorder.Eventf(curIng, corev1.EventTypeNormal, "DELETE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
} else if validCur && !reflect.DeepEqual(old, cur) {
recorder.Eventf(curIng, corev1.EventTypeNormal, "UPDATE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
if curIng.Spec.Backend != nil && disableCatchAll {
klog.Infof("ignoring update for catch-all ingress %v/%v because of --disable-catch-all", curIng.Namespace, curIng.Name)
// FIXME: this does not actually delete the Ingress resource.
// The existing one will be updated with latest changes.
recorder.Eventf(curIng, corev1.EventTypeNormal, "DELETE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
} else {
recorder.Eventf(curIng, corev1.EventTypeNormal, "UPDATE", fmt.Sprintf("Ingress %s/%s", curIng.Namespace, curIng.Name))
}
} else {
klog.Infof("ignoring ingress %v based on annotation %v", curIng.Name, class.IngressKey)
return

View file

@ -82,7 +82,8 @@ func TestStore(t *testing.T) {
fs,
updateCh,
false,
pod)
pod,
false)
storer.Run(stopCh)
@ -163,7 +164,8 @@ func TestStore(t *testing.T) {
fs,
updateCh,
false,
pod)
pod,
false)
storer.Run(stopCh)
@ -316,7 +318,8 @@ func TestStore(t *testing.T) {
fs,
updateCh,
false,
pod)
pod,
false)
storer.Run(stopCh)
@ -424,7 +427,8 @@ func TestStore(t *testing.T) {
fs,
updateCh,
false,
pod)
pod,
false)
storer.Run(stopCh)
@ -514,7 +518,8 @@ func TestStore(t *testing.T) {
fs,
updateCh,
false,
pod)
pod,
false)
storer.Run(stopCh)
@ -627,7 +632,8 @@ func TestStore(t *testing.T) {
fs,
updateCh,
false,
pod)
pod,
false)
storer.Run(stopCh)

View file

@ -372,6 +372,21 @@ func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name
return nil
}
// UpdateIngress runs the given updateFunc on the ingress
func UpdateIngress(kubeClientSet kubernetes.Interface, namespace string, name string, updateFunc func(d *extensions.Ingress) error) error {
ingress, err := kubeClientSet.ExtensionsV1beta1().Ingresses(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return err
}
if err := updateFunc(ingress); err != nil {
return err
}
_, err = kubeClientSet.ExtensionsV1beta1().Ingresses(namespace).Update(ingress)
return err
}
// NewSingleIngressWithTLS creates a simple ingress rule with TLS spec included
func NewSingleIngressWithTLS(name, path, host, ns, service string, port int, annotations *map[string]string) *extensions.Ingress {
return newSingleIngressWithRules(name, path, host, ns, service, port, annotations, true)

View file

@ -0,0 +1,109 @@
/*
Copyright 2018 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 settings
import (
"strings"
. "github.com/onsi/ginkgo"
appsv1beta1 "k8s.io/api/apps/v1beta1"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Disabled catch-all", func() {
f := framework.NewDefaultFramework("disabled-catch-all")
BeforeEach(func() {
f.NewEchoDeploymentWithReplicas(1)
framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "nginx-ingress-controller", 1,
func(deployment *appsv1beta1.Deployment) error {
args := deployment.Spec.Template.Spec.Containers[0].Args
args = append(args, "--disable-catch-all=true")
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := f.KubeClientSet.AppsV1beta1().Deployments(f.IngressController.Namespace).Update(deployment)
return err
})
})
AfterEach(func() {
})
It("should ignore catch all Ingress", func() {
host := "foo"
ing := framework.NewSingleCatchAllIngress("catch-all", f.IngressController.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ing)
ing = framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxServer(host, func(cfg string) bool {
return strings.Contains(cfg, "server_name foo")
})
f.WaitForNginxServer("_", func(cfg string) bool {
return strings.Contains(cfg, `set $ingress_name ""`) &&
strings.Contains(cfg, `set $proxy_upstream_name "upstream-default-backend"`)
})
})
// FIXME: This test doesn't work because of a bug in Ingress update handle in store package.
// It("should delete Ingress updated to catch-all", func() {
// host := "foo"
// ing := framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil)
// f.EnsureIngress(ing)
// f.WaitForNginxServer(host,
// func(server string) bool {
// return strings.Contains(server, "server_name foo")
// })
// resp, _, errs := gorequest.New().
// Get(f.IngressController.HTTPURL).
// Set("Host", host).
// End()
// Expect(errs).To(BeNil())
// Expect(resp.StatusCode).Should(Equal(http.StatusOK))
// err := framework.UpdateIngress(f.KubeClientSet, f.IngressController.Namespace, host, func(ingress *extensions.Ingress) error {
// ingress.Spec.Rules = nil
// ingress.Spec.Backend = &extensions.IngressBackend{
// ServiceName: "http-svc",
// ServicePort: intstr.FromInt(80),
// }
// return nil
// })
// Expect(err).ToNot(HaveOccurred())
// f.WaitForNginxConfiguration(func(cfg string) bool {
// return !strings.Contains(cfg, "server_name foo") &&
// !strings.Contains(cfg, `set $ingress_name "foo"`) &&
// !strings.Contains(cfg, `set $service_name "http-svc"`)
// })
// resp, _, errs = gorequest.New().
// Get(f.IngressController.HTTPURL).
// Set("Host", host).
// End()
// Expect(errs).To(BeNil())
// Expect(resp.StatusCode).Should(Equal(http.StatusNotFound))
// })
})