Skip to content

Commit cd32219

Browse files
ronethingAlinsRan
andauthored
feat: support ingress annotations (#352)
Co-authored-by: Ashing Zheng <[email protected]> Co-authored-by: AlinsRan <[email protected]>
1 parent f8d9357 commit cd32219

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3442
-381
lines changed

api/adc/types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,15 @@ type ResponseRewriteConfig struct {
658658
Filters []map[string]string `json:"filters,omitempty" yaml:"filters,omitempty"`
659659
}
660660

661+
type FaultInjectionConfig struct {
662+
Abort *FaultInjectionAbortConfig `json:"abort,omitempty" yaml:"abort,omitempty"`
663+
}
664+
665+
type FaultInjectionAbortConfig struct {
666+
HTTPStatus int `json:"http_status" yaml:"http_status"`
667+
Vars [][]expr.Expr `json:"vars,omitempty" yaml:"vars,omitempty"`
668+
}
669+
661670
type ResponseHeaders struct {
662671
Set map[string]string `json:"set,omitempty" yaml:"set,omitempty"`
663672
Add []string `json:"add,omitempty" yaml:"add,omitempty"`

internal/adc/translator/annotations.go

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,40 @@ import (
2121

2222
"github.com/imdario/mergo"
2323

24+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
2425
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
26+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/pluginconfig"
27+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/plugins"
28+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/regex"
29+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/servicenamespace"
30+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/upstream"
31+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/websocket"
2532
)
2633

2734
// Structure extracted by Ingress Resource
28-
type Ingress struct{}
35+
type IngressConfig struct {
36+
Upstream upstream.Upstream
37+
Plugins adctypes.Plugins
38+
EnableWebsocket bool
39+
ServiceNamespace string
40+
PluginConfigName string
41+
UseRegex bool
42+
}
2943

30-
// parsers registered for ingress annotations
31-
var ingressAnnotationParsers = map[string]annotations.IngressAnnotationsParser{}
44+
var ingressAnnotationParsers = map[string]annotations.IngressAnnotationsParser{
45+
"upstream": upstream.NewParser(),
46+
"plugins": plugins.NewParser(),
47+
"EnableWebsocket": websocket.NewParser(),
48+
"PluginConfigName": pluginconfig.NewParser(),
49+
"ServiceNamespace": servicenamespace.NewParser(),
50+
"UseRegex": regex.NewParser(),
51+
}
3252

33-
func (t *Translator) TranslateIngressAnnotations(anno map[string]string) *Ingress {
34-
ing := &Ingress{}
53+
func (t *Translator) TranslateIngressAnnotations(anno map[string]string) *IngressConfig {
54+
if len(anno) == 0 {
55+
return nil
56+
}
57+
ing := &IngressConfig{}
3558
if err := translateAnnotations(anno, ing); err != nil {
3659
t.Log.Error(err, "failed to translate ingress annotations", "annotations", anno)
3760
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
package pluginconfig
16+
17+
import "github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
18+
19+
type pluginconfig struct{}
20+
21+
func NewParser() annotations.IngressAnnotationsParser {
22+
return &pluginconfig{}
23+
}
24+
25+
func (w *pluginconfig) Parse(e annotations.Extractor) (any, error) {
26+
return e.GetStringAnnotation(annotations.AnnotationsPluginConfigName), nil
27+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package plugins
17+
18+
import (
19+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
20+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
21+
)
22+
23+
type basicAuth struct{}
24+
25+
// NewkeyBasicHandler creates a handler to convert
26+
// annotations about basicAuth control to APISIX basic-auth plugin.
27+
func NewBasicAuthHandler() PluginAnnotationsHandler {
28+
return &basicAuth{}
29+
}
30+
31+
func (b *basicAuth) PluginName() string {
32+
return "basic-auth"
33+
}
34+
35+
func (b *basicAuth) Handle(e annotations.Extractor) (any, error) {
36+
if e.GetStringAnnotation(annotations.AnnotationsAuthType) != "basicAuth" {
37+
return nil, nil
38+
}
39+
plugin := adctypes.BasicAuthConfig{}
40+
return &plugin, nil
41+
}
42+
43+
type keyAuth struct{}
44+
45+
// NewkeyAuthHandler creates a handler to convert
46+
// annotations about keyAuth control to APISIX key-auth plugin.
47+
func NewKeyAuthHandler() PluginAnnotationsHandler {
48+
return &keyAuth{}
49+
}
50+
51+
func (k *keyAuth) PluginName() string {
52+
return "key-auth"
53+
}
54+
55+
func (k *keyAuth) Handle(e annotations.Extractor) (any, error) {
56+
if e.GetStringAnnotation(annotations.AnnotationsAuthType) != "keyAuth" {
57+
return nil, nil
58+
}
59+
plugin := adctypes.KeyAuthConfig{}
60+
return &plugin, nil
61+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package plugins
17+
18+
import (
19+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
20+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
21+
)
22+
23+
type cors struct{}
24+
25+
// NewCorsHandler creates a handler to convert annotations about
26+
// CORS to APISIX cors plugin.
27+
func NewCorsHandler() PluginAnnotationsHandler {
28+
return &cors{}
29+
}
30+
31+
func (c *cors) PluginName() string {
32+
return "cors"
33+
}
34+
35+
func (c *cors) Handle(e annotations.Extractor) (any, error) {
36+
if !e.GetBoolAnnotation(annotations.AnnotationsEnableCors) {
37+
return nil, nil
38+
}
39+
40+
return &adctypes.CorsConfig{
41+
AllowOrigins: e.GetStringAnnotation(annotations.AnnotationsCorsAllowOrigin),
42+
AllowMethods: e.GetStringAnnotation(annotations.AnnotationsCorsAllowMethods),
43+
AllowHeaders: e.GetStringAnnotation(annotations.AnnotationsCorsAllowHeaders),
44+
}, nil
45+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package plugins
17+
18+
import (
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
23+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
24+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
25+
)
26+
27+
func TestCorsHandler(t *testing.T) {
28+
anno := map[string]string{
29+
annotations.AnnotationsEnableCors: "true",
30+
annotations.AnnotationsCorsAllowHeaders: "abc,def",
31+
annotations.AnnotationsCorsAllowOrigin: "https://a.com",
32+
annotations.AnnotationsCorsAllowMethods: "GET,HEAD",
33+
}
34+
p := NewCorsHandler()
35+
out, err := p.Handle(annotations.NewExtractor(anno))
36+
assert.Nil(t, err, "checking given error")
37+
config := out.(*adctypes.CorsConfig)
38+
assert.Equal(t, "abc,def", config.AllowHeaders)
39+
assert.Equal(t, "https://a.com", config.AllowOrigins)
40+
assert.Equal(t, "GET,HEAD", config.AllowMethods)
41+
42+
assert.Equal(t, "cors", p.PluginName())
43+
44+
anno[annotations.AnnotationsEnableCors] = "false"
45+
out, err = p.Handle(annotations.NewExtractor(anno))
46+
assert.Nil(t, err, "checking given error")
47+
assert.Nil(t, out, "checking given output")
48+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package plugins
17+
18+
import (
19+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
20+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
21+
)
22+
23+
type csrf struct{}
24+
25+
// NewCSRFHandler creates a handler to convert annotations about
26+
// CSRF to APISIX csrf plugin.
27+
func NewCSRFHandler() PluginAnnotationsHandler {
28+
return &csrf{}
29+
}
30+
31+
func (c *csrf) PluginName() string {
32+
return "csrf"
33+
}
34+
35+
func (c *csrf) Handle(e annotations.Extractor) (any, error) {
36+
if !e.GetBoolAnnotation(annotations.AnnotationsEnableCsrf) {
37+
return nil, nil
38+
}
39+
40+
key := e.GetStringAnnotation(annotations.AnnotationsCsrfKey)
41+
if key == "" {
42+
return nil, nil
43+
}
44+
45+
return &adctypes.CSRFConfig{
46+
Key: key,
47+
}, nil
48+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package plugins
17+
18+
import (
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
23+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
24+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
25+
)
26+
27+
func TestCSRFHandler(t *testing.T) {
28+
anno := map[string]string{
29+
annotations.AnnotationsEnableCsrf: "true",
30+
annotations.AnnotationsCsrfKey: "my-secret-key",
31+
}
32+
p := NewCSRFHandler()
33+
out, err := p.Handle(annotations.NewExtractor(anno))
34+
assert.Nil(t, err, "checking given error")
35+
config := out.(*adctypes.CSRFConfig)
36+
assert.Equal(t, "my-secret-key", config.Key)
37+
38+
assert.Equal(t, "csrf", p.PluginName())
39+
40+
// Test with enable-csrf set to false
41+
anno[annotations.AnnotationsEnableCsrf] = "false"
42+
out, err = p.Handle(annotations.NewExtractor(anno))
43+
assert.Nil(t, err, "checking given error")
44+
assert.Nil(t, out, "checking given output")
45+
46+
// Test with enable-csrf true but no key
47+
anno[annotations.AnnotationsEnableCsrf] = "true"
48+
delete(anno, annotations.AnnotationsCsrfKey)
49+
out, err = p.Handle(annotations.NewExtractor(anno))
50+
assert.Nil(t, err, "checking given error")
51+
assert.Nil(t, out, "checking given output when key is missing")
52+
}

0 commit comments

Comments
 (0)