Repository: fluxcd/flagger
Pull request #932 (2021-06-11 20:19:34)

gloo: copy labels from upstream
Copy the Labels over from the upstream as well as config values. This ensures that gatekeeper or OPA validations can pass.


Patch:
diff --git a/docs/gitbook/tutorials/gloo-progressive-delivery.md b/docs/gitbook/tutorials/gloo-progressive-delivery.md
index a661f0a1..f32ed976 100644
--- a/docs/gitbook/tutorials/gloo-progressive-delivery.md
+++ b/docs/gitbook/tutorials/gloo-progressive-delivery.md
@@ -160,6 +160,8 @@ spec:
           cmd: "hey -z 2m -q 5 -c 2 -host app.example.com http://gateway-proxy.gloo-system"
 ```
 
+*Note: when using upstreamRef the following fields are copied over from the original upstream: `Labels, SslConfig, CircuitBreakers, ConnectionConfig, UseHttp2, InitialStreamWindowSize`*
+
 Save the above resource as podinfo-canary.yaml and then apply it:
 
 ```bash
diff --git a/pkg/apis/gloo/gloo/v1/types.go b/pkg/apis/gloo/gloo/v1/types.go
index 7348f338..e37ba5d5 100644
--- a/pkg/apis/gloo/gloo/v1/types.go
+++ b/pkg/apis/gloo/gloo/v1/types.go
@@ -18,6 +18,7 @@ type Upstream struct {
 
 type UpstreamSpec struct {
 	Kube                        *KubeUpstream         `json:"kube,omitempty"`
+	Labels                      map[string]string     `json:"labels,omitempty"`
 	SslConfig                   *UpstreamSslConfig    `json:"sslConfig,omitempty"`
 	CircuitBreakers             *CircuitBreakerConfig `json:"circuitBreakers,omitempty"`
 	ConnectionConfig            *ConnectionConfig     `json:"connectionConfig,omitempty"`
diff --git a/pkg/apis/gloo/gloo/v1/zz_generated.deepcopy.go b/pkg/apis/gloo/gloo/v1/zz_generated.deepcopy.go
index edf42622..0b305b25 100644
--- a/pkg/apis/gloo/gloo/v1/zz_generated.deepcopy.go
+++ b/pkg/apis/gloo/gloo/v1/zz_generated.deepcopy.go
@@ -294,6 +294,13 @@ func (in *UpstreamSpec) DeepCopyInto(out *UpstreamSpec) {
 		*out = new(KubeUpstream)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
 	if in.SslConfig != nil {
 		in, out := &in.SslConfig, &out.SslConfig
 		*out = new(UpstreamSslConfig)
diff --git a/pkg/router/gloo.go b/pkg/router/gloo.go
index e5dc9bcd..823a16b5 100644
--- a/pkg/router/gloo.go
+++ b/pkg/router/gloo.go
@@ -38,10 +38,11 @@ import (
 
 // GlooRouter is managing Gloo route tables
 type GlooRouter struct {
-	kubeClient    kubernetes.Interface
-	glooClient    clientset.Interface
-	flaggerClient clientset.Interface
-	logger        *zap.SugaredLogger
+	kubeClient         kubernetes.Interface
+	glooClient         clientset.Interface
+	flaggerClient      clientset.Interface
+	logger             *zap.SugaredLogger
+	includeLabelPrefix []string
 }
 
 // Reconcile creates or updates the Gloo Edge route table
@@ -276,6 +277,7 @@ func (gr *GlooRouter) getGlooUpstreamKubeService(canary *flaggerv1.Canary, svc *
 	if glooUpstreamWithConfig != nil {
 		configSpec := glooUpstreamWithConfig.Spec
 		upstreamSpec = gloov1.UpstreamSpec{
+			Labels:                      configSpec.Labels,
 			SslConfig:                   configSpec.SslConfig,
 			CircuitBreakers:             configSpec.CircuitBreakers,
 			ConnectionConfig:            configSpec.ConnectionConfig,
@@ -293,10 +295,13 @@ func (gr *GlooRouter) getGlooUpstreamKubeService(canary *flaggerv1.Canary, svc *
 		Selector:         svc.Spec.Selector,
 	}
 
+	upstreamLabels := includeLabelsByPrefix(upstreamSpec.Labels, gr.includeLabelPrefix)
+
 	return &gloov1.Upstream{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      upstreamName,
 			Namespace: canary.Namespace,
+			Labels:    upstreamLabels,
 			OwnerReferences: []metav1.OwnerReference{
 				*metav1.NewControllerRef(canary, schema.GroupVersionKind{
 					Group:   flaggerv1.SchemeGroupVersion.Group,
diff --git a/pkg/router/util.go b/pkg/router/util.go
new file mode 100644
index 00000000..e2bb04ee
--- /dev/null
+++ b/pkg/router/util.go
@@ -0,0 +1,19 @@
+package router
+
+import (
+	"strings"
+)
+
+func includeLabelsByPrefix(labels map[string]string, includeLabelPrefixes []string) map[string]string {
+	filteredLabels := make(map[string]string)
+	for key, value := range labels {
+		for _, includeLabelPrefix := range includeLabelPrefixes {
+			if includeLabelPrefix == "*" || strings.HasPrefix(key, includeLabelPrefix) {
+				filteredLabels[key] = value
+				break
+			}
+		}
+	}
+
+	return filteredLabels
+}


Test patch:
diff --git a/pkg/router/util_test.go b/pkg/router/util_test.go
new file mode 100644
index 00000000..2069810e
--- /dev/null
+++ b/pkg/router/util_test.go
@@ -0,0 +1,57 @@
+/*
+Copyright 2020 The Flux 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 router
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestIncludeLabelsByPrefix(t *testing.T) {
+	labels := map[string]string{
+		"foo":   "foo-value",
+		"bar":   "bar-value",
+		"lorem": "ipsum",
+	}
+	includeLabelPrefix := []string{"foo", "lor"}
+
+	filteredLabels := includeLabelsByPrefix(labels, includeLabelPrefix)
+
+	assert.Equal(t, filteredLabels, map[string]string{
+		"foo":   "foo-value",
+		"lorem": "ipsum",
+		// bar excluded
+	})
+}
+
+func TestIncludeLabelsByPrefixWithWildcard(t *testing.T) {
+	labels := map[string]string{
+		"foo":   "foo-value",
+		"bar":   "bar-value",
+		"lorem": "ipsum",
+	}
+	includeLabelPrefix := []string{"*"}
+
+	filteredLabels := includeLabelsByPrefix(labels, includeLabelPrefix)
+
+	assert.Equal(t, filteredLabels, map[string]string{
+		"foo":   "foo-value",
+		"bar":   "bar-value",
+		"lorem": "ipsum",
+	})
+}