Skip to content

Commit

Permalink
feat: add ApisixPluginConfig translator (apache#638)
Browse files Browse the repository at this point in the history
  • Loading branch information
neverCase committed Dec 9, 2021
1 parent 413e7ca commit ebfa98e
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 26 deletions.
70 changes: 70 additions & 0 deletions pkg/kube/translation/apisix_pluginconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// 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 translation

import (
"github.com/apache/apisix-ingress-controller/pkg/id"
configv2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta2"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)

func (t *translator) translatePluginConfig(namespace, name string, plugins apisixv1.Plugins) (*apisixv1.PluginConfig, error) {
pc, err := t.TranslatePluginConfig(namespace, name, plugins)
if err != nil {
return nil, err
}
pc.Name = apisixv1.ComposePluginConfigName(namespace, name)
pc.ID = id.GenID(pc.Name)
return pc, nil
}

func (t *translator) TranslatePluginConfig(namespace, name string, plugins apisixv1.Plugins) (*apisixv1.PluginConfig, error) {
pc := apisixv1.NewDefaultPluginConfig()
pc.Plugins = plugins
return pc, nil
}

// TranslatePluginConfigV2beta2 temporarily
func (t *translator) TranslatePluginConfigV2beta2(apc *configv2beta2.ApisixPluginConfig) (*TranslateContext, error) {
ctx := defaultEmptyTranslateContext()
if err := t.translatePluginConfigV2beta2(ctx, apc); err != nil {
return nil, err
}
return ctx, nil
}

// translatePluginConfigV2beta2 temporarily
func (t *translator) translatePluginConfigV2beta2(ctx *TranslateContext, apc *configv2beta2.ApisixPluginConfig) error {
//pluginMap := make(apisixv1.Plugins)
// add route plugins
//for _, plugin := range apc.Spec.Plugins {
//
// if !plugin.Enable {
// continue
// }
// if plugin.Config != nil {
// pluginMap[plugin.Name] = plugin.Config
// } else {
// pluginMap[plugin.Name] = make(map[string]interface{})
// }
//}
return nil
}

// TranslatePluginConfigV2beta2NotStrictly temporarily
func (t *translator) TranslatePluginConfigV2beta2NotStrictly(*configv2beta2.ApisixPluginConfig) (*TranslateContext, error) {
ctx := defaultEmptyTranslateContext()
return ctx, nil
}
15 changes: 15 additions & 0 deletions pkg/kube/translation/apisix_pluginconfig_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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 translation
48 changes: 30 additions & 18 deletions pkg/kube/translation/apisix_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ import (
//}

func (t *translator) TranslateRouteV2beta1(ar *configv2beta1.ApisixRoute) (*TranslateContext, error) {
ctx := &TranslateContext{
upstreamMap: make(map[string]struct{}),
}
ctx := defaultEmptyTranslateContext()

if err := t.translateHTTPRouteV2beta1(ctx, ar); err != nil {
return nil, err
Expand All @@ -149,9 +147,7 @@ func (t *translator) TranslateRouteV2beta1(ar *configv2beta1.ApisixRoute) (*Tran
}

func (t *translator) TranslateRouteV2beta1NotStrictly(ar *configv2beta1.ApisixRoute) (*TranslateContext, error) {
ctx := &TranslateContext{
upstreamMap: make(map[string]struct{}),
}
ctx := defaultEmptyTranslateContext()

if err := t.translateHTTPRouteV2beta1NotStrictly(ctx, ar); err != nil {
return nil, err
Expand Down Expand Up @@ -246,6 +242,7 @@ func (t *translator) translateHTTPRouteV2beta1(ctx *TranslateContext, ar *config
route.UpstreamId = id.GenID(upstreamName)
route.EnableWebsocket = part.Websocket
route.Plugins = pluginMap
pluginConfigName := apisixv1.ComposePluginConfigName(ar.Namespace, backend.ServiceName)

if len(backends) > 0 {
weight := _defaultWeight
Expand All @@ -272,14 +269,19 @@ func (t *translator) translateHTTPRouteV2beta1(ctx *TranslateContext, ar *config
}
ctx.addUpstream(ups)
}
if !ctx.checkPluginConfigExist(pluginConfigName) {
pc, err := t.translatePluginConfig(ar.Namespace, backend.ServiceName, pluginMap)
if err != nil {
return err
}
ctx.addPluginConfig(pc)
}
}
return nil
}

func (t *translator) TranslateRouteV2beta2(ar *configv2beta2.ApisixRoute) (*TranslateContext, error) {
ctx := &TranslateContext{
upstreamMap: make(map[string]struct{}),
}
ctx := defaultEmptyTranslateContext()

if err := t.translateHTTPRouteV2beta2(ctx, ar); err != nil {
return nil, err
Expand All @@ -291,9 +293,7 @@ func (t *translator) TranslateRouteV2beta2(ar *configv2beta2.ApisixRoute) (*Tran
}

func (t *translator) TranslateRouteV2beta2NotStrictly(ar *configv2beta2.ApisixRoute) (*TranslateContext, error) {
ctx := &TranslateContext{
upstreamMap: make(map[string]struct{}),
}
ctx := defaultEmptyTranslateContext()

if err := t.translateHTTPRouteV2beta2NotStrictly(ctx, ar); err != nil {
return nil, err
Expand All @@ -305,9 +305,7 @@ func (t *translator) TranslateRouteV2beta2NotStrictly(ar *configv2beta2.ApisixRo
}

func (t *translator) TranslateRouteV2beta3(ar *configv2beta3.ApisixRoute) (*TranslateContext, error) {
ctx := &TranslateContext{
upstreamMap: make(map[string]struct{}),
}
ctx := defaultEmptyTranslateContext()

if err := t.translateHTTPRouteV2beta3(ctx, ar); err != nil {
return nil, err
Expand All @@ -319,9 +317,7 @@ func (t *translator) TranslateRouteV2beta3(ar *configv2beta3.ApisixRoute) (*Tran
}

func (t *translator) TranslateRouteV2beta3NotStrictly(ar *configv2beta3.ApisixRoute) (*TranslateContext, error) {
ctx := &TranslateContext{
upstreamMap: make(map[string]struct{}),
}
ctx := defaultEmptyTranslateContext()

if err := t.translateHTTPRouteV2beta3NotStrictly(ctx, ar); err != nil {
return nil, err
Expand Down Expand Up @@ -413,6 +409,7 @@ func (t *translator) translateHTTPRouteV2beta2(ctx *TranslateContext, ar *config
route.UpstreamId = id.GenID(upstreamName)
route.EnableWebsocket = part.Websocket
route.Plugins = pluginMap
pluginConfigName := apisixv1.ComposePluginConfigName(ar.Namespace, backend.ServiceName)

if len(backends) > 0 {
weight := _defaultWeight
Expand All @@ -439,6 +436,13 @@ func (t *translator) translateHTTPRouteV2beta2(ctx *TranslateContext, ar *config
}
ctx.addUpstream(ups)
}
if !ctx.checkPluginConfigExist(pluginConfigName) {
pc, err := t.translatePluginConfig(ar.Namespace, backend.ServiceName, pluginMap)
if err != nil {
return err
}
ctx.addPluginConfig(pc)
}
}
return nil
}
Expand Down Expand Up @@ -542,6 +546,7 @@ func (t *translator) translateHTTPRouteV2beta3(ctx *TranslateContext, ar *config
route.EnableWebsocket = part.Websocket
route.Plugins = pluginMap
route.Timeout = timeout
pluginConfigName := apisixv1.ComposePluginConfigName(ar.Namespace, backend.ServiceName)

if len(backends) > 0 {
weight := _defaultWeight
Expand All @@ -566,6 +571,13 @@ func (t *translator) translateHTTPRouteV2beta3(ctx *TranslateContext, ar *config
}
ctx.addUpstream(ups)
}
if !ctx.checkPluginConfigExist(pluginConfigName) {
pc, err := t.translatePluginConfig(ar.Namespace, backend.ServiceName, pluginMap)
if err != nil {
return err
}
ctx.addPluginConfig(pc)
}
}
return nil
}
Expand Down
32 changes: 27 additions & 5 deletions pkg/kube/translation/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@ import apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"

// TranslateContext contains APISIX resources generated by the translator.
type TranslateContext struct {
Routes []*apisix.Route
StreamRoutes []*apisix.StreamRoute
Upstreams []*apisix.Upstream
upstreamMap map[string]struct{}
SSL []*apisix.Ssl
Routes []*apisix.Route
StreamRoutes []*apisix.StreamRoute
Upstreams []*apisix.Upstream
upstreamMap map[string]struct{}
SSL []*apisix.Ssl
PluginConfigs []*apisix.PluginConfig
pluginConfigMaps map[string]struct{}
}

func defaultEmptyTranslateContext() *TranslateContext {
return &TranslateContext{
upstreamMap: make(map[string]struct{}),
pluginConfigMaps: make(map[string]struct{}),
}
}

func (tc *TranslateContext) addRoute(r *apisix.Route) {
Expand All @@ -49,3 +58,16 @@ func (tc *TranslateContext) checkUpstreamExist(name string) (ok bool) {
_, ok = tc.upstreamMap[name]
return
}

func (tc *TranslateContext) addPluginConfig(pc *apisix.PluginConfig) {
if _, ok := tc.pluginConfigMaps[pc.Name]; ok {
return
}
tc.pluginConfigMaps[pc.Name] = struct{}{}
tc.PluginConfigs = append(tc.PluginConfigs, pc)
}

func (tc *TranslateContext) checkPluginConfigExist(name string) (ok bool) {
_, ok = tc.pluginConfigMaps[name]
return
}
23 changes: 20 additions & 3 deletions pkg/kube/translation/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ import (
)

func TestTranslateContext(t *testing.T) {
ctx := &TranslateContext{
upstreamMap: make(map[string]struct{}),
}
ctx := defaultEmptyTranslateContext()

r1 := &apisix.Route{
Metadata: apisix.Metadata{
ID: "1",
Expand Down Expand Up @@ -54,23 +53,41 @@ func TestTranslateContext(t *testing.T) {
Name: "aaa",
},
}
pc1 := &apisix.PluginConfig{
Metadata: apisix.Metadata{
ID: "1",
Name: "aaa",
},
}
pc2 := &apisix.PluginConfig{
Metadata: apisix.Metadata{
ID: "2",
Name: "aaa",
},
}
ctx.addRoute(r1)
ctx.addRoute(r2)
ctx.addStreamRoute(sr1)
ctx.addStreamRoute(sr2)
ctx.addUpstream(u1)
ctx.addUpstream(u2)
ctx.addPluginConfig(pc1)
ctx.addPluginConfig(pc2)

assert.Len(t, ctx.Routes, 2)
assert.Len(t, ctx.StreamRoutes, 2)
assert.Len(t, ctx.Upstreams, 1)
assert.Len(t, ctx.PluginConfigs, 1)

assert.Equal(t, r1, ctx.Routes[0])
assert.Equal(t, r2, ctx.Routes[1])
assert.Equal(t, sr1, ctx.StreamRoutes[0])
assert.Equal(t, sr2, ctx.StreamRoutes[1])
assert.Equal(t, u1, ctx.Upstreams[0])
assert.Equal(t, pc1, ctx.PluginConfigs[0])

assert.Equal(t, true, ctx.checkUpstreamExist("aaa"))
assert.Equal(t, false, ctx.checkUpstreamExist("bbb"))
assert.Equal(t, true, ctx.checkPluginConfigExist("aaa"))
assert.Equal(t, false, ctx.checkPluginConfigExist("bbb"))
}
6 changes: 6 additions & 0 deletions pkg/kube/translation/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ type Translator interface {
// TranslateRouteV2beta3NotStrictly translates the configv2beta3.ApisixRoute object into several Route
// and Upstream resources not strictly, only used for delete event.
TranslateRouteV2beta3NotStrictly(*configv2beta3.ApisixRoute) (*TranslateContext, error)
// TranslatePluginConfigV2beta2 translates the configv2beta2.ApisixPluginConfig object into APISIX PluginConfig
// and Upstream resources.
TranslatePluginConfigV2beta2(config *configv2beta2.ApisixPluginConfig) (*TranslateContext, error)
// TranslatePluginConfigV2beta2NotStrictly translates the configv2beta2.ApisixRoute object into APISIX PluginConfig
// and Upstream resources not strictly, only used for delete event.
TranslatePluginConfigV2beta2NotStrictly(*configv2beta2.ApisixPluginConfig) (*TranslateContext, error)
// TranslateSSL translates the configv2beta3.ApisixTls object into the APISIX SSL resource.
TranslateSSL(*configv2beta3.ApisixTls) (*apisixv1.Ssl, error)
// TranslateClusterConfig translates the configv2beta3.ApisixClusterConfig object into the APISIX
Expand Down
28 changes: 28 additions & 0 deletions pkg/types/apisix/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,19 @@ func NewDefaultConsumer() *Consumer {
}
}

// NewDefaultPluginConfig returns an empty PluginConfig with default values.
func NewDefaultPluginConfig() *PluginConfig {
return &PluginConfig{
Metadata: Metadata{
Desc: "Created by apisix-ingress-controller, DO NOT modify it manually",
Labels: map[string]string{
"managed-by": "apisix-ingress-controller",
},
},
Plugins: make(Plugins),
}
}

// ComposeUpstreamName uses namespace, name, subset (optional) and port info to compose
// the upstream name.
func ComposeUpstreamName(namespace, name, subset string, port int32) string {
Expand Down Expand Up @@ -484,6 +497,21 @@ func ComposeConsumerName(namespace, name string) string {
return buf.String()
}

// ComposePluginConfigName uses namespace, name to compose
// the route name.
func ComposePluginConfigName(namespace, name string) string {
// FIXME Use sync.Pool to reuse this buffer if the upstream
// name composing code path is hot.
p := make([]byte, 0, len(namespace)+len(name)+1)
buf := bytes.NewBuffer(p)

buf.WriteString(namespace)
buf.WriteByte('_')
buf.WriteString(name)

return buf.String()
}

// Schema represents the schema of APISIX objects.
type Schema struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Expand Down

0 comments on commit ebfa98e

Please sign in to comment.