From ae479a2451c6d879c717145462335b4c842d0626 Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Thu, 14 May 2020 12:06:56 +0300 Subject: [PATCH] Add ingress class support for Contour Add `-ingress-class` command flag. When set, the specified class is used to annotate the generated HTTPProxy objects. --- cmd/flagger/main.go | 8 +++++--- pkg/controller/scheduler_daemonset_fixture_test.go | 2 +- pkg/controller/scheduler_deployment_fixture_test.go | 2 +- pkg/router/contour.go | 9 +++++++++ pkg/router/contour_test.go | 2 ++ pkg/router/factory.go | 3 +++ 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/cmd/flagger/main.go b/cmd/flagger/main.go index cfb534431..540179a80 100644 --- a/cmd/flagger/main.go +++ b/cmd/flagger/main.go @@ -54,6 +54,7 @@ var ( meshProvider string selectorLabels string ingressAnnotationsPrefix string + ingressClass string enableLeaderElection bool leaderElectionNamespace string enableConfigTracking bool @@ -77,9 +78,10 @@ func init() { flag.BoolVar(&zapReplaceGlobals, "zap-replace-globals", false, "Whether to change the logging level of the global zap logger.") flag.StringVar(&zapEncoding, "zap-encoding", "json", "Zap logger encoding.") flag.StringVar(&namespace, "namespace", "", "Namespace that flagger would watch canary object.") - flag.StringVar(&meshProvider, "mesh-provider", "istio", "Service mesh provider, can be istio, linkerd, appmesh, supergloo, nginx or smi.") + flag.StringVar(&meshProvider, "mesh-provider", "istio", "Service mesh provider, can be istio, linkerd, appmesh, contour, gloo or nginx.") flag.StringVar(&selectorLabels, "selector-labels", "app,name,app.kubernetes.io/name", "List of pod labels that Flagger uses to create pod selectors.") - flag.StringVar(&ingressAnnotationsPrefix, "ingress-annotations-prefix", "nginx.ingress.kubernetes.io", "Annotations prefix for ingresses.") + flag.StringVar(&ingressAnnotationsPrefix, "ingress-annotations-prefix", "nginx.ingress.kubernetes.io", "Annotations prefix for NGINX ingresses.") + flag.StringVar(&ingressClass, "ingress-class", "", "Ingress class used for annotating HTTPProxy objects.") flag.BoolVar(&enableLeaderElection, "enable-leader-election", false, "Enable leader election.") flag.StringVar(&leaderElectionNamespace, "leader-election-namespace", "kube-system", "Namespace used to create the leader election config map.") flag.BoolVar(&enableConfigTracking, "enable-config-tracking", true, "Enable secrets and configmaps tracking.") @@ -169,7 +171,7 @@ func main() { // start HTTP server go server.ListenAndServe(port, 3*time.Second, logger, stopCh) - routerFactory := router.NewFactory(cfg, kubeClient, flaggerClient, ingressAnnotationsPrefix, logger, meshClient) + routerFactory := router.NewFactory(cfg, kubeClient, flaggerClient, ingressAnnotationsPrefix, ingressClass, logger, meshClient) var configTracker canary.Tracker if enableConfigTracking { diff --git a/pkg/controller/scheduler_daemonset_fixture_test.go b/pkg/controller/scheduler_daemonset_fixture_test.go index 02d8778cb..ac620814f 100644 --- a/pkg/controller/scheduler_daemonset_fixture_test.go +++ b/pkg/controller/scheduler_daemonset_fixture_test.go @@ -76,7 +76,7 @@ func newDaemonSetFixture(c *flaggerv1.Canary) daemonSetFixture { } // init router - rf := router.NewFactory(nil, kubeClient, flaggerClient, "annotationsPrefix", logger, flaggerClient) + rf := router.NewFactory(nil, kubeClient, flaggerClient, "annotationsPrefix", "", logger, flaggerClient) // init observer observerFactory, _ := observers.NewFactory("fake") diff --git a/pkg/controller/scheduler_deployment_fixture_test.go b/pkg/controller/scheduler_deployment_fixture_test.go index fadf8366e..d1bfb3ba2 100644 --- a/pkg/controller/scheduler_deployment_fixture_test.go +++ b/pkg/controller/scheduler_deployment_fixture_test.go @@ -104,7 +104,7 @@ func newDeploymentFixture(c *flaggerv1.Canary) fixture { } // init router - rf := router.NewFactory(nil, kubeClient, flaggerClient, "annotationsPrefix", logger, flaggerClient) + rf := router.NewFactory(nil, kubeClient, flaggerClient, "annotationsPrefix", "", logger, flaggerClient) // init observer observerFactory, _ := observers.NewFactory("fake") diff --git a/pkg/router/contour.go b/pkg/router/contour.go index bf3079af9..a2e7b6b04 100644 --- a/pkg/router/contour.go +++ b/pkg/router/contour.go @@ -23,10 +23,13 @@ type ContourRouter struct { contourClient clientset.Interface flaggerClient clientset.Interface logger *zap.SugaredLogger + ingressClass string } // Reconcile creates or updates the HTTP proxy func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error { + annotation := "projectcontour.io/ingress.class" + apexName, primaryName, canaryName := canary.GetServiceNames() newSpec := contourv1.HTTPProxySpec{ @@ -151,6 +154,12 @@ func (cr *ContourRouter) Reconcile(canary *flaggerv1.Canary) error { }, } + if cr.ingressClass != "" { + proxy.Annotations = map[string]string{ + annotation: cr.ingressClass, + } + } + _, err = cr.contourClient.ProjectcontourV1().HTTPProxies(canary.Namespace).Create(context.TODO(), proxy, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("HTTPProxy %s.%s create error: %w", apexName, canary.Namespace, err) diff --git a/pkg/router/contour_test.go b/pkg/router/contour_test.go index e54e70b71..abb6562d1 100644 --- a/pkg/router/contour_test.go +++ b/pkg/router/contour_test.go @@ -17,6 +17,7 @@ func TestContourRouter_Reconcile(t *testing.T) { flaggerClient: mocks.flaggerClient, contourClient: mocks.meshClient, kubeClient: mocks.kubeClient, + ingressClass: "contour", } // init @@ -31,6 +32,7 @@ func TestContourRouter_Reconcile(t *testing.T) { require.Len(t, services, 2) assert.Equal(t, uint32(100), services[0].Weight) assert.Equal(t, uint32(0), services[1].Weight) + assert.Equal(t, "contour", proxy.Annotations["projectcontour.io/ingress.class"]) // test update cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get(context.TODO(), "podinfo", metav1.GetOptions{}) diff --git a/pkg/router/factory.go b/pkg/router/factory.go index 9efcf8a6b..fed25506a 100644 --- a/pkg/router/factory.go +++ b/pkg/router/factory.go @@ -17,12 +17,14 @@ type Factory struct { meshClient clientset.Interface flaggerClient clientset.Interface ingressAnnotationsPrefix string + ingressClass string logger *zap.SugaredLogger } func NewFactory(kubeConfig *restclient.Config, kubeClient kubernetes.Interface, flaggerClient clientset.Interface, ingressAnnotationsPrefix string, + ingressClass string, logger *zap.SugaredLogger, meshClient clientset.Interface) *Factory { return &Factory{ @@ -31,6 +33,7 @@ func NewFactory(kubeConfig *restclient.Config, kubeClient kubernetes.Interface, kubeClient: kubeClient, flaggerClient: flaggerClient, ingressAnnotationsPrefix: ingressAnnotationsPrefix, + ingressClass: ingressClass, logger: logger, } }