mirror of
https://github.com/fluxcd/flagger.git
synced 2026-03-03 02:00:18 +00:00
Signed-off-by: Sanskar Jaiswal <sanskar.jaiswal@weave.works> Co-authored-by: wucg <wucg@trip.com>
193 lines
7.0 KiB
Go
193 lines
7.0 KiB
Go
/*
|
|
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 (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
func TestAppmeshRouter_Reconcile(t *testing.T) {
|
|
mocks := newFixture(nil)
|
|
router := &AppMeshRouter{
|
|
logger: mocks.logger,
|
|
flaggerClient: mocks.flaggerClient,
|
|
appmeshClient: mocks.meshClient,
|
|
kubeClient: mocks.kubeClient,
|
|
}
|
|
|
|
err := router.Reconcile(mocks.appmeshCanary)
|
|
require.NoError(t, err)
|
|
|
|
// check virtual service
|
|
vsName := fmt.Sprintf("%s.%s", mocks.appmeshCanary.Spec.TargetRef.Name, mocks.appmeshCanary.Namespace)
|
|
vs, err := router.appmeshClient.AppmeshV1beta1().VirtualServices("default").Get(context.TODO(), vsName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, mocks.appmeshCanary.Spec.Service.MeshName, vs.Spec.MeshName)
|
|
assert.Len(t, vs.Spec.Routes[0].Http.Action.WeightedTargets, 2)
|
|
|
|
// check canary virtual service
|
|
vsCanaryName := fmt.Sprintf("%s-canary.%s", mocks.appmeshCanary.Spec.TargetRef.Name, mocks.appmeshCanary.Namespace)
|
|
vsCanary, err := router.appmeshClient.AppmeshV1beta1().VirtualServices("default").Get(context.TODO(), vsCanaryName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
|
|
// check if the canary virtual service routes all traffic to the canary virtual node
|
|
target := vsCanary.Spec.Routes[0].Http.Action.WeightedTargets[0]
|
|
canaryVirtualNodeName := fmt.Sprintf("%s-canary", mocks.appmeshCanary.Spec.TargetRef.Name)
|
|
assert.Equal(t, canaryVirtualNodeName, target.VirtualNodeName)
|
|
assert.Equal(t, int64(100), target.Weight)
|
|
|
|
// check virtual node
|
|
vnName := mocks.appmeshCanary.Spec.TargetRef.Name
|
|
vn, err := router.appmeshClient.AppmeshV1beta1().VirtualNodes("default").Get(context.TODO(), vnName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, vn.Spec.Logging)
|
|
|
|
primaryDNS := fmt.Sprintf("%s-primary.%s", mocks.appmeshCanary.Spec.TargetRef.Name, mocks.appmeshCanary.Namespace)
|
|
assert.Equal(t, primaryDNS, vn.Spec.ServiceDiscovery.Dns.HostName)
|
|
|
|
// test backends update
|
|
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get(context.TODO(), "appmesh", metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
|
|
cdClone := cd.DeepCopy()
|
|
hosts := cdClone.Spec.Service.Backends
|
|
hosts = append(hosts, "test.example.com")
|
|
cdClone.Spec.Service.Backends = hosts
|
|
canary, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(context.TODO(), cdClone, metav1.UpdateOptions{})
|
|
require.NoError(t, err)
|
|
|
|
// apply change
|
|
err = router.Reconcile(canary)
|
|
require.NoError(t, err)
|
|
|
|
// verify
|
|
vnCanaryName := fmt.Sprintf("%s-canary", mocks.appmeshCanary.Spec.TargetRef.Name)
|
|
vnCanary, err := router.appmeshClient.AppmeshV1beta1().VirtualNodes("default").Get(context.TODO(), vnCanaryName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
require.Len(t, vnCanary.Spec.Backends, 2)
|
|
|
|
// test weight update
|
|
vsClone := vs.DeepCopy()
|
|
vsClone.Spec.Routes[0].Http.Action.WeightedTargets[0].Weight = 50
|
|
vsClone.Spec.Routes[0].Http.Action.WeightedTargets[1].Weight = 50
|
|
vs, err = mocks.meshClient.AppmeshV1beta1().VirtualServices("default").Update(context.TODO(), vsClone, metav1.UpdateOptions{})
|
|
require.NoError(t, err)
|
|
|
|
// apply change
|
|
err = router.Reconcile(canary)
|
|
require.NoError(t, err)
|
|
|
|
vs, err = router.appmeshClient.AppmeshV1beta1().VirtualServices("default").Get(context.TODO(), vsName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(50), vs.Spec.Routes[0].Http.Action.WeightedTargets[0].Weight)
|
|
|
|
// test URI update
|
|
vsClone = vs.DeepCopy()
|
|
vsClone.Spec.Routes[0].Http.Match.Prefix = "api"
|
|
vs, err = mocks.meshClient.AppmeshV1beta1().VirtualServices("default").Update(context.TODO(), vsClone, metav1.UpdateOptions{})
|
|
require.NoError(t, err)
|
|
|
|
// apply change
|
|
err = router.Reconcile(canary)
|
|
require.NoError(t, err)
|
|
vs, err = router.appmeshClient.AppmeshV1beta1().VirtualServices("default").Get(context.TODO(), vsName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "/", vs.Spec.Routes[0].Http.Match.Prefix)
|
|
}
|
|
|
|
func TestAppmeshRouter_GetSetRoutes(t *testing.T) {
|
|
mocks := newFixture(nil)
|
|
router := &AppMeshRouter{
|
|
logger: mocks.logger,
|
|
flaggerClient: mocks.flaggerClient,
|
|
appmeshClient: mocks.meshClient,
|
|
kubeClient: mocks.kubeClient,
|
|
}
|
|
|
|
err := router.Reconcile(mocks.appmeshCanary)
|
|
require.NoError(t, err)
|
|
|
|
err = router.SetRoutes(mocks.appmeshCanary, 60, 40, false)
|
|
require.NoError(t, err)
|
|
|
|
p, c, m, err := router.GetRoutes(mocks.appmeshCanary)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 60, p)
|
|
assert.Equal(t, 40, c)
|
|
assert.False(t, m)
|
|
}
|
|
|
|
func TestAppmeshRouter_ABTest(t *testing.T) {
|
|
mocks := newFixture(nil)
|
|
router := &AppMeshRouter{
|
|
logger: mocks.logger,
|
|
flaggerClient: mocks.flaggerClient,
|
|
appmeshClient: mocks.meshClient,
|
|
kubeClient: mocks.kubeClient,
|
|
}
|
|
|
|
err := router.Reconcile(mocks.abtest)
|
|
require.NoError(t, err)
|
|
|
|
// check virtual service
|
|
vsName := fmt.Sprintf("%s.%s", mocks.abtest.Spec.TargetRef.Name, mocks.abtest.Namespace)
|
|
vs, err := router.appmeshClient.AppmeshV1beta1().VirtualServices("default").Get(context.TODO(), vsName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
|
|
// check virtual service
|
|
assert.Len(t, vs.Spec.Routes, 2)
|
|
|
|
// check headers
|
|
assert.GreaterOrEqual(t, len(vs.Spec.Routes[0].Http.Match.Headers), 1, "Got no http match headers")
|
|
assert.Equal(t, "x-user-type", vs.Spec.Routes[0].Http.Match.Headers[0].Name)
|
|
assert.Equal(t, "test", *vs.Spec.Routes[0].Http.Match.Headers[0].Match.Exact)
|
|
}
|
|
|
|
func TestAppmeshRouter_Gateway(t *testing.T) {
|
|
mocks := newFixture(nil)
|
|
router := &AppMeshRouter{
|
|
logger: mocks.logger,
|
|
flaggerClient: mocks.flaggerClient,
|
|
appmeshClient: mocks.meshClient,
|
|
kubeClient: mocks.kubeClient,
|
|
}
|
|
|
|
err := router.Reconcile(mocks.appmeshCanary)
|
|
require.NoError(t, err)
|
|
|
|
// check virtual service
|
|
vsName := fmt.Sprintf("%s.%s", mocks.appmeshCanary.Spec.TargetRef.Name, mocks.appmeshCanary.Namespace)
|
|
vs, err := router.appmeshClient.AppmeshV1beta1().VirtualServices("default").Get(context.TODO(), vsName, metav1.GetOptions{})
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, "true", vs.Annotations["gateway.appmesh.k8s.aws/expose"])
|
|
assert.True(t, strings.Contains(vs.Annotations["gateway.appmesh.k8s.aws/domain"], mocks.appmeshCanary.Spec.Service.Hosts[0]))
|
|
assert.Equal(t, mocks.appmeshCanary.Spec.Service.Timeout, vs.Annotations["gateway.appmesh.k8s.aws/timeout"])
|
|
|
|
retries := vs.Annotations["gateway.appmesh.k8s.aws/retries"]
|
|
assert.Equal(t, strconv.Itoa(mocks.appmeshCanary.Spec.Service.Retries.Attempts), retries)
|
|
}
|