Skip to content

Commit

Permalink
Add ingress
Browse files Browse the repository at this point in the history
  • Loading branch information
SpecialYang authored and special.fy committed Nov 2, 2022
1 parent 2e0b90f commit 21a5dac
Show file tree
Hide file tree
Showing 51 changed files with 11,877 additions and 0 deletions.
846 changes: 846 additions & 0 deletions ingress/config/ingress_config.go

Large diffs are not rendered by default.

613 changes: 613 additions & 0 deletions ingress/config/ingress_config_test.go

Large diffs are not rendered by default.

212 changes: 212 additions & 0 deletions ingress/kube/annotations/annotations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
// 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 (
networking "istio.io/api/networking/v1alpha3"
"istio.io/istio/pilot/pkg/util/sets"
listersv1 "k8s.io/client-go/listers/core/v1"
)

type GlobalContext struct {
// secret key is cluster/namespace/name
WatchedSecrets sets.Set

ClusterSecretLister map[string]listersv1.SecretLister

ClusterServiceList map[string]listersv1.ServiceLister
}

type Meta struct {
Namespace string
Name string
RawClusterId string
ClusterId string
}

// Ingress defines the valid annotations present in one NGINX Ingress.
type Ingress struct {
Meta

Cors *CorsConfig

Rewrite *RewriteConfig

Redirect *RedirectConfig

UpstreamTLS *UpstreamTLSConfig

DownstreamTLS *DownstreamTLSConfig

Canary *CanaryConfig

IPAccessControl *IPAccessControlConfig

HeaderControl *HeaderControlConfig

Timeout *TimeoutConfig

Retry *RetryConfig

LoadBalance *LoadBalanceConfig

localRateLimit *localRateLimitConfig

Fallback *FallbackConfig

Auth *AuthConfig
}

func (i *Ingress) NeedRegexMatch() bool {
if i.Rewrite == nil {
return false
}

return i.Rewrite.RewriteTarget != "" || i.Rewrite.UseRegex
}

func (i *Ingress) IsCanary() bool {
if i.Canary == nil {
return false
}

return i.Canary.Enabled
}

// CanaryKind return byHeader, byWeight
func (i *Ingress) CanaryKind() (bool, bool) {
if !i.IsCanary() {
return false, false
}

// first header, cookie
if i.Canary.Header != "" || i.Canary.Cookie != "" {
return true, false
}

// then weight
return false, true
}

func (i *Ingress) NeedTrafficPolicy() bool {
return i.UpstreamTLS != nil ||
i.LoadBalance != nil
}

func (i *Ingress) MergeHostIPAccessControlIfNotExist(ac *IPAccessControlConfig) {
if i.IPAccessControl != nil && i.IPAccessControl.Domain != nil {
return
}

if ac != nil && ac.Domain != nil {
if i.IPAccessControl == nil {
i.IPAccessControl = &IPAccessControlConfig{
Domain: ac.Domain,
}
} else {
i.IPAccessControl.Domain = ac.Domain
}
}
}

type AnnotationHandler interface {
Parser
GatewayHandler
VirtualServiceHandler
RouteHandler
TrafficPolicyHandler
}

type AnnotationHandlerManager struct {
parsers []Parser
gatewayHandlers []GatewayHandler
virtualServiceHandlers []VirtualServiceHandler
routeHandlers []RouteHandler
trafficPolicyHandlers []TrafficPolicyHandler
}

func NewAnnotationHandlerManager() AnnotationHandler {
return &AnnotationHandlerManager{
parsers: []Parser{
canary{},
cors{},
downstreamTLS{},
redirect{},
rewrite{},
upstreamTLS{},
ipAccessControl{},
headerControl{},
timeout{},
retry{},
loadBalance{},
localRateLimit{},
fallback{},
auth{},
},
gatewayHandlers: []GatewayHandler{
downstreamTLS{},
},
virtualServiceHandlers: []VirtualServiceHandler{
ipAccessControl{},
},
routeHandlers: []RouteHandler{
cors{},
redirect{},
rewrite{},
ipAccessControl{},
headerControl{},
timeout{},
retry{},
localRateLimit{},
fallback{},
},
trafficPolicyHandlers: []TrafficPolicyHandler{
upstreamTLS{},
loadBalance{},
},
}
}

