package controller import ( "testing" flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func TestController_verifyCanary(t *testing.T) { tests := []struct { name string canary flaggerv1.Canary wantErr bool }{ { name: "Gloo upstream in a different namespace should return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ UpstreamRef: &flaggerv1.CrossNamespaceObjectReference{ Name: "upstream", Namespace: "test", }, Analysis: &flaggerv1.CanaryAnalysis{}, }, }, wantErr: true, }, { name: "Gloo upstream in the same namespace is allowed", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ UpstreamRef: &flaggerv1.CrossNamespaceObjectReference{ Name: "upstream", Namespace: "default", }, Analysis: &flaggerv1.CanaryAnalysis{}, }, }, wantErr: false, }, { name: "MetricTemplate in a different namespace should return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Analysis: &flaggerv1.CanaryAnalysis{ Metrics: []flaggerv1.CanaryMetric{ { TemplateRef: &flaggerv1.CrossNamespaceObjectReference{ Name: "mt-1", Namespace: "test", }, }, }, }, }, }, wantErr: true, }, { name: "MetricTemplate in same namespace with no namespace specified should not return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Analysis: &flaggerv1.CanaryAnalysis{ Metrics: []flaggerv1.CanaryMetric{ { TemplateRef: &flaggerv1.CrossNamespaceObjectReference{ Name: "mt-1", Namespace: "", }, }, }, }, }, }, wantErr: false, }, { name: "AlertProvider in a different namespace should return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Analysis: &flaggerv1.CanaryAnalysis{ Alerts: []flaggerv1.CanaryAlert{ { ProviderRef: flaggerv1.CrossNamespaceObjectReference{ Name: "ap-1", Namespace: "test", }, }, }, }, }, }, wantErr: true, }, { name: "knative provider with non-knative service should return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Provider: "knative", TargetRef: flaggerv1.LocalObjectReference{ Kind: "Deployment", Name: "podinfo", }, Analysis: &flaggerv1.CanaryAnalysis{}, }, }, wantErr: true, }, { name: "knative service with non-knative provider should return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Provider: "istio", TargetRef: flaggerv1.LocalObjectReference{ Kind: "Service", APIVersion: "serving.knative.dev/v1", Name: "podinfo", }, Analysis: &flaggerv1.CanaryAnalysis{}, }, }, wantErr: true, }, { name: "knative service with autoscaler ref should return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Provider: "knative", AutoscalerRef: &flaggerv1.AutoscalerReference{}, TargetRef: flaggerv1.LocalObjectReference{ Kind: "Service", APIVersion: "serving.knative.dev/v1", Name: "podinfo", }, Analysis: &flaggerv1.CanaryAnalysis{}, }, }, wantErr: true, }, { name: "knative service with knative provider is okay", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Provider: "knative", TargetRef: flaggerv1.LocalObjectReference{ Kind: "Service", APIVersion: "serving.knative.dev/v1", Name: "podinfo", }, Analysis: &flaggerv1.CanaryAnalysis{}, }, }, wantErr: false, }, { name: "session affinity with same cookie names should return an error", canary: flaggerv1.Canary{ ObjectMeta: metav1.ObjectMeta{ Name: "cd-1", Namespace: "default", }, Spec: flaggerv1.CanarySpec{ Analysis: &flaggerv1.CanaryAnalysis{ SessionAffinity: &flaggerv1.SessionAffinity{ CookieName: "smth", PrimaryCookieName: "smth", }, }, }, }, wantErr: true, }, } ctrl := &Controller{ noCrossNamespaceRefs: true, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { err := ctrl.verifyCanary(&test.canary) if test.wantErr { require.Error(t, err) } }) } }