Skip to content

Commit 1f090bc

Browse files
committed
Merge branch 'master' into feat/ingress-anno-regex
2 parents bb60e3f + 9baf472 commit 1f090bc

File tree

9 files changed

+133
-6
lines changed

9 files changed

+133
-6
lines changed

internal/adc/translator/annotations.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/pluginconfig"
2727
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/plugins"
2828
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/regex"
29+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/servicenamespace"
2930
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/upstream"
3031
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations/websocket"
3132
)
@@ -35,6 +36,7 @@ type IngressConfig struct {
3536
Upstream upstream.Upstream
3637
Plugins adctypes.Plugins
3738
EnableWebsocket bool
39+
ServiceNamespace string
3840
PluginConfigName string
3941
UseRegex bool
4042
}
@@ -44,6 +46,7 @@ var ingressAnnotationParsers = map[string]annotations.IngressAnnotationsParser{
4446
"plugins": plugins.NewParser(),
4547
"EnableWebsocket": websocket.NewParser(),
4648
"PluginConfigName": pluginconfig.NewParser(),
49+
"ServiceNamespace": servicenamespace.NewParser(),
4750
"UseRegex": regex.NewParser(),
4851
}
4952

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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 servicenamespace
17+
18+
import (
19+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
20+
)
21+
22+
type servicenamespace struct{}
23+
24+
func NewParser() annotations.IngressAnnotationsParser {
25+
return &servicenamespace{}
26+
}
27+
28+
func (w *servicenamespace) Parse(e annotations.Extractor) (any, error) {
29+
return e.GetStringAnnotation(annotations.AnnotationsSvcNamespace), nil
30+
}

