This is an automated email from the ASF dual-hosted git repository.

ashishtiwari pushed a commit to branch v1.8.0
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git


The following commit(s) were added to refs/heads/v1.8.0 by this push:
     new 4d42c9ae release: add release notes for 1.8.1 and cherry pick commits 
(#2211)
4d42c9ae is described below

commit 4d42c9ae5b46fd77cfb9c653af3e8a36ba1983b4
Author: Ashish Tiwari <[email protected]>
AuthorDate: Fri Apr 12 17:16:46 2024 +0530

    release: add release notes for 1.8.1 and cherry pick commits (#2211)
    
    * docs: clarify usage of external service discovery (#2124)
    
    * feat: add plugin_config_namespace parameter to ApisixRoute (#2137)
    
    * feat: add plugin_config_namespace parameter to ApisixRoute
    
    Add plugin_config_namespace parameter to ApisixRoute resource to allow 
cross namespace discovery.
    
    * fix indentation
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    
    * remove route.yaml
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    
    * fix e2e test
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    
    * update gomod gosum
    
    * fix e2e test
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    
    * fix e2e test
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    
    * Update pkg/providers/apisix/apisix_route.go
    
    Co-authored-by: Gallardot <[email protected]>
    
    * create namespace
    
    * refactor test
    
    * refactor test
    
    * fix e2e
    
    * fix e2e
    
    * update crd
    
    * Add EOL
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    
    ---------
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    Co-authored-by: Gallardot <[email protected]>
    
    * fix: remove path validation (#2140)
    
    * docs: update NOTICE (#2149)
    
    * refactor(cmd/ingress): invert signal ctx logic (#2139)
    
    * refactor(cmd/ingress): invert signal ctx logic
    
    this commit changes the signal handling in cmd/ingress to be wrapped in
    a context, and inverts which goroutine runs the controller and
    which watches for the context to be cancelled, which allows some
    scaffolding (`sync.WaitGroup`) to be removed and now properly handles
    the controller exiting with `nil` (as it does when leader election
    fails)
    
    * test: failing flaky unit test (#2151)
    
    * fix: failing flaky unit test
    
    * chore(ci): remove tao12345666333 and lingsamuel in reviewers (#2150)
    
    * chore(deps): bump github.com/onsi/ginkgo/v2 in /test/e2e (#2177)
    
    Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 
2.13.2 to 2.16.0.
    - [Release notes](https://github.com/onsi/ginkgo/releases)
    - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/onsi/ginkgo/compare/v2.13.2...v2.16.0)
    
    ---
    updated-dependencies:
    - dependency-name: github.com/onsi/ginkgo/v2
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * chore(deps): bump k8s.io/apimachinery from 0.29.0 to 0.29.2 in /test/e2e 
(#2161)
    
    Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) 
from 0.29.0 to 0.29.2.
    - 
[Commits](https://github.com/kubernetes/apimachinery/compare/v0.29.0...v0.29.2)
    
    ---
    updated-dependencies:
    - dependency-name: k8s.io/apimachinery
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * chore(deps): bump k8s.io/api from 0.29.0 to 0.29.2 in /test/e2e (#2163)
    
    Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.29.0 to 0.29.2.
    - [Commits](https://github.com/kubernetes/api/compare/v0.29.0...v0.29.2)
    
    ---
    updated-dependencies:
    - dependency-name: k8s.io/api
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * chore(deps): bump go.uber.org/zap from 1.26.0 to 1.27.0 in /test/e2e 
(#2172)
    
    Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.26.0 to 
1.27.0.
    - [Release notes](https://github.com/uber-go/zap/releases)
    - [Changelog](https://github.com/uber-go/zap/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/uber-go/zap/compare/v1.26.0...v1.27.0)
    
    ---
    updated-dependencies:
    - dependency-name: go.uber.org/zap
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * chore(deps): bump k8s.io/client-go from 0.29.0 to 0.29.2 in /test/e2e 
(#2162)
    
    Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 
0.29.0 to 0.29.2.
    - 
[Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
    - 
[Commits](https://github.com/kubernetes/client-go/compare/v0.29.0...v0.29.2)
    
    ---
    updated-dependencies:
    - dependency-name: k8s.io/client-go
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * chore(deps): bump k8s.io/apimachinery from 0.29.2 to 0.29.3 in /test/e2e 
(#2185)
    
    Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) 
from 0.29.2 to 0.29.3.
    - 
[Commits](https://github.com/kubernetes/apimachinery/compare/v0.29.2...v0.29.3)
    
    ---
    updated-dependencies:
    - dependency-name: k8s.io/apimachinery
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * chore: upgrade etcd-adapter to latest version (#2205)
    
    * chore(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0 (#2196)
    
    Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 
to 1.8.0.
    - [Release notes](https://github.com/spf13/cobra/releases)
    - [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)
    
    ---
    updated-dependencies:
    - dependency-name: github.com/spf13/cobra
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * chore(deps): bump github.com/onsi/ginkgo/v2 in /test/e2e (#2195)
    
    Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 
2.16.0 to 2.17.1.
    - [Release notes](https://github.com/onsi/ginkgo/releases)
    - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/onsi/ginkgo/compare/v2.16.0...v2.17.1)
    
    ---
    updated-dependencies:
    - dependency-name: github.com/onsi/ginkgo/v2
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    
    * fix: use force=true to hard delete the apisix resource (#2210)
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    
    * chore: remove redundant logs and improve logs for users (#2206)
    
    * chore: remove redundant logs and improve error when upstream is created
    
    Co-authored-by: AlinsRan <[email protected]>
    
    
    ---------
    
    Signed-off-by: Ashish Tiwari <[email protected]>
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: Gallardot <[email protected]>
    Co-authored-by: Leigang Zhang <[email protected]>
    Co-authored-by: Aurelia <[email protected]>
    Co-authored-by: AlinsRan <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
---
 .github/dependabot.yml                             |  6 --
 .github/workflows/codeql-analysis.yml              |  2 +-
 .github/workflows/dependency-review.yml            |  2 +-
 .github/workflows/e2e-test-ci-v2-cron-dev.yml      |  2 +-
 .github/workflows/e2e-test-ci-v2-cron.yml          |  2 +-
 .github/workflows/e2e-test-ci.yml                  |  2 +-
 .github/workflows/goimports-reviser.yml            |  2 +-
 .github/workflows/golangci-lint.yml                |  2 +-
 .github/workflows/license-checker.yml              |  2 +-
 .github/workflows/lint-checker.yml                 |  2 +-
 .github/workflows/spell-checker.yml                |  2 +-
 .github/workflows/unit-test-ci.yml                 |  2 +-
 .github/workflows/verify-codegen.yml               |  2 +-
 .github/workflows/yamllint-checker.yml             |  2 +-
 CHANGELOG.md                                       | 31 ++++++++
 Makefile                                           |  2 +-
 NOTICE                                             |  2 +-
 cmd/ingress/ingress.go                             | 42 +++++-----
 docs/en/latest/references/apisix_route_v2.md       |  1 +
 .../latest/tutorials/external-service-discovery.md | 15 ++++
 go.mod                                             |  4 +-
 go.sum                                             | 10 +--
 pkg/apisix/cluster.go                              |  3 +-
 pkg/kube/apisix/apis/config/v2/types.go            | 10 ++-
 pkg/providers/apisix/apisix_route.go               | 10 ++-
 pkg/providers/apisix/apisix_upstream.go            | 38 ++++++---
 pkg/providers/apisix/translation/apisix_route.go   | 12 ++-
 .../apisix/translation/apisix_route_test.go        | 40 ++++++++++
 pkg/providers/controller.go                        |  9 +--
 pkg/types/labels_test.go                           |  2 +-
 releases/v1.8.1.toml                               | 56 ++++++++++++++
 samples/deploy/crd/v1/ApisixRoute.yaml             |  4 +-
 test/e2e/go.mod                                    | 30 ++++----
 test/e2e/go.sum                                    | 65 ++++++++--------
 .../suite-plugins-other/plugin_config.go           | 90 ++++++++++++++++++++++
 35 files changed, 383 insertions(+), 125 deletions(-)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index c34d0cba..3ae11605 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -26,8 +26,6 @@ updates:
     labels:
       - "area/dependencies"
     reviewers:
-      - "tao12345666333"
-      - "lingsamuel"
       - "AlinsRan"
       - "Gallardot"
       - "Revolyssup"
@@ -38,8 +36,6 @@ updates:
     labels:
       - "area/dependencies"
     reviewers:
-      - "tao12345666333"
-      - "lingsamuel"
       - "AlinsRan"
       - "Gallardot"
       - "Revolyssup"
@@ -50,8 +46,6 @@ updates:
     labels:
       - "area/dependencies"
     reviewers:
-      - "tao12345666333"
-      - "lingsamuel"
       - "AlinsRan"
       - "Gallardot"
       - "Revolyssup"
diff --git a/.github/workflows/codeql-analysis.yml 
b/.github/workflows/codeql-analysis.yml
index 245cb3de..3cad41fb 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -24,7 +24,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
   schedule:
     - cron: '25 5 * * 5'
 
diff --git a/.github/workflows/dependency-review.yml 
b/.github/workflows/dependency-review.yml
index 1234af91..2189ee5b 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -21,7 +21,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 
 permissions:
   contents: read
diff --git a/.github/workflows/e2e-test-ci-v2-cron-dev.yml 
b/.github/workflows/e2e-test-ci-v2-cron-dev.yml
index 9cc3a58e..b7a1fbc3 100644
--- a/.github/workflows/e2e-test-ci-v2-cron-dev.yml
+++ b/.github/workflows/e2e-test-ci-v2-cron-dev.yml
@@ -25,7 +25,7 @@ on:
   push:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 
 concurrency:
   group: ${{ github.workflow }}-dev
diff --git a/.github/workflows/e2e-test-ci-v2-cron.yml 
b/.github/workflows/e2e-test-ci-v2-cron.yml
index afd6ea7c..287c3e85 100644
--- a/.github/workflows/e2e-test-ci-v2-cron.yml
+++ b/.github/workflows/e2e-test-ci-v2-cron.yml
@@ -24,7 +24,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.number || 
github.ref }}-v2
diff --git a/.github/workflows/e2e-test-ci.yml 
b/.github/workflows/e2e-test-ci.yml
index 4cf2cbfa..bf5ae422 100644
--- a/.github/workflows/e2e-test-ci.yml
+++ b/.github/workflows/e2e-test-ci.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.number || 
github.ref }}
diff --git a/.github/workflows/goimports-reviser.yml 
b/.github/workflows/goimports-reviser.yml
index b19e8ff6..ddae0015 100644
--- a/.github/workflows/goimports-reviser.yml
+++ b/.github/workflows/goimports-reviser.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 jobs:
   changes:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/golangci-lint.yml 
b/.github/workflows/golangci-lint.yml
index df43ab90..5f373fc2 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 
 jobs:
   changes:
diff --git a/.github/workflows/license-checker.yml 
b/.github/workflows/license-checker.yml
index 48463b5c..0d458178 100644
--- a/.github/workflows/license-checker.yml
+++ b/.github/workflows/license-checker.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 
 jobs:
   check-license:
diff --git a/.github/workflows/lint-checker.yml 
b/.github/workflows/lint-checker.yml
index 9fc762d5..4c7534a1 100644
--- a/.github/workflows/lint-checker.yml
+++ b/.github/workflows/lint-checker.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 jobs:
   changes:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/spell-checker.yml 
b/.github/workflows/spell-checker.yml
index 5e738d1f..1ada725b 100644
--- a/.github/workflows/spell-checker.yml
+++ b/.github/workflows/spell-checker.yml
@@ -24,7 +24,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 jobs:
   misspell:
     name: runner / misspell
diff --git a/.github/workflows/unit-test-ci.yml 
b/.github/workflows/unit-test-ci.yml
index 238df382..094b1c64 100644
--- a/.github/workflows/unit-test-ci.yml
+++ b/.github/workflows/unit-test-ci.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 jobs:
   changes:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/verify-codegen.yml 
b/.github/workflows/verify-codegen.yml
index 835ab657..ef028615 100644
--- a/.github/workflows/verify-codegen.yml
+++ b/.github/workflows/verify-codegen.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 jobs:
   changes:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/yamllint-checker.yml 
b/.github/workflows/yamllint-checker.yml
index 767075af..c69a091d 100644
--- a/.github/workflows/yamllint-checker.yml
+++ b/.github/workflows/yamllint-checker.yml
@@ -25,7 +25,7 @@ on:
   pull_request:
     branches:
       - master
-      - 1.8.0
+      - v1.8.0
 jobs:
   changes:
     runs-on: ubuntu-latest
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dbd25fb5..73d30b16 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,37 @@
 - [0.2.0](#020)
 - [0.1.0](#010)
 
+# 1.8.1
+
+## What's New
+
+- chore: remove redundant logs and improve logs for users @Revolyssup (#2206)
+- fix: use force=true to hard delete the apisix resource @Revolyssup (#2210)
+- chore: upgrade etcd-adapter to latest version @Revolyssup (#2205)
+- chore(ci): remove tao12345666333 and lingsamuel in reviewers @AlinsRan 
(#2150)
+- test: failing flaky unit test @Revolyssup (#2151)
+- refactor(cmd/ingress): invert signal ctx logic @acuteaura (#2139)
+- chore: update NOTICE to 2024 @zll600 (#2149)
+- fix: remove path validation @Revolyssup (#2140)
+- feat: add plugin_config_namespace parameter to ApisixRoute @Revolyssup 
(#2137)
+- docs: clarify usage of external service discovery @Revolyssup (#2124)
+
+## 🧰 Maintenance
+
+- chore(deps): bump github.com/onsi/ginkgo/v2 from 2.16.0 to 2.17.1 in 
/test/e2e @dependabot (#2195)
+- chore(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0 @dependabot 
(#2196)
+- chore(deps): bump k8s.io/apimachinery from 0.29.2 to 0.29.3 in /test/e2e 
@dependabot (#2185)
+- chore(deps): bump k8s.io/client-go from 0.29.0 to 0.29.2 in /test/e2e 
@dependabot (#2162)
+- chore(deps): bump go.uber.org/zap from 1.26.0 to 1.27.0 in /test/e2e 
@dependabot (#2172)
+- chore(deps): bump k8s.io/api from 0.29.0 to 0.29.2 in /test/e2e @dependabot 
(#2163)
+- chore(deps): bump k8s.io/apimachinery from 0.29.0 to 0.29.2 in /test/e2e 
@dependabot (#2161)
+- chore(deps): bump github.com/onsi/ginkgo/v2 from 2.13.2 to 2.16.0 in 
/test/e2e @dependabot (#2177)
+
+## 👨🏽‍💻 Contributors
+
+Thank you to our contributors for making this release possible:
+@AlinsRan, @Revolyssup, @acuteaura, @dependabot, @dependabot[bot] and @zll600
+
 # 1.8.0
 
 ## What's New
diff --git a/Makefile b/Makefile
index 6229e4c2..09e1f813 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 #
 default: help
 
-VERSION ?= 1.8.0
+VERSION ?= 1.8.1
 
 
 TARGET_APISIX_VERSION ?= "3.4.1-centos"
diff --git a/NOTICE b/NOTICE
index c663509f..abdbd3d3 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache APISIX
-Copyright 2019-2023 The Apache Software Foundation
+Copyright 2019-2024 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/cmd/ingress/ingress.go b/cmd/ingress/ingress.go
index 3d2311e8..34bb05e7 100644
--- a/cmd/ingress/ingress.go
+++ b/cmd/ingress/ingress.go
@@ -15,12 +15,12 @@
 package ingress
 
 import (
+       "context"
        "encoding/json"
        "fmt"
        "os"
        "os/signal"
        "strings"
-       "sync"
        "syscall"
        "time"
 
@@ -42,13 +42,19 @@ func dief(template string, args ...interface{}) {
        os.Exit(1)
 }
 
-func waitForSignal(stopCh chan struct{}) {
-       sigCh := make(chan os.Signal, 1)
-       signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
-
-       sig := <-sigCh
-       log.Infof("signal %d (%s) received", sig, sig.String())
-       close(stopCh)
+func contextWithSignalCancel(ctx context.Context, signals ...os.Signal) 
context.Context {
+       newCtx, cancel := context.WithCancel(ctx)
+       go func() {
+               sigCh := make(chan os.Signal, 1)
+               signal.Notify(sigCh, signals...)
+
+               sig := <-sigCh
+               log.Infof("signal %d (%s) received", sig, sig.String())
+               signal.Stop(sigCh)
+               close(sigCh)
+               cancel()
+       }()
+       return newCtx
 }
 
 // NewIngressCommand creates the ingress sub command for 
apisix-ingress-controller.
@@ -118,8 +124,8 @@ the apisix cluster and others are created`,
                                dief("failed to initialize logging: %s", err)
                        }
                        log.DefaultLogger = logger
-                       log.Info("init apisix ingress controller")
 
+                       log.Info("init apisix ingress controller")
                        log.Info("version:\n", version.Long())
 
                        // We should make sure that the cfg that's logged out 
is sanitized.
@@ -132,25 +138,17 @@ the apisix cluster and others are created`,
                        }
                        log.Info("use configuration\n", string(data))
 
-                       stop := make(chan struct{})
+                       ctx := contextWithSignalCancel(context.Background(), 
syscall.SIGINT, syscall.SIGTERM)
+
                        ingress, err := controller.NewController(cfg)
                        if err != nil {
                                dief("failed to create ingress controller: %s", 
err)
                        }
-                       wg := sync.WaitGroup{}
-                       wg.Add(1)
-                       go func() {
-                               defer wg.Done()
 
-                               log.Info("start ingress controller")
-
-                               if err := ingress.Run(stop); err != nil {
-                                       dief("failed to run ingress controller: 
%s", err)
-                               }
-                       }()
+                       if err := ingress.Run(ctx); err != nil {
+                               dief("failed to run ingress controller: %s", 
err)
+                       }
 
-                       waitForSignal(stop)
-                       wg.Wait()
                        log.Info("apisix ingress controller exited")
                },
        }
diff --git a/docs/en/latest/references/apisix_route_v2.md 
b/docs/en/latest/references/apisix_route_v2.md
index 27910083..0104efe5 100644
--- a/docs/en/latest/references/apisix_route_v2.md
+++ b/docs/en/latest/references/apisix_route_v2.md
@@ -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.                          
                                                                                
           |
diff --git a/docs/en/latest/tutorials/external-service-discovery.md 
b/docs/en/latest/tutorials/external-service-discovery.md
index 63c0b4e0..a9471970 100644
--- a/docs/en/latest/tutorials/external-service-discovery.md
+++ b/docs/en/latest/tutorials/external-service-discovery.md
@@ -88,3 +88,18 @@ discovery:
 ```
 
 After applying the above configuration, we can try to access 
`httpbin.default.svc.cluster.local` directly through APISIX.
+
+:::note
+The above discovery configuration needs to be configured at the time of 
installation and cannot be edited later. For example, if you're installing via 
helm chart, make sure that you use the below configuration to override default 
helm values.
+
+```yaml
+apisix:
+  discovery:
+    enabled: true
+    registry:
+      dns:
+        servers:
+          - "172.17.0.11:53" # replace with your server addresses
+```
+
+:::
diff --git a/go.mod b/go.mod
index 251548fa..b92e2e44 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/apache/apisix-ingress-controller
 go 1.20
 
 require (
-       github.com/api7/etcd-adapter v0.2.3
+       github.com/api7/etcd-adapter v0.2.4
        github.com/api7/gopkg v0.2.0
        github.com/gin-gonic/gin v1.9.1
        github.com/hashicorp/go-memdb v1.3.4
@@ -14,7 +14,7 @@ require (
        github.com/prometheus/client_golang v1.16.0
        github.com/prometheus/client_model v0.4.0
        github.com/slok/kubewebhook/v2 v2.5.0
-       github.com/spf13/cobra v1.7.0
+       github.com/spf13/cobra v1.8.0
        github.com/stretchr/testify v1.8.4
        github.com/xeipuuv/gojsonschema v1.2.0
        go.uber.org/multierr v1.11.0
diff --git a/go.sum b/go.sum
index 0216c321..650ed779 100644
--- a/go.sum
+++ b/go.sum
@@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod 
h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 cloud.google.com/go v0.34.0/go.mod 
h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/BurntSushi/toml v0.3.1/go.mod 
h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/antihax/optional v1.0.0/go.mod 
h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/api7/etcd-adapter v0.2.3 
h1:nb2IDli/d9WlhtObhYUtJUXs+IfGMTcXRc5Fu9IBgtk=
-github.com/api7/etcd-adapter v0.2.3/go.mod 
h1:JoLtq4IxiIw6Z+k9eRGHL0CDyfRvnNXGI0skV0EsSE8=
+github.com/api7/etcd-adapter v0.2.4 
h1:VWdDPUJPai5IdxV5dwwZF9e7Ilw7sBWwaEeFzPO2fV4=
+github.com/api7/etcd-adapter v0.2.4/go.mod 
h1:JoLtq4IxiIw6Z+k9eRGHL0CDyfRvnNXGI0skV0EsSE8=
 github.com/api7/gopkg v0.2.0 h1:+5vw6Rt9IeEpJoL2JMZFDwGDhH4aaeUJize21/3Qdzc=
 github.com/api7/gopkg v0.2.0/go.mod 
h1:LlplmjGCrkcS3nyCYpTwkdLkuNlYRYAnI8XH1qwsICw=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -21,7 +21,7 @@ github.com/client9/misspell v0.3.4/go.mod 
h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod 
h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/coreos/go-semver v0.3.1 
h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
 github.com/coreos/go-systemd/v22 v22.5.0 
h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod 
h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 
h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -199,8 +199,8 @@ github.com/slok/kubewebhook/v2 v2.5.0/go.mod 
h1:TcQS+Ae0TDiiwm9glxum6AFvtumR33qd
 github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
 github.com/soheilhy/cmux v0.1.5/go.mod 
h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
 github.com/sony/sonyflake v1.1.0/go.mod 
h1:LORtCywH/cq10ZbyfhKrHYgAUGH7mOBa76enV9txy/Y=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod 
h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod 
h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod 
h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
diff --git a/pkg/apisix/cluster.go b/pkg/apisix/cluster.go
index 969fb2df..840a4e74 100644
--- a/pkg/apisix/cluster.go
+++ b/pkg/apisix/cluster.go
@@ -849,6 +849,7 @@ func (c *cluster) updateResource(ctx context.Context, url, 
resource string, body
 }
 
 func (c *cluster) deleteResource(ctx context.Context, url, resource string) 
error {
+       url = url + "?force=true"
        log.Debugw("deleting resource in cluster",
                zap.String("cluster_name", c.name),
                zap.String("name", resource),
@@ -1161,7 +1162,7 @@ func (c *cluster) GetUpstream(ctx context.Context, 
baseUrl, id string) (*v1.Upst
        resp, err := c.getResource(ctx, url, "upstream")
        if err != nil {
                if err == cache.ErrNotFound {
-                       log.Warnw("upstream not found",
+                       log.Debugw("upstream not found",
                                zap.String("id", id),
                                zap.String("url", url),
                                zap.String("cluster", c.name),
diff --git a/pkg/kube/apisix/apis/config/v2/types.go 
b/pkg/kube/apisix/apis/config/v2/types.go
index 1edb8e55..dfec5928 100644
--- a/pkg/kube/apisix/apis/config/v2/types.go
+++ b/pkg/kube/apisix/apis/config/v2/types.go
@@ -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).
diff --git a/pkg/providers/apisix/apisix_route.go 
b/pkg/providers/apisix/apisix_route.go
index 937f02fa..c06a8a0f 100644
--- a/pkg/providers/apisix/apisix_route.go
+++ b/pkg/providers/apisix/apisix_route.go
@@ -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))
                                }
diff --git a/pkg/providers/apisix/apisix_upstream.go 
b/pkg/providers/apisix/apisix_upstream.go
index 02866ef5..72ee5369 100644
--- a/pkg/providers/apisix/apisix_upstream.go
+++ b/pkg/providers/apisix/apisix_upstream.go
@@ -32,6 +32,7 @@ import (
        "k8s.io/client-go/tools/cache"
        "k8s.io/client-go/util/workqueue"
 
+       "github.com/apache/apisix-ingress-controller/pkg/apisix"
        "github.com/apache/apisix-ingress-controller/pkg/config"
        "github.com/apache/apisix-ingress-controller/pkg/kube"
        configv2 
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
@@ -215,12 +216,15 @@ func (c *apisixUpstreamController) sync(ctx 
context.Context, ev *types.Event) er
                        // for service discovery related configuration
                        if au.Spec.Discovery.ServiceName == "" || 
au.Spec.Discovery.Type == "" {
                                log.Error("If you setup Discovery for 
ApisixUpstream, you need to specify the ServiceName and Type fields.")
-                               errRecord = fmt.Errorf("No ServiceName or Type 
fields found")
+                               errRecord = fmt.Errorf("no ServiceName or Type 
fields found")
                                goto updateStatus
                        }
                        // updateUpstream for real
                        upsName := 
apisixv1.ComposeExternalUpstreamName(au.Namespace, au.Name)
                        errRecord = c.updateUpstream(ctx, upsName, 
&au.Spec.ApisixUpstreamConfig, ev.Type.IsSyncEvent())
+                       if err == apisix.ErrNotFound {
+                               errRecord = fmt.Errorf("%s", "upstream doesn't 
exist. It will be created after ApisixRoute is created referencing it.")
+                       }
                        goto updateStatus
                }
 
@@ -254,15 +258,22 @@ func (c *apisixUpstreamController) sync(ctx 
context.Context, ev *types.Event) er
                                                cfg = 
au.Spec.ApisixUpstreamConfig
                                        }
                                }
-
                                err := c.updateUpstream(ctx, 
apisixv1.ComposeUpstreamName(namespace, name, subset.Name, port.Port, 
types.ResolveGranularity.Endpoint), &cfg, ev.Type.IsSyncEvent())
                                if err != nil {
-                                       errRecord = err
+                                       if err == apisix.ErrNotFound {
+                                               errRecord = fmt.Errorf("%s", 
"upstream doesn't exist. It will be created after ApisixRoute is created 
referencing it.")
+                                       } else {
+                                               errRecord = err
+                                       }
                                        goto updateStatus
                                }
                                err = c.updateUpstream(ctx, 
apisixv1.ComposeUpstreamName(namespace, name, subset.Name, port.Port, 
types.ResolveGranularity.Service), &cfg, ev.Type.IsSyncEvent())
                                if err != nil {
-                                       errRecord = err
+                                       if err == apisix.ErrNotFound {
+                                               errRecord = fmt.Errorf("%s", 
"upstream doesn't exist. It will be created after ApisixRoute is created 
referencing it.")
+                                       } else {
+                                               errRecord = err
+                                       }
                                        goto updateStatus
                                }
                        }
@@ -330,8 +341,7 @@ func (c *apisixUpstreamController) updateUpstream(ctx 
context.Context, upsName s
 
        ups, err := c.APISIX.Cluster(clusterName).Upstream().Get(ctx, upsName)
        if err != nil {
-               log.Errorf("failed to get upstream %s: %s", upsName, err)
-               return err
+               return apisix.ErrNotFound
        }
        var newUps *apisixv1.Upstream
        if cfg != nil {
@@ -373,9 +383,19 @@ func (c *apisixUpstreamController) updateExternalNodes(ctx 
context.Context, au *
        upsName := apisixv1.ComposeExternalUpstreamName(ns, name)
        ups, err := c.APISIX.Cluster(clusterName).Upstream().Get(ctx, upsName)
        if err != nil {
-               log.Errorf("failed to get upstream %s: %s", upsName, err)
-               c.RecordEvent(au, corev1.EventTypeWarning, 
utils.ResourceSyncAborted, err)
-               c.recordStatus(au, utils.ResourceSyncAborted, err, 
metav1.ConditionFalse, au.GetGeneration())
+               if err == apisix.ErrNotFound {
+                       log.Debugw("upstream is not referenced",
+                               zap.String("cluster", clusterName),
+                               zap.String("upstream", upsName),
+                       )
+                       err = fmt.Errorf("%s", "upstream doesn't exist. It will 
be created after ApisixRoute is created referencing it.")
+                       c.RecordEvent(au, corev1.EventTypeWarning, 
utils.ResourceSyncAborted, err)
+                       c.recordStatus(au, utils.ResourceSyncAborted, err, 
metav1.ConditionFalse, au.GetGeneration())
+               } else {
+                       c.RecordEvent(au, corev1.EventTypeWarning, 
utils.ResourceSyncAborted, err)
+                       c.recordStatus(au, utils.ResourceSyncAborted, err, 
metav1.ConditionFalse, au.GetGeneration())
+                       log.Errorf("failed to get upstream %s: %s", upsName, 
err)
+               }
                return err
        } else if ups != nil {
                nodes, err := 
c.translator.TranslateApisixUpstreamExternalNodes(au)
diff --git a/pkg/providers/apisix/translation/apisix_route.go 
b/pkg/providers/apisix/translation/apisix_route.go
index 856709e6..9fa8b2b2 100644
--- a/pkg/providers/apisix/translation/apisix_route.go
+++ b/pkg/providers/apisix/translation/apisix_route.go
@@ -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 {
@@ -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)
diff --git a/pkg/providers/apisix/translation/apisix_route_test.go 
b/pkg/providers/apisix/translation/apisix_route_test.go
index 36f12983..64fa166f 100644
--- a/pkg/providers/apisix/translation/apisix_route_test.go
+++ b/pkg/providers/apisix/translation/apisix_route_test.go
@@ -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{},
diff --git a/pkg/providers/controller.go b/pkg/providers/controller.go
index a2ebc253..d8693221 100644
--- a/pkg/providers/controller.go
+++ b/pkg/providers/controller.go
@@ -144,13 +144,10 @@ func (c *Controller) Eventf(_ runtime.Object, eventType 
string, reason string, m
 }
 
 // Run launches the controller.
-func (c *Controller) Run(stop chan struct{}) error {
-       rootCtx, rootCancel := context.WithCancel(context.Background())
+func (c *Controller) Run(ctx context.Context) error {
+       rootCtx, rootCancel := context.WithCancel(ctx)
        defer rootCancel()
-       go func() {
-               <-stop
-               rootCancel()
-       }()
+
        c.MetricsCollector.ResetLeader(false)
 
        go func() {
diff --git a/pkg/types/labels_test.go b/pkg/types/labels_test.go
index ae9cd891..d38bda52 100644
--- a/pkg/types/labels_test.go
+++ b/pkg/types/labels_test.go
@@ -61,5 +61,5 @@ func TestBuildQuery(t *testing.T) {
                "a": []string{"a1", "a2"},
                "b": []string{"b1", "b2"},
        }
-       assert.Equal(t, []string{"a in (a1,a2)", "b in (b1,b2)"}, 
l.BuildQuery())
+       assert.ElementsMatch(t, l.BuildQuery(), []string{"a in (a1,a2)", "b in 
(b1,b2)"})
 }
diff --git a/releases/v1.8.1.toml b/releases/v1.8.1.toml
new file mode 100644
index 00000000..c2cf9587
--- /dev/null
+++ b/releases/v1.8.1.toml
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+# commit to be tagged for new release
+commit = "HEAD"
+
+# project_name is used to refer to the project in the notes
+project_name = "apisix-ingress-controller"
+
+# github_repo is the github project, only github is currently supported
+github_repo = "apache/apisix-ingress-controller"
+
+# match_deps is a pattern to determine which dependencies should be included
+# as part of this release. The changelog will also include changes for these
+# dependencies based on the change in the dependency's version.
+match_deps = "^github.com/(apache/[a-zA-Z0-9-]+)$"
+
+# previous release of this project for determining changes
+previous = "1.8.0"
+
+# pre_release is whether to include a disclaimer about being a pre-release
+pre_release = false
+
+# preface is the description of the release which precedes the author list
+# and changelog. This description could include highlights as well as any
+# description of changes. Use markdown formatting.
+preface = """\
+This is a patch release.
+
+## Highlights
+
+- chore: remove redundant logs and improve logs for users
+- fix: use force=true to hard delete the apisix resource
+- chore: upgrade etcd-adapter to latest version
+- chore(ci): remove tao12345666333 and lingsamuel in reviewers
+- test: failing flaky unit tes
+- refactor(cmd/ingress): invert signal ctx logic
+- chore: update NOTICE to 2024
+- fix: remove path validation
+- feat: add plugin_config_namespace parameter to ApisixRoute
+- docs: clarify usage of external service discoveryj
+
+"""
diff --git a/samples/deploy/crd/v1/ApisixRoute.yaml 
b/samples/deploy/crd/v1/ApisixRoute.yaml
index 8f3ba25d..a479e1b6 100644
--- a/samples/deploy/crd/v1/ApisixRoute.yaml
+++ b/samples/deploy/crd/v1/ApisixRoute.yaml
@@ -104,7 +104,6 @@ spec:
                             minItems: 1
                             items:
                               type: string
-                              pattern: 
"^/[a-zA-Z0-9\\-._~%!$&'()+,;=:@/]*\\*?$"
                           hosts:
                             type: array
                             minItems: 1
@@ -184,6 +183,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
diff --git a/test/e2e/go.mod b/test/e2e/go.mod
index 4a01b704..b2f1e80f 100644
--- a/test/e2e/go.mod
+++ b/test/e2e/go.mod
@@ -9,19 +9,19 @@ require (
        github.com/gavv/httpexpect/v2 v2.16.0
        github.com/gorilla/websocket v1.5.1
        github.com/gruntwork-io/terratest v0.40.22
-       github.com/onsi/ginkgo/v2 v2.13.2
+       github.com/onsi/ginkgo/v2 v2.17.1
        github.com/stretchr/testify v1.8.4
-       go.uber.org/zap v1.26.0
-       k8s.io/api v0.29.0
-       k8s.io/apimachinery v0.29.0
-       k8s.io/client-go v0.29.0
+       go.uber.org/zap v1.27.0
+       k8s.io/api v0.29.2
+       k8s.io/apimachinery v0.29.3
+       k8s.io/client-go v0.29.2
 )
 
 require (
        github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // 
indirect
        github.com/ajg/form v1.5.1 // indirect
        github.com/andybalholm/brotli v1.0.4 // indirect
-       github.com/api7/etcd-adapter v0.2.3 // indirect
+       github.com/api7/etcd-adapter v0.2.4 // indirect
        github.com/api7/gopkg v0.2.0 // indirect
        github.com/aws/aws-sdk-go v1.40.56 // indirect
        github.com/beorn7/perks v1.0.1 // indirect
@@ -38,7 +38,7 @@ require (
        github.com/gin-contrib/sse v0.1.0 // indirect
        github.com/gin-gonic/gin v1.9.1 // indirect
        github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 // 
indirect
-       github.com/go-logr/logr v1.3.0 // indirect
+       github.com/go-logr/logr v1.4.1 // indirect
        github.com/go-openapi/jsonpointer v0.20.0 // indirect
        github.com/go-openapi/jsonreference v0.20.2 // indirect
        github.com/go-openapi/swag v0.22.4 // indirect
@@ -51,7 +51,7 @@ require (
        github.com/goccy/go-json v0.10.2 // indirect
        github.com/gogo/protobuf v1.3.2 // indirect
        github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // 
indirect
-       github.com/golang/protobuf v1.5.3 // indirect
+       github.com/golang/protobuf v1.5.4 // indirect
        github.com/google/btree v1.1.2 // indirect
        github.com/google/gnostic-models v0.6.8 // indirect
        github.com/google/go-cmp v0.6.0 // indirect
@@ -117,22 +117,22 @@ require (
        go.etcd.io/etcd/api/v3 v3.5.9 // indirect
        go.uber.org/multierr v1.11.0 // indirect
        golang.org/x/arch v0.3.0 // indirect
-       golang.org/x/crypto v0.17.0 // indirect
-       golang.org/x/net v0.17.0 // indirect
+       golang.org/x/crypto v0.18.0 // indirect
+       golang.org/x/net v0.20.0 // indirect
        golang.org/x/oauth2 v0.10.0 // indirect
-       golang.org/x/sync v0.4.0 // indirect
-       golang.org/x/sys v0.15.0 // indirect
-       golang.org/x/term v0.15.0 // indirect
+       golang.org/x/sync v0.6.0 // indirect
+       golang.org/x/sys v0.16.0 // indirect
+       golang.org/x/term v0.16.0 // indirect
        golang.org/x/text v0.14.0 // indirect
        golang.org/x/time v0.3.0 // indirect
-       golang.org/x/tools v0.14.0 // indirect
+       golang.org/x/tools v0.17.0 // indirect
        google.golang.org/appengine v1.6.7 // indirect
        google.golang.org/genproto v0.0.0-20230815205213-6bfd019c3878 // 
indirect
        google.golang.org/genproto/googleapis/api 
v0.0.0-20230815205213-6bfd019c3878 // indirect
        google.golang.org/genproto/googleapis/rpc 
v0.0.0-20230815205213-6bfd019c3878 // indirect
        google.golang.org/grpc v1.57.1 // indirect
        google.golang.org/grpc/examples v0.0.0-20211119181224-d542bfcee46d // 
indirect
-       google.golang.org/protobuf v1.31.0 // indirect
+       google.golang.org/protobuf v1.33.0 // indirect
        gopkg.in/inf.v0 v0.9.1 // indirect
        gopkg.in/yaml.v2 v2.4.0 // indirect
        gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/test/e2e/go.sum b/test/e2e/go.sum
index 374dbbb1..58d3d1aa 100644
--- a/test/e2e/go.sum
+++ b/test/e2e/go.sum
@@ -8,8 +8,8 @@ github.com/ajg/form v1.5.1/go.mod 
h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY
 github.com/andybalholm/brotli v1.0.4 
h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
 github.com/andybalholm/brotli v1.0.4/go.mod 
h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/antihax/optional v1.0.0/go.mod 
h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/api7/etcd-adapter v0.2.3 
h1:nb2IDli/d9WlhtObhYUtJUXs+IfGMTcXRc5Fu9IBgtk=
-github.com/api7/etcd-adapter v0.2.3/go.mod 
h1:JoLtq4IxiIw6Z+k9eRGHL0CDyfRvnNXGI0skV0EsSE8=
+github.com/api7/etcd-adapter v0.2.4 
h1:VWdDPUJPai5IdxV5dwwZF9e7Ilw7sBWwaEeFzPO2fV4=
+github.com/api7/etcd-adapter v0.2.4/go.mod 
h1:JoLtq4IxiIw6Z+k9eRGHL0CDyfRvnNXGI0skV0EsSE8=
 github.com/api7/gopkg v0.2.0 h1:+5vw6Rt9IeEpJoL2JMZFDwGDhH4aaeUJize21/3Qdzc=
 github.com/api7/gopkg v0.2.0/go.mod 
h1:LlplmjGCrkcS3nyCYpTwkdLkuNlYRYAnI8XH1qwsICw=
 github.com/api7/terratest v1.0.0 
h1:Grg0xcvNpSRZa7QzjqfTPR3lfiHk13IdIBUrfUrDmw4=
@@ -78,8 +78,9 @@ github.com/gin-gonic/gin v1.9.1/go.mod 
h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SU
 github.com/go-errors/errors v1.0.1/go.mod 
h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
 github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 
h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU=
 github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod 
h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
-github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
 github.com/go-logr/logr v1.3.0/go.mod 
h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod 
h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 github.com/go-openapi/jsonpointer v0.19.6/go.mod 
h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
 github.com/go-openapi/jsonpointer v0.20.0 
h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
 github.com/go-openapi/jsonpointer v0.20.0/go.mod 
h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
@@ -128,8 +129,8 @@ github.com/golang/protobuf v1.4.1/go.mod 
h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
 github.com/golang/protobuf v1.4.2/go.mod 
h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod 
h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod 
h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.3 
h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod 
h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 
h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod 
h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
 github.com/google/btree v1.1.2/go.mod 
h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
 github.com/google/gnostic-models v0.6.8 
h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
@@ -252,11 +253,11 @@ github.com/onsi/ginkgo v1.6.0/go.mod 
h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
 github.com/onsi/ginkgo v1.12.1/go.mod 
h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
 github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
 github.com/onsi/ginkgo v1.16.4/go.mod 
h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
-github.com/onsi/ginkgo/v2 v2.13.2 
h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
-github.com/onsi/ginkgo/v2 v2.13.2/go.mod 
h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
+github.com/onsi/ginkgo/v2 v2.17.1 
h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
+github.com/onsi/ginkgo/v2 v2.17.1/go.mod 
h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
 github.com/onsi/gomega v1.7.1/go.mod 
h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod 
h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
+github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
 github.com/pelletier/go-toml/v2 v2.0.1/go.mod 
h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
 github.com/pelletier/go-toml/v2 v2.0.9 
h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
 github.com/pelletier/go-toml/v2 v2.0.9/go.mod 
h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
@@ -356,13 +357,13 @@ go.etcd.io/etcd/api/v3 v3.5.9/go.mod 
h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+
 go.etcd.io/etcd/client/pkg/v3 v3.5.9 
h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE=
 go.etcd.io/etcd/client/v3 v3.5.9 
h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E=
 go.uber.org/atomic v1.7.0/go.mod 
h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/multierr v1.6.0/go.mod 
h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod 
h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
-go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod 
h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
 golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
@@ -371,8 +372,8 @@ golang.org/x/crypto 
v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod 
h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod 
h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod 
h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod 
h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.18.0/go.mod 
h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod 
h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod 
h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod 
h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -380,7 +381,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod 
h1:6SW0HCj/g11FgYtHl
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -400,8 +400,8 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod 
h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod 
h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod 
h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod 
h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod 
h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod 
h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
@@ -412,8 +412,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod 
h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -440,12 +440,12 @@ golang.org/x/sys 
v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod 
h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod 
h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
-golang.org/x/term v0.15.0/go.mod 
h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
+golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
+golang.org/x/term v0.16.0/go.mod 
h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -465,8 +465,8 @@ golang.org/x/tools 
v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod 
h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod 
h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod 
h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
-golang.org/x/tools v0.14.0/go.mod 
h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
+golang.org/x/tools v0.17.0/go.mod 
h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -507,10 +507,9 @@ google.golang.org/protobuf 
v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 google.golang.org/protobuf v1.24.0/go.mod 
h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
 google.golang.org/protobuf v1.25.0/go.mod 
h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod 
h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod 
h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.28.0/go.mod 
h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.31.0 
h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod 
h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.33.0 
h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod 
h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -535,12 +534,12 @@ gopkg.in/yaml.v3 v3.0.1 
h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod 
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod 
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A=
-k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA=
-k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
-k8s.io/apimachinery v0.29.0/go.mod 
h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis=
-k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8=
-k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38=
+k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
+k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
+k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
+k8s.io/apimachinery v0.29.3/go.mod 
h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
+k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg=
+k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA=
 k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
 k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
 k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 
h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
diff --git a/test/e2e/suite-plugins/suite-plugins-other/plugin_config.go 
b/test/e2e/suite-plugins/suite-plugins-other/plugin_config.go
index 0a91b837..ea4cbe9c 100644
--- a/test/e2e/suite-plugins/suite-plugins-other/plugin_config.go
+++ b/test/e2e/suite-plugins/suite-plugins-other/plugin_config.go
@@ -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")
+       })
+})

Reply via email to