Skip to content

Commit

Permalink
chore(refactor): annotations handle (#1245)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlinsRan committed Aug 30, 2022
1 parent 9dafeb8 commit 0b999ec
Show file tree
Hide file tree
Showing 18 changed files with 417 additions and 176 deletions.
46 changes: 30 additions & 16 deletions pkg/providers/ingress/translation/annotations.go
Expand Up @@ -15,40 +15,54 @@
package translation

import (
"github.com/imdario/mergo"
"go.uber.org/zap"

"github.com/apache/apisix-ingress-controller/pkg/log"
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/pluginconfig"
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/plugins"
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/regex"
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations/websocket"
apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

// Structure extracted by Ingress Resource
type Ingress struct {
Plugins apisix.Plugins
UseRegex bool
EnableWebSocket bool
PluginConfigName string
}

var (
_handlers = []annotations.Handler{
annotations.NewCorsHandler(),
annotations.NewIPRestrictionHandler(),
annotations.NewRewriteHandler(),
annotations.NewRedirectHandler(),
annotations.NewForwardAuthHandler(),
annotations.NewBasicAuthHandler(),
annotations.NewKeyAuthHandler(),
annotations.NewCSRFHandler(),
_parsers = map[string]annotations.IngressAnnotationsParser{
"Plugins": plugins.NewParser(),
"UseRegex": regex.NewParser(),
"EnableWebSocket": websocket.NewParser(),
"PluginConfigName": pluginconfig.NewParser(),
}
)

func (t *translator) TranslateAnnotations(anno map[string]string) apisix.Plugins {
func (t *translator) TranslateAnnotations(anno map[string]string) *Ingress {
ing := &Ingress{}
extractor := annotations.NewExtractor(anno)
plugins := make(apisix.Plugins)
for _, handler := range _handlers {
out, err := handler.Handle(extractor)
data := make(map[string]interface{})
for name, parser := range _parsers {
out, err := parser.Parse(extractor)
if err != nil {
log.Warnw("failed to handle annotations",
log.Warnw("failed to parse annotations",
zap.Error(err),
)
continue
}
if out != nil {
plugins[handler.PluginName()] = out
data[name] = out
}
}
return plugins
err := mergo.MapWithOverwrite(ing, data)
if err != nil {
log.Errorw("unexpected error merging extracted annotations", zap.Error(err))
}
return ing
}
@@ -0,0 +1,29 @@
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 pluginconfig

import (
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
)

type pluginconfig struct{}

func NewParser() annotations.IngressAnnotationsParser {
return &pluginconfig{}
}

func (w *pluginconfig) Parse(e annotations.Extractor) (interface{}, error) {
return e.GetStringAnnotation(annotations.AnnotationsPluginConfigName), nil
}
Expand Up @@ -12,31 +12,27 @@
// 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
package plugins

import (
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

const (
// auth-type: keyAuth | basicAuth
_authType = AnnotationsPrefix + "auth-type"
)

type basicAuth struct{}

// NewkeyBasicHandler creates a handler to convert
// annotations about basicAuth control to APISIX basic-auth plugin.
func NewBasicAuthHandler() Handler {
func NewBasicAuthHandler() PluginAnnotationsHandler {
return &basicAuth{}
}

func (b *basicAuth) PluginName() string {
return "basic-auth"
}

func (b *basicAuth) Handle(e Extractor) (interface{}, error) {
if e.GetStringAnnotation(_authType) != "basicAuth" {
func (b *basicAuth) Handle(e annotations.Extractor) (interface{}, error) {
if e.GetStringAnnotation(annotations.AnnotationsAuthType) != "basicAuth" {
return nil, nil
}
plugin := apisixv1.BasicAuthConfig{}
Expand All @@ -47,16 +43,16 @@ type keyAuth struct{}

// NewkeyAuthHandler creates a handler to convert
// annotations about keyAuth control to APISIX key-auth plugin.
func NewKeyAuthHandler() Handler {
func NewKeyAuthHandler() PluginAnnotationsHandler {
return &keyAuth{}
}

func (k *keyAuth) PluginName() string {
return "key-auth"
}

func (k *keyAuth) Handle(e Extractor) (interface{}, error) {
if e.GetStringAnnotation(_authType) != "keyAuth" {
func (k *keyAuth) Handle(e annotations.Extractor) (interface{}, error) {
if e.GetStringAnnotation(annotations.AnnotationsAuthType) != "keyAuth" {
return nil, nil
}
plugin := apisixv1.KeyAuthConfig{}
Expand Down
Expand Up @@ -12,38 +12,32 @@
// 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
package plugins

import (
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

const (
_enableCors = AnnotationsPrefix + "enable-cors"
_corsAllowOrigin = AnnotationsPrefix + "cors-allow-origin"
_corsAllowHeaders = AnnotationsPrefix + "cors-allow-headers"
_corsAllowMethods = AnnotationsPrefix + "cors-allow-methods"
)

type cors struct{}

// NewCorsHandler creates a handler to convert annotations about
// CORS to APISIX cors plugin.
func NewCorsHandler() Handler {
func NewCorsHandler() PluginAnnotationsHandler {
return &cors{}
}

func (c *cors) PluginName() string {
return "cors"
}

func (c *cors) Handle(e Extractor) (interface{}, error) {
if !e.GetBoolAnnotation(_enableCors) {
func (c *cors) Handle(e annotations.Extractor) (interface{}, error) {
if !e.GetBoolAnnotation(annotations.AnnotationsEnableCors) {
return nil, nil
}
return &apisixv1.CorsConfig{
AllowOrigins: e.GetStringAnnotation(_corsAllowOrigin),
AllowMethods: e.GetStringAnnotation(_corsAllowMethods),
AllowHeaders: e.GetStringAnnotation(_corsAllowHeaders),
AllowOrigins: e.GetStringAnnotation(annotations.AnnotationsCorsAllowOrigin),
AllowMethods: e.GetStringAnnotation(annotations.AnnotationsCorsAllowMethods),
AllowHeaders: e.GetStringAnnotation(annotations.AnnotationsCorsAllowHeaders),
}, nil
}
Expand Up @@ -12,25 +12,26 @@
// 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
package plugins

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

func TestCorsHandler(t *testing.T) {
annotations := map[string]string{
_enableCors: "true",
_corsAllowHeaders: "abc,def",
_corsAllowOrigin: "https://a.com",
_corsAllowMethods: "GET,HEAD",
anno := map[string]string{
annotations.AnnotationsEnableCors: "true",
annotations.AnnotationsCorsAllowHeaders: "abc,def",
annotations.AnnotationsCorsAllowOrigin: "https://a.com",
annotations.AnnotationsCorsAllowMethods: "GET,HEAD",
}
p := NewCorsHandler()
out, err := p.Handle(NewExtractor(annotations))
out, err := p.Handle(annotations.NewExtractor(anno))
assert.Nil(t, err, "checking given error")
config := out.(*apisixv1.CorsConfig)
assert.Equal(t, "abc,def", config.AllowHeaders)
Expand All @@ -39,8 +40,8 @@ func TestCorsHandler(t *testing.T) {

assert.Equal(t, "cors", p.PluginName())

annotations[_enableCors] = "false"
out, err = p.Handle(NewExtractor(annotations))
anno[annotations.AnnotationsEnableCors] = "false"
out, err = p.Handle(annotations.NewExtractor(anno))
assert.Nil(t, err, "checking given error")
assert.Nil(t, out, "checking given output")
}
Expand Up @@ -12,35 +12,31 @@
// 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
package plugins

import (
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

const (
_enableCsrf = AnnotationsPrefix + "enable-csrf"
_csrfKey = AnnotationsPrefix + "csrf-key"
)

type csrf struct{}

// NewCSRFHandler creates a handler to convert annotations about
// CSRF to APISIX csrf plugin.
func NewCSRFHandler() Handler {
func NewCSRFHandler() PluginAnnotationsHandler {
return &csrf{}
}

func (c *csrf) PluginName() string {
return "csrf"
}

func (c *csrf) Handle(e Extractor) (interface{}, error) {
if !e.GetBoolAnnotation(_enableCsrf) {
func (c *csrf) Handle(e annotations.Extractor) (interface{}, error) {
if !e.GetBoolAnnotation(annotations.AnnotationsEnableCsrf) {
return nil, nil
}
var plugin apisixv1.CSRFConfig
plugin.Key = e.GetStringAnnotation(_csrfKey)
plugin.Key = e.GetStringAnnotation(annotations.AnnotationsCsrfKey)
if plugin.Key != "" {
return &plugin, nil
}
Expand Down
Expand Up @@ -12,45 +12,38 @@
// 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
package plugins

import (
"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

const (
_forwardAuthURI = AnnotationsPrefix + "auth-uri"
_forwardAuthSSLVerify = AnnotationsPrefix + "auth-ssl-verify"
_forwardAuthRequestHeaders = AnnotationsPrefix + "auth-request-headers"
_forwardAuthUpstreamHeaders = AnnotationsPrefix + "auth-upstream-headers"
_forwardAuthClientHeaders = AnnotationsPrefix + "auth-client-headers"
)

type forwardAuth struct{}

// NewForwardAuthHandler creates a handler to convert
// annotations about forward authentication to APISIX forward-auth plugin.
func NewForwardAuthHandler() Handler {
func NewForwardAuthHandler() PluginAnnotationsHandler {
return &forwardAuth{}
}

func (i *forwardAuth) PluginName() string {
return "forward-auth"
}

func (i *forwardAuth) Handle(e Extractor) (interface{}, error) {
uri := e.GetStringAnnotation(_forwardAuthURI)
func (i *forwardAuth) Handle(e annotations.Extractor) (interface{}, error) {
uri := e.GetStringAnnotation(annotations.AnnotationsForwardAuthURI)
sslVerify := true
if e.GetStringAnnotation(_forwardAuthSSLVerify) == "false" {
if e.GetStringAnnotation(annotations.AnnotationsForwardAuthSSLVerify) == "false" {
sslVerify = false
}
if len(uri) > 0 {
return &apisixv1.ForwardAuthConfig{
URI: uri,
SSLVerify: sslVerify,
RequestHeaders: e.GetStringsAnnotation(_forwardAuthRequestHeaders),
UpstreamHeaders: e.GetStringsAnnotation(_forwardAuthUpstreamHeaders),
ClientHeaders: e.GetStringsAnnotation(_forwardAuthClientHeaders),
RequestHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthRequestHeaders),
UpstreamHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthUpstreamHeaders),
ClientHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthClientHeaders),
}, nil
}

Expand Down
Expand Up @@ -12,25 +12,26 @@
// 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
package plugins

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/apache/apisix-ingress-controller/pkg/providers/ingress/translation/annotations"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

func TestForwardAuthHandler(t *testing.T) {
annotations := map[string]string{
_forwardAuthURI: "http://127.0.0.1:9080",
_forwardAuthRequestHeaders: "Authorization",
_forwardAuthClientHeaders: "Location",
_forwardAuthUpstreamHeaders: "X-User-ID",
anno := map[string]string{
annotations.AnnotationsForwardAuthURI: "http://127.0.0.1:9080",
annotations.AnnotationsForwardAuthRequestHeaders: "Authorization",
annotations.AnnotationsForwardAuthClientHeaders: "Location",
annotations.AnnotationsForwardAuthUpstreamHeaders: "X-User-ID",
}
p := NewForwardAuthHandler()
out, err := p.Handle(NewExtractor(annotations))
out, err := p.Handle(annotations.NewExtractor(anno))
assert.Nil(t, err, "checking given error")
config := out.(*apisixv1.ForwardAuthConfig)
assert.Equal(t, "http://127.0.0.1:9080", config.URI)
Expand All @@ -40,14 +41,14 @@ func TestForwardAuthHandler(t *testing.T) {
assert.Equal(t, true, config.SSLVerify)
assert.Equal(t, "forward-auth", p.PluginName())

annotations[_forwardAuthSSLVerify] = "false"
out, err = p.Handle(NewExtractor(annotations))
anno[annotations.AnnotationsForwardAuthSSLVerify] = "false"
out, err = p.Handle(annotations.NewExtractor(anno))
assert.Nil(t, err, "checking given error")
config = out.(*apisixv1.ForwardAuthConfig)
assert.Equal(t, false, config.SSLVerify)

annotations[_forwardAuthURI] = ""
out, err = p.Handle(NewExtractor(annotations))
anno[annotations.AnnotationsForwardAuthURI] = ""
out, err = p.Handle(annotations.NewExtractor(anno))
assert.Nil(t, err, "checking given error")
assert.Nil(t, out, "checking given output")
}

0 comments on commit 0b999ec

Please sign in to comment.