Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/en/latest/references/apisix_route_v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ The table below describes each of the attributes in the spec. The fields `apiVer
| http[].match.exprs[].set | array | Set to compare the subject with. Only used when the operator is `In` or `NotIn`. Can use either this or `http[].match.exprs[].value`. |
| http[].websocket | boolean | When set to `true` enables websocket proxy. |
| http[].plugin_config_name | string | Existing Plugin Config name to use in the Route. |
| http[].plugin_config_namespace | string | Namespace in which to look for `plugin_config_name` Route. |
| http[].backends | object | List of backend services. If there are more than one, a weight based traffic split policy would be applied. |
| http[].backends[].serviceName | string | Name of the backend service. The service and the `ApisixRoute` resource should be created in the same namespace. |
| http[].backends[].servicePort | integer or string | Port number or the name defined in the service object of the backend. |
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,4 @@ require (
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
)
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove EOL?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my editor autoformatted this. I'll remove this

2 changes: 1 addition & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -413,4 +413,4 @@ sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6Lv
sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
10 changes: 6 additions & 4 deletions pkg/kube/apisix/apis/config/v2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ type ApisixRouteHTTP struct {
// Upstreams refer to ApisixUpstream CRD
Upstreams []ApisixRouteUpstreamReference `json:"upstreams,omitempty" yaml:"upstreams,omitempty"`

Websocket bool `json:"websocket" yaml:"websocket"`
PluginConfigName string `json:"plugin_config_name,omitempty" yaml:"plugin_config_name,omitempty"`
Plugins []ApisixRoutePlugin `json:"plugins,omitempty" yaml:"plugins,omitempty"`
Authentication ApisixRouteAuthentication `json:"authentication,omitempty" yaml:"authentication,omitempty"`
Websocket bool `json:"websocket" yaml:"websocket"`
PluginConfigName string `json:"plugin_config_name,omitempty" yaml:"plugin_config_name,omitempty"`
//By default, PluginConfigNamespace will be the same as the namespace of ApisixRoute
PluginConfigNamespace string `json:"plugin_config_namespace,omitempty" yaml:"plugin_config_namespace,omitempty"`
Plugins []ApisixRoutePlugin `json:"plugins,omitempty" yaml:"plugins,omitempty"`
Authentication ApisixRouteAuthentication `json:"authentication,omitempty" yaml:"authentication,omitempty"`
}

// ApisixRouteHTTPBackend represents an HTTP backend (a Kubernetes Service).
Expand Down
10 changes: 7 additions & 3 deletions pkg/providers/apisix/apisix_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,20 @@ updateStatus:
func (c *apisixRouteController) checkPluginNameIfNotEmptyV2(ctx context.Context, in *v2.ApisixRoute) error {
for _, v := range in.Spec.HTTP {
if v.PluginConfigName != "" {
_, err := c.APISIX.Cluster(c.Config.APISIX.DefaultClusterName).PluginConfig().Get(ctx, apisixv1.ComposePluginConfigName(in.Namespace, v.PluginConfigName))
ns := in.Namespace
if v.PluginConfigNamespace != "" {
ns = v.PluginConfigNamespace
}
_, err := c.APISIX.Cluster(c.Config.APISIX.DefaultClusterName).PluginConfig().Get(ctx, apisixv1.ComposePluginConfigName(ns, v.PluginConfigName))
if err != nil {
if err == apisixcache.ErrNotFound {
log.Errorw("checkPluginNameIfNotEmptyV2 error: plugin_config not found",
zap.String("name", apisixv1.ComposePluginConfigName(in.Namespace, v.PluginConfigName)),
zap.String("name", apisixv1.ComposePluginConfigName(ns, v.PluginConfigName)),
zap.Any("obj", in),
zap.Error(err))
} else {
log.Errorw("checkPluginNameIfNotEmptyV2 PluginConfig get failed",
zap.String("name", apisixv1.ComposePluginConfigName(in.Namespace, v.PluginConfigName)),
zap.String("name", apisixv1.ComposePluginConfigName(ns, v.PluginConfigName)),
zap.Any("obj", in),
zap.Error(err))
}
Expand Down
12 changes: 10 additions & 2 deletions pkg/providers/apisix/translation/apisix_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,11 @@ func (t *translator) translateHTTPRouteV2(ctx *translation.TranslateContext, ar
route.FilterFunc = part.Match.FilterFunc

if part.PluginConfigName != "" {
route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ar.Namespace, part.PluginConfigName))
ns := ar.Namespace
if part.PluginConfigNamespace != "" {
ns = part.PluginConfigNamespace
}
route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ns, part.PluginConfigName))
}

for k, v := range ar.ObjectMeta.Labels {
Expand Down Expand Up @@ -465,7 +469,11 @@ func (t *translator) generateHTTPRouteV2DeleteMark(ctx *translation.TranslateCon
route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name)
route.ID = id.GenID(route.Name)
if part.PluginConfigName != "" {
route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ar.Namespace, part.PluginConfigName))
ns := ar.Namespace
if part.PluginConfigNamespace != "" {
ns = part.PluginConfigNamespace
}
route.PluginConfigId = id.GenID(apisixv1.ComposePluginConfigName(ns, part.PluginConfigName))
}

ctx.AddRoute(route)
Expand Down
40 changes: 40 additions & 0 deletions pkg/providers/apisix/translation/apisix_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,46 @@ func TestTranslateApisixRouteV2WithEmptyPluginConfigName(t *testing.T) {
assert.Equal(t, "", res.Routes[2].PluginConfigId)
}

func TestTranslateApisixRouteV2WithPluginConfigNamespace(t *testing.T) {
tr, processCh := mockTranslatorV2(t)
<-processCh
<-processCh
pluginConfigNamespace := "test-2"
ar := &configv2.ApisixRoute{
ObjectMeta: metav1.ObjectMeta{
Name: "ar",
Namespace: "test",
},
Spec: configv2.ApisixRouteSpec{
HTTP: []configv2.ApisixRouteHTTP{
{
Name: "rule1",
Match: configv2.ApisixRouteHTTPMatch{
Paths: []string{
"/*",
},
},
Backends: []configv2.ApisixRouteHTTPBackend{
{
ServiceName: "svc",
ServicePort: intstr.IntOrString{
IntVal: 80,
},
},
},
PluginConfigName: "test-PluginConfigName-1",
PluginConfigNamespace: pluginConfigNamespace,
},
},
},
}
res, err := tr.TranslateRouteV2(ar)
assert.NoError(t, err)
assert.Len(t, res.PluginConfigs, 0)
expectedPluginId := id.GenID(apisixv1.ComposePluginConfigName(pluginConfigNamespace, ar.Spec.HTTP[0].PluginConfigName))
assert.Equal(t, expectedPluginId, res.Routes[0].PluginConfigId)
}

func TestGenerateApisixRouteV2DeleteMark(t *testing.T) {
tr := &translator{
&TranslatorOptions{},
Expand Down
3 changes: 3 additions & 0 deletions samples/deploy/crd/v1/ApisixRoute.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ spec:
plugin_config_name:
type: string
minLength: 1
plugin_config_namespace:
type: string
minLength: 1
upstreams:
description: Upstreams refer to ApisixUpstream CRD
type: array
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,4 @@ replace github.com/apache/apisix-ingress-controller => ../../

replace github.com/apache/apisix-ingress-controller/test/e2e/testbackend => ./testbackend

replace github.com/gruntwork-io/terratest => github.com/api7/terratest v1.0.0
replace github.com/gruntwork-io/terratest => github.com/api7/terratest v1.0.0
2 changes: 1 addition & 1 deletion test/e2e/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -557,4 +557,4 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h6
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
90 changes: 90 additions & 0 deletions test/e2e/suite-plugins/suite-plugins-other/plugin_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,3 +594,93 @@ spec:
resp.Status(http.StatusOK)
})
})

var _ = ginkgo.Describe("suite-plugins-other: ApisixPluginConfig cross namespace", func() {
s := scaffold.NewScaffold(&scaffold.Options{
NamespaceSelectorLabel: map[string][]string{
"apisix.ingress.watch": {"test"},
},
})
ginkgo.It("ApisixPluginConfig cross namespace", func() {
testns := `
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
apisix.ingress.watch: test
`
err := s.CreateResourceFromString(testns)
assert.Nil(ginkgo.GinkgoT(), err, "Creating test namespace")
backendSvc, backendPorts := s.DefaultHTTPBackend()
apc := fmt.Sprintf(`
apiVersion: apisix.apache.org/v2
kind: ApisixPluginConfig
metadata:
name: echo-and-cors-apc
namespace: test
spec:
plugins:
- name: echo
enable: true
config:
before_body: "This is the preface"
after_body: "This is the epilogue"
headers:
X-Foo: v1
X-Foo2: v2
- name: cors
enable: true
`)
assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromStringWithNamespace(apc, "test"))

err = s.EnsureNumApisixPluginConfigCreated(1)
assert.Nil(ginkgo.GinkgoT(), err, "Checking number of pluginConfigs")

time.Sleep(time.Second * 3)

ar := fmt.Sprintf(`
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: httpbin-route
spec:
http:
- name: rule1
match:
hosts:
- httpbin.org
paths:
- /ip
backends:
- serviceName: %s
servicePort: %d
weight: 10
plugin_config_name: echo-and-cors-apc
plugin_config_namespace: test
`, backendSvc, backendPorts[0])
assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar))

err = s.EnsureNumApisixRoutesCreated(1)
assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")

time.Sleep(3 * time.Second)
pcs, err := s.ListApisixPluginConfig()
assert.Nil(ginkgo.GinkgoT(), err, nil, "listing pluginConfigs")
assert.Len(ginkgo.GinkgoT(), pcs, 1)
assert.Len(ginkgo.GinkgoT(), pcs[0].Plugins, 2)

resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect()
resp.Status(http.StatusOK)
resp.Header("X-Foo").Equal("v1")
resp.Header("X-Foo2").Equal("v2")
resp.Header("Access-Control-Allow-Origin").Equal("*")
resp.Header("Access-Control-Allow-Methods").Equal("*")
resp.Header("Access-Control-Allow-Headers").Equal("*")
resp.Header("Access-Control-Expose-Headers").Equal("*")
resp.Header("Access-Control-Max-Age").Equal("5")
resp.Body().Contains("This is the preface")
resp.Body().Contains("origin")
resp.Body().Contains("This is the epilogue")
})
})