func (h *AnnotationHandlerManager) Parse(annotations Annotations, config *Ingress, globalContext *GlobalContext) error {
for _, parser := range h.parsers {
_ = parser.Parse(annotations, config, globalContext)
}

return nil
}

func (h *AnnotationHandlerManager) ApplyGateway(gateway *networking.Gateway, config *Ingress) {
for _, handler := range h.gatewayHandlers {
handler.ApplyGateway(gateway, config)
}
}

func (h *AnnotationHandlerManager) ApplyVirtualServiceHandler(virtualService *networking.VirtualService, config *Ingress) {
for _, handler := range h.virtualServiceHandlers {
handler.ApplyVirtualServiceHandler(virtualService, config)
}
}

func (h *AnnotationHandlerManager) ApplyRoute(route *networking.HTTPRoute, config *Ingress) {
for _, handler := range h.routeHandlers {
handler.ApplyRoute(route, config)
}
}

func (h *AnnotationHandlerManager) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) {
for _, handler := range h.trafficPolicyHandlers {
handler.ApplyTrafficPolicy(trafficPolicy, config)
}
}
182 changes: 182 additions & 0 deletions ingress/kube/annotations/annotations_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// 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 "testing"

func TestNeedRegexMatch(t *testing.T) {
testCases := []struct {
input *Ingress
expect bool
}{
{
input: &Ingress{},
expect: false,
},
{
input: &Ingress{
Rewrite: &RewriteConfig{},
},
expect: false,
},
{
input: &Ingress{
Rewrite: &RewriteConfig{
RewriteTarget: "/test",
},
},
expect: true,
},
{
input: &Ingress{
Rewrite: &RewriteConfig{
UseRegex: true,
},
},
expect: true,
},
}

for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
if testCase.input.NeedRegexMatch() != testCase.expect {
t.Fatalf("Should be %t, but actual is %t", testCase.expect, testCase.input.NeedRegexMatch())
}
})
}
}

func TestIsCanary(t *testing.T) {
testCases := []struct {
input *Ingress
expect bool
}{
{
input: &Ingress{},
expect: false,
},
{
input: &Ingress{
Canary: &CanaryConfig{},
},
expect: false,
},
{
input: &Ingress{
Canary: &CanaryConfig{
Enabled: true,
},
},
expect: true,
},
}

for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
if testCase.input.IsCanary() != testCase.expect {
t.Fatalf("Should be %t, but actual is %t", testCase.expect, testCase.input.IsCanary())
}
})
}
}

func TestCanaryKind(t *testing.T) {
testCases := []struct {
input *Ingress
byHeader bool
byWeight bool
}{
{
input: &Ingress{},
byHeader: false,
byWeight: false,
},
{
input: &Ingress{
Canary: &CanaryConfig{},
},
byHeader: false,
byWeight: false,
},
{
input: &Ingress{
Canary: &CanaryConfig{
Enabled: true,
},
},
byHeader: false,
byWeight: true,
},
{
input: &Ingress{
Canary: &CanaryConfig{
Enabled: true,
Header: "test",
},
},
byHeader: true,
byWeight: false,
},
{
input: &Ingress{
Canary: &CanaryConfig{
Enabled: true,
Cookie: "test",
},
},
byHeader: true,
byWeight: false,
},
{
input: &Ingress{
Canary: &CanaryConfig{
Enabled: true,
Weight: 2,
},
},
byHeader: false,
byWeight: true,
},
}

for _, testCase := range testCases {
t.Run("", func(t *testing.T) {
byHeader, byWeight := testCase.input.CanaryKind()
if byHeader != testCase.byHeader {
t.Fatalf("Should be %t, but actual is %t", testCase.byHeader, byHeader)
}

if byWeight != testCase.byWeight {
t.Fatalf("Should be %t, but actual is %t", testCase.byWeight, byWeight)
}
})
}
}

func TestNeedTrafficPolicy(t *testing.T) {
config1 := &Ingress{}
if config1.NeedTrafficPolicy() {
t.Fatal("should be false")
}

config2 := &Ingress{
UpstreamTLS: &UpstreamTLSConfig{
BackendProtocol: defaultBackendProtocol,
},
}
if !config2.NeedTrafficPolicy() {
t.Fatal("should be true")
}
}
Loading

0 comments on commit 21a5dac

Please sign in to comment.