internal/adc/translator/annotations_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,15 @@ func TestTranslateIngressAnnotations(t *testing.T) {
279279
},
280280
},
281281
},
282+
{
283+
name: "service namespace",
284+
anno: map[string]string{
285+
annotations.AnnotationsSvcNamespace: "custom-namespace",
286+
},
287+
expected: &IngressConfig{
288+
ServiceNamespace: "custom-namespace",
289+
},
290+
},
282291
{
283292
name: "regex",
284293
anno: map[string]string{

internal/adc/translator/ingress.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,11 @@ func (t *Translator) resolveIngressUpstream(
182182
backendService *networkingv1.IngressServiceBackend,
183183
upstream *adctypes.Upstream,
184184
) string {
185-
backendRef := convertBackendRef(obj.Namespace, backendService.Name, internaltypes.KindService)
185+
ns := obj.Namespace
186+
if config != nil && config.ServiceNamespace != "" {
187+
ns = config.ServiceNamespace
188+
}
189+
backendRef := convertBackendRef(ns, backendService.Name, internaltypes.KindService)
186190
t.AttachBackendTrafficPolicyToUpstream(backendRef, tctx.BackendTrafficPolicies, upstream)
187191
if config != nil {
188192
upConfig := config.Upstream
@@ -210,7 +214,7 @@ func (t *Translator) resolveIngressUpstream(
210214
}
211215

212216
getService := tctx.Services[types.NamespacedName{
213-
Namespace: obj.Namespace,
217+
Namespace: ns,
214218
Name: backendService.Name,
215219
}]
216220
if getService == nil {
@@ -239,7 +243,7 @@ func (t *Translator) resolveIngressUpstream(
239243
}
240244

241245
endpointSlices := tctx.EndpointSlices[types.NamespacedName{
242-
Namespace: obj.Namespace,
246+
Namespace: ns,
243247
Name: backendService.Name,
244248
}]
245249
if len(endpointSlices) > 0 {

internal/controller/indexer/indexer.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,10 @@ func IngressServiceIndexFunc(rawObj client.Object) []string {
472472
ingress := rawObj.(*networkingv1.Ingress)
473473
var services []string
474474

475+
ns := ingress.Namespace
476+
if svcNs := ingress.Annotations[annotations.AnnotationsSvcNamespace]; svcNs != "" {
477+
ns = svcNs
478+
}
475479
for _, rule := range ingress.Spec.Rules {
476480
if rule.HTTP == nil {
477481
continue
@@ -481,7 +485,7 @@ func IngressServiceIndexFunc(rawObj client.Object) []string {
481485
if path.Backend.Service == nil {
482486
continue
483487
}
484-
key := GenIndexKey(ingress.Namespace, path.Backend.Service.Name)
488+
key := GenIndexKey(ns, path.Backend.Service.Name)
485489
services = append(services, key)
486490
}
487491
}

internal/controller/ingress_controller.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ func (r *IngressReconciler) listIngressForBackendTrafficPolicy(ctx context.Conte
410410
r.Log.Error(fmt.Errorf("unexpected object type"), "failed to convert object to BackendTrafficPolicy")
411411
return nil
412412
}
413+
413414
var namespacedNameMap = make(map[types.NamespacedName]struct{})
414415
ingresses := []networkingv1.Ingress{}
415416
for _, ref := range v.Spec.TargetRefs {
@@ -532,7 +533,11 @@ func (r *IngressReconciler) processBackends(tctx *provider.TranslateContext, ing
532533
continue
533534
}
534535
service := path.Backend.Service
535-
if err := r.processBackendService(tctx, ingress.Namespace, service); err != nil {
536+
ns := ingress.Namespace
537+
if svcNs := ingress.Annotations[annotations.AnnotationsSvcNamespace]; svcNs != "" {
538+
ns = ingress.Annotations[annotations.AnnotationsSvcNamespace]
539+
}
540+
if err := r.processBackendService(tctx, ns, service); err != nil {
536541
terr = err
537542
}
538543
}

internal/webhook/v1/ingress_webhook.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ var unsupportedAnnotations = []string{
4646
"k8s.apisix.apache.org/auth-client-headers",
4747
"k8s.apisix.apache.org/allowlist-source-range",
4848
"k8s.apisix.apache.org/blocklist-source-range",
49-
"k8s.apisix.apache.org/svc-namespace",
5049
}
5150

5251
// checkUnsupportedAnnotations checks if the Ingress contains any unsupported annotations

test/e2e/framework/k8s.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@ func (f *Framework) CreateNamespaceWithTestService(name string) {
175175
}
176176
}
177177

178+
func (f *Framework) CreateNamespace(name string) {
179+
_, err := f.clientset.CoreV1().
180+
Namespaces().
181+
Create(f.Context, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}}, metav1.CreateOptions{})
182+
if err != nil && !errors.IsAlreadyExists(err) {
183+
f.GomegaT.Expect(err).ShouldNot(HaveOccurred(), "create namespace")
184+
return
185+
}
186+
}
187+
178188
func (f *Framework) DeleteNamespace(name string) {
179189
err := f.clientset.CoreV1().Namespaces().Delete(f.Context, name, metav1.DeleteOptions{})
180190
if err == nil || errors.IsNotFound(err) {

test/e2e/ingress/annotations.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,69 @@ spec:
953953
})
954954
})
955955

956+
Context("Service Namespace", func() {
957+
var (
958+
ns string
959+
svc = `
960+
apiVersion: v1
961+
kind: Service
962+
metadata:
963+
name: httpbin-external-domain
964+
spec:
965+
type: ExternalName
966+
externalName: httpbin-service-e2e-test.%s.svc
967+
`
968+
ingressSvcNamespace = `
969+
apiVersion: networking.k8s.io/v1
970+
kind: Ingress
971+
metadata:
972+
name: retries
973+
annotations:
974+
k8s.apisix.apache.org/svc-namespace: %s
975+
spec:
976+
ingressClassName: %s
977+
rules:
978+
- host: httpbin.example
979+
http:
980+
paths:
981+
- path: /get
982+
pathType: Exact
983+
backend:
984+
service:
985+
name: httpbin-external-domain
986+
port:
987+
number: 80
988+
`
989+
)
990+
BeforeEach(func() {
991+
ns = s.Namespace() + "-v2"
992+
s.CreateNamespace(ns)
993+
err := s.CreateResourceFromStringWithNamespace(fmt.Sprintf(svc, s.Namespace()), ns)
994+
Expect(err).NotTo(HaveOccurred(), "creating Service in custom namespace")
995+
996+
By("create GatewayProxy")
997+
Expect(s.CreateResourceFromString(s.GetGatewayProxySpec())).NotTo(HaveOccurred(), "creating GatewayProxy")
998+
999+
By("create IngressClass")
1000+
err = s.CreateResourceFromStringWithNamespace(s.GetIngressClassYaml(), "")
1001+
Expect(err).NotTo(HaveOccurred(), "creating IngressClass")
1002+
time.Sleep(5 * time.Second)
1003+
})
1004+
AfterEach(func() {
1005+
s.DeleteNamespace(ns)
1006+
})
1007+
It("svc-namespace", func() {
1008+
Expect(s.CreateResourceFromString(fmt.Sprintf(ingressSvcNamespace, ns, s.Namespace()))).ShouldNot(HaveOccurred(), "creating Ingress")
1009+
1010+
s.RequestAssert(&scaffold.RequestAssert{
1011+
Method: "GET",
1012+
Path: "/get",
1013+
Host: "httpbin.example",
1014+
Check: scaffold.WithExpectedStatus(http.StatusOK),
1015+
})
1016+
})
1017+
})
1018+
9561019
Context("Route", func() {
9571020
var (
9581021
ingressRegex = `

0 commit comments

Comments
 (0)