Files
higress/pkg/ingress/kube/annotations/default_backend_test.go
2022-11-10 20:53:23 +08:00

230 lines
5.6 KiB
Go

// Copyright (c) 2022 Alibaba Group Holding Ltd.
//
// 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 annotations
import (
"context"
"reflect"
"testing"
"time"
networking "istio.io/api/networking/v1alpha3"
"istio.io/istio/pilot/pkg/model"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
listerv1 "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/cache"
)
var (
normalService = &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "app",
Namespace: "test",
},
Spec: v1.ServiceSpec{
Ports: []v1.ServicePort{{
Name: "http",
Port: 80,
}},
},
}
abnormalService = &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "app",
Namespace: "foo",
},
}
)
func TestFallbackParse(t *testing.T) {
fallback := fallback{}
inputCases := []struct {
input map[string]string
expect *FallbackConfig
}{
{},
{
input: map[string]string{
buildNginxAnnotationKey(annDefaultBackend): "test/app",
},
expect: &FallbackConfig{
DefaultBackend: model.NamespacedName{
Namespace: "test",
Name: "app",
},
Port: 80,
},
},
{
input: map[string]string{
buildHigressAnnotationKey(annDefaultBackend): "app",
},
expect: &FallbackConfig{
DefaultBackend: model.NamespacedName{
Namespace: "test",
Name: "app",
},
Port: 80,
},
},
{
input: map[string]string{
buildHigressAnnotationKey(annDefaultBackend): "foo/app",
},
},
{
input: map[string]string{
buildHigressAnnotationKey(annDefaultBackend): "test/app",
buildNginxAnnotationKey(customHTTPError): "404,503",
},
expect: &FallbackConfig{
DefaultBackend: model.NamespacedName{
Namespace: "test",
Name: "app",
},
Port: 80,
customHTTPErrors: []uint32{404, 503},
},
},
{
input: map[string]string{
buildHigressAnnotationKey(annDefaultBackend): "test/app",
buildNginxAnnotationKey(customHTTPError): "404,5ac",
},
expect: &FallbackConfig{
DefaultBackend: model.NamespacedName{
Namespace: "test",
Name: "app",
},
Port: 80,
customHTTPErrors: []uint32{404},
},
},
}
for _, inputCase := range inputCases {
t.Run("", func(t *testing.T) {
config := &Ingress{
Meta: Meta{
Namespace: "test",
ClusterId: "cluster",
},
}
globalContext, cancel := initGlobalContextForService()
defer cancel()
_ = fallback.Parse(inputCase.input, config, globalContext)
if !reflect.DeepEqual(inputCase.expect, config.Fallback) {
t.Fatal("Should be equal")
}
})
}
}
func TestFallbackApplyRoute(t *testing.T) {
fallback := fallback{}
inputCases := []struct {
config *Ingress
input *networking.HTTPRoute
expect *networking.HTTPRoute
}{
{
config: &Ingress{},
input: &networking.HTTPRoute{},
expect: &networking.HTTPRoute{},
},
{
config: &Ingress{
Fallback: &FallbackConfig{
DefaultBackend: model.NamespacedName{
Namespace: "test",
Name: "app",
},
Port: 80,
customHTTPErrors: []uint32{404, 503},
},
},
input: &networking.HTTPRoute{
Name: "route",
Route: []*networking.HTTPRouteDestination{
{},
},
},
expect: &networking.HTTPRoute{
Name: "route",
InternalActiveRedirect: &networking.HTTPInternalActiveRedirect{
MaxInternalRedirects: 1,
RedirectResponseCodes: []uint32{404, 503},
AllowCrossScheme: true,
Headers: &networking.Headers{
Request: &networking.Headers_HeaderOperations{
Add: map[string]string{
FallbackInjectHeaderRouteName: "route" + FallbackRouteNameSuffix,
FallbackInjectFallbackService: "test/app",
},
},
},
RedirectUrlRewriteSpecifier: &networking.HTTPInternalActiveRedirect_RedirectUrl{
RedirectUrl: defaultRedirectUrl,
},
ForcedUseOriginalHost: true,
ForcedAddHeaderBeforeRouteMatcher: true,
},
Route: []*networking.HTTPRouteDestination{
{
FallbackClusters: []*networking.Destination{
{
Host: "app.test.svc.cluster.local",
Port: &networking.PortSelector{
Number: 80,
},
},
},
},
},
},
},
}
for _, inputCase := range inputCases {
t.Run("", func(t *testing.T) {
fallback.ApplyRoute(inputCase.input, inputCase.config)
if !reflect.DeepEqual(inputCase.input, inputCase.expect) {
t.Fatal("Should be equal")
}
})
}
}
func initGlobalContextForService() (*GlobalContext, context.CancelFunc) {
ctx, cancel := context.WithCancel(context.Background())
client := fake.NewSimpleClientset(normalService, abnormalService)
informerFactory := informers.NewSharedInformerFactory(client, time.Hour)
serviceInformer := informerFactory.Core().V1().Services()
go serviceInformer.Informer().Run(ctx.Done())
cache.WaitForCacheSync(ctx.Done(), serviceInformer.Informer().HasSynced)
return &GlobalContext{
ClusterServiceList: map[string]listerv1.ServiceLister{
"cluster": serviceInformer.Lister(),
},
}, cancel
}