[navi] Update discovery filter (#785)
diff --git a/go.mod b/go.mod
index 43a1999..6ae58bc 100644
--- a/go.mod
+++ b/go.mod
@@ -54,13 +54,14 @@
google.golang.org/grpc v1.74.2
google.golang.org/protobuf v1.36.7
gopkg.in/yaml.v3 v3.0.1
- helm.sh/helm/v3 v3.18.4
- istio.io/api v1.26.0-alpha.0.0.20250820113222-47f832b86cdd
- istio.io/client-go v1.26.0-alpha.0.0.20250820113822-8b883d128bac
- k8s.io/api v0.33.3
- k8s.io/apiextensions-apiserver v0.33.3
- k8s.io/apimachinery v0.33.3
- k8s.io/client-go v0.33.3
+ helm.sh/helm/v3 v3.18.6
+ istio.io/api v1.26.0-alpha.0.0.20250908200844-f7a34ed800ee
+ istio.io/client-go v1.26.0-alpha.0.0.20250908201345-99e026bfe54f
+ k8s.io/api v0.33.4
+ k8s.io/apiextensions-apiserver v0.33.4
+ k8s.io/apimachinery v0.33.4
+ k8s.io/client-go v0.33.4
+ k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.130.1
k8s.io/kubectl v0.33.3
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
@@ -119,7 +120,7 @@
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgraph-io/ristretto v0.0.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
- github.com/dlclark/regexp2 v1.10.0 // indirect
+ github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
@@ -141,6 +142,7 @@
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect
+ github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/goph/emperror v0.17.2 // indirect
@@ -182,7 +184,8 @@
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nikolalohinski/gonja v1.5.3 // indirect
- github.com/onsi/ginkgo/v2 v2.23.4 // indirect
+ github.com/onsi/ginkgo/v2 v2.24.0 // indirect
+ github.com/onsi/gomega v1.38.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runc v1.1.7 // indirect
@@ -194,9 +197,12 @@
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkoukk/tiktoken-go v0.1.6 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240409071808-615f978279ca // indirect
+ github.com/prometheus/client_golang v1.23.0 // indirect
+ github.com/prometheus/procfs v0.17.0 // indirect
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect
+ github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
@@ -210,17 +216,15 @@
github.com/vbatts/tar-split v0.12.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
- github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
- github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
- github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
github.com/yargevad/filepathx v1.0.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
+ go.opentelemetry.io/otel v1.37.0 // indirect
+ go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
go.starlark.net v0.0.0-20230302034142-4b1e35fe2254 // indirect
- go.uber.org/multierr v1.11.0 // indirect
- go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.3 // indirect
- golang.org/x/mod v0.26.0 // indirect
+ golang.org/x/mod v0.27.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.35.0 // indirect
@@ -231,7 +235,6 @@
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
- gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/cli-runtime v0.33.3 // indirect
diff --git a/go.sum b/go.sum
index 970219c..fbf08c2 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@
cloud.google.com/go/vertexai v0.12.0/go.mod h1:8u+d0TsvBfAAd2x5R6GMgbYhsLgo3J7lmP4bR8g2ig8=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
-github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
+github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
github.com/AssemblyAI/assemblyai-go-sdk v1.3.0 h1:AtOVgGxUycvK4P4ypP+1ZupecvFgnfH+Jsum0o5ILoU=
@@ -215,8 +215,8 @@
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
-github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
+github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/cli v23.0.1+incompatible h1:LRyWITpGzl2C9e9uGxzisptnxAn1zfZKXy13Ul2Q5oM=
github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
@@ -282,6 +282,7 @@
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@@ -483,8 +484,8 @@
github.com/nikolalohinski/gonja v1.5.3/go.mod h1:RmjwxNiXAEqcq1HeK5SSMmqFJvKOfTfXhkJv6YBtPa4=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
-github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
+github.com/onsi/ginkgo/v2 v2.24.0 h1:obZz8LAnHicNdbBqvG3ytAFx8fgza+i1IDpBVcHT2YE=
+github.com/onsi/ginkgo/v2 v2.24.0/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY=
github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o=
@@ -542,6 +543,8 @@
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
+github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sashabaranov/go-openai v1.40.5 h1:SwIlNdWflzR1Rxd1gv3pUg6pwPc6cQ2uMoHs8ai+/NY=
github.com/sashabaranov/go-openai v1.40.5/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
@@ -619,13 +622,6 @@
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
-github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
-github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
-github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
-github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
-github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc=
@@ -669,10 +665,6 @@
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
-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.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
-go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
@@ -699,8 +691,8 @@
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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
-golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
+golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
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=
@@ -782,8 +774,8 @@
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
-golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
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=
@@ -828,8 +820,6 @@
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
-gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
@@ -845,26 +835,26 @@
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
-helm.sh/helm/v3 v3.18.4 h1:pNhnHM3nAmDrxz6/UC+hfjDY4yeDATQCka2/87hkZXQ=
-helm.sh/helm/v3 v3.18.4/go.mod h1:WVnwKARAw01iEdjpEkP7Ii1tT1pTPYfM1HsakFKM3LI=
+helm.sh/helm/v3 v3.18.6 h1:S/2CqcYnNfLckkHLI0VgQbxgcDaU3N4A/46E3n9wSNY=
+helm.sh/helm/v3 v3.18.6/go.mod h1:L/dXDR2r539oPlFP1PJqKAC1CUgqHJDLkxKpDGrWnyg=
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=
-istio.io/api v1.26.0-alpha.0.0.20250820113222-47f832b86cdd h1:rXbbklkrc68YSkBExYtJHYNWLNTXP3m9H6EbYgjHtQI=
-istio.io/api v1.26.0-alpha.0.0.20250820113222-47f832b86cdd/go.mod h1:BD3qv/ekm16kvSgvSpuiDawgKhEwG97wx849CednJSg=
-istio.io/client-go v1.26.0-alpha.0.0.20250820113822-8b883d128bac h1:cig/XcnMBOfb88t1qbtnGEbHLffLnv3xQGPDYson1kI=
-istio.io/client-go v1.26.0-alpha.0.0.20250820113822-8b883d128bac/go.mod h1:0XgBG5O4fXCea2bhGlxz9/tcVZvE5tegmn7ST6/hUeQ=
-istio.io/istio v0.0.0-20250824174020-b75eb7fd7d09 h1:bQ8Yd3gJXDLZPjhGln8rG6U0FkDov9T5BNTd6fHYBD0=
-istio.io/istio v0.0.0-20250824174020-b75eb7fd7d09/go.mod h1:/5U2lRJulLgMvq5m2d8pkrGSkboNtW5QT8iG4u2ND78=
-k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
-k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
-k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs=
-k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8=
-k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
-k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
+istio.io/api v1.26.0-alpha.0.0.20250908200844-f7a34ed800ee h1:pDLJDbgzc69hw3EQHIhO+j/efHketfwARg3eL+QIqss=
+istio.io/api v1.26.0-alpha.0.0.20250908200844-f7a34ed800ee/go.mod h1:BD3qv/ekm16kvSgvSpuiDawgKhEwG97wx849CednJSg=
+istio.io/client-go v1.26.0-alpha.0.0.20250908201345-99e026bfe54f h1:gTRu3JTMDWZ2Qi7RcYIHXK2PPmiCtRAZ47QOiSooCxM=
+istio.io/client-go v1.26.0-alpha.0.0.20250908201345-99e026bfe54f/go.mod h1:k9fittgsfNR2AkUGLYRkEyTbSa1marHI4oqsGkE4AEI=
+k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk=
+k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc=
+k8s.io/apiextensions-apiserver v0.33.4 h1:rtq5SeXiDbXmSwxsF0MLe2Mtv3SwprA6wp+5qh/CrOU=
+k8s.io/apiextensions-apiserver v0.33.4/go.mod h1:mWXcZQkQV1GQyxeIjYApuqsn/081hhXPZwZ2URuJeSs=
+k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s=
+k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/cli-runtime v0.33.3 h1:Dgy4vPjNIu8LMJBSvs8W0LcdV0PX/8aGG1DA1W8lklA=
k8s.io/cli-runtime v0.33.3/go.mod h1:yklhLklD4vLS8HNGgC9wGiuHWze4g7x6XQZ+8edsKEo=
-k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
-k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
+k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw=
+k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY=
+k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
+k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
diff --git a/navigator/pkg/bootstrap/server.go b/navigator/pkg/bootstrap/server.go
index 6b6a5e3..3882b72 100644
--- a/navigator/pkg/bootstrap/server.go
+++ b/navigator/pkg/bootstrap/server.go
@@ -31,12 +31,15 @@
"github.com/apache/dubbo-kubernetes/pkg/h2c"
dubbokeepalive "github.com/apache/dubbo-kubernetes/pkg/keepalive"
kubelib "github.com/apache/dubbo-kubernetes/pkg/kube"
+ "github.com/apache/dubbo-kubernetes/pkg/kube/kclient"
+ "github.com/apache/dubbo-kubernetes/pkg/kube/namespace"
"github.com/apache/dubbo-kubernetes/pkg/network"
"github.com/fsnotify/fsnotify"
"golang.org/x/net/http2"
"google.golang.org/grpc"
+ corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
- "k8s.io/klog/v2"
+ "k8s.io/klog"
"net"
"net/http"
"os"
@@ -93,6 +96,13 @@
}
s.initMeshConfiguration(args, s.fileWatcher)
+ if s.kubeClient != nil {
+ // // Build a namespace watcher. This must have no filter, since this is our input to the filter itself.
+ namespaces := kclient.New[*corev1.Namespace](s.kubeClient)
+ filter := namespace.NewDiscoveryNamespacesFilter(namespaces, s.environment.Watcher, s.internalStop)
+ s.kubeClient = kubelib.SetObjectFilter(s.kubeClient, filter)
+ }
+
return s, nil
}
diff --git a/pkg/config/schema/gvr/resource.gen.go b/pkg/config/schema/gvr/resource.gen.go
index 40402ff..1fd1e2e 100644
--- a/pkg/config/schema/gvr/resource.gen.go
+++ b/pkg/config/schema/gvr/resource.gen.go
@@ -41,6 +41,20 @@
switch g {
case ConfigMap:
return false
+ case Namespace:
+ return true
+ case DaemonSet:
+ return false
+ case Deployment:
+ return false
+ case StatefulSet:
+ return false
+ case Secret:
+ return false
+ case Service:
+ return false
+ case ServiceAccount:
+ return false
}
return false
}
diff --git a/pkg/config/schema/kubetypes/resources.gen.go b/pkg/config/schema/kubetypes/resources.gen.go
index 9e48eac..0eb976b 100644
--- a/pkg/config/schema/kubetypes/resources.gen.go
+++ b/pkg/config/schema/kubetypes/resources.gen.go
@@ -30,8 +30,9 @@
return gvk.ConfigMap, true
case *istioioapimeshv1alpha1.MeshConfig:
return gvk.MeshConfig, true
+ case *k8sioapicorev1.Namespace:
+ return gvk.Namespace, true
default:
return config.GroupVersionKind{}, false
}
-
}
diff --git a/pkg/kube/client.go b/pkg/kube/client.go
index ed208da..638db0f 100644
--- a/pkg/kube/client.go
+++ b/pkg/kube/client.go
@@ -23,8 +23,10 @@
"github.com/apache/dubbo-kubernetes/pkg/cluster"
"github.com/apache/dubbo-kubernetes/pkg/kube/collections"
"github.com/apache/dubbo-kubernetes/pkg/kube/informerfactory"
+ "github.com/apache/dubbo-kubernetes/pkg/kube/kubetypes"
"github.com/apache/dubbo-kubernetes/pkg/lazy"
"github.com/apache/dubbo-kubernetes/pkg/sleep"
+ "go.uber.org/atomic"
istioclient "istio.io/client-go/pkg/clientset/versioned"
kubeExtClient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/api/meta"
@@ -37,25 +39,28 @@
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
- "k8s.io/klog/v2"
+ "k8s.io/klog"
"net/http"
"time"
)
type client struct {
- extSet kubeExtClient.Interface
- config *rest.Config
- revision string
- clientFactory *clientFactory
- version lazy.Lazy[*kubeVersion.Info]
- informerFactory informerfactory.InformerFactory
- dynamic dynamic.Interface
- kube kubernetes.Interface
- mapper meta.ResettableRESTMapper
- metadata metadata.Interface
- http *http.Client
- dubbo istioclient.Interface
- clusterID cluster.ID
+ extSet kubeExtClient.Interface
+ config *rest.Config
+ revision string
+ clientFactory *clientFactory
+ version lazy.Lazy[*kubeVersion.Info]
+ informerFactory informerfactory.InformerFactory
+ dynamic dynamic.Interface
+ kube kubernetes.Interface
+ mapper meta.ResettableRESTMapper
+ metadata metadata.Interface
+ http *http.Client
+ objectFilter kubetypes.DynamicObjectFilter
+ clusterID cluster.ID
+ informerWatchesPending *atomic.Int32
+ crdWatcher kubetypes.CrdWatcher
+ istio istioclient.Interface
}
type Client interface {
@@ -71,7 +76,13 @@
Informers() informerfactory.InformerFactory
+ ObjectFilter() kubetypes.DynamicObjectFilter
+
ClusterID() cluster.ID
+
+ CrdWatcher() kubetypes.CrdWatcher
+
+ Shutdown()
}
type CLIClient interface {
@@ -192,6 +203,14 @@
return c.informerFactory
}
+func (c *client) ObjectFilter() kubetypes.DynamicObjectFilter {
+ return c.objectFilter
+}
+
+func (c *client) CrdWatcher() kubetypes.CrdWatcher {
+ return c.crdWatcher
+}
+
func (c *client) DynamicClientFor(gvk schema.GroupVersionKind, obj *unstructured.Unstructured, namespace string) (dynamic.ResourceInterface, error) {
gvr, namespaced := c.bestEffortToGVR(gvk, obj, namespace)
var dr dynamic.ResourceInterface
@@ -279,6 +298,11 @@
c.informerFactory.Shutdown()
}
+func SetObjectFilter(c Client, filter kubetypes.DynamicObjectFilter) Client {
+ c.(*client).objectFilter = filter
+ return c
+}
+
func WithCluster(id cluster.ID) ClientOption {
return func(c CLIClient) CLIClient {
client := c.(*client)
diff --git a/pkg/kube/controllers/common.go b/pkg/kube/controllers/common.go
index a0d4861..b15e8bf 100644
--- a/pkg/kube/controllers/common.go
+++ b/pkg/kube/controllers/common.go
@@ -111,3 +111,7 @@
}
return o
}
+
+func ExtractObject(obj any) Object {
+ return Extract[Object](obj)
+}
diff --git a/pkg/kube/kclient/client.go b/pkg/kube/kclient/client.go
index fd14ce5..31df02f 100644
--- a/pkg/kube/kclient/client.go
+++ b/pkg/kube/kclient/client.go
@@ -48,6 +48,12 @@
client kube.Client
}
+func New[T controllers.ComparableObject](c kube.Client) Client[T] {
+ return NewFiltered[T](c, Filter{})
+}
+
+type Filter = kubetypes.Filter
+
func NewFiltered[T controllers.ComparableObject](c kube.Client, filter Filter) Client[T] {
gvr := types.MustToGVR[T](types.MustGVKFromType[T]())
inf := kubeclient.GetInformerFiltered[T](c, ToOpts(c, gvr, filter), gvr)
@@ -57,8 +63,6 @@
}
}
-type Filter = kubetypes.Filter
-
func ToOpts(c kube.Client, gvr schema.GroupVersionResource, filter Filter) kubetypes.InformerOptions {
ns := filter.Namespace
if !dubbogvr.IsClusterScoped(gvr) && ns == "" {
@@ -184,6 +188,20 @@
return cast
}
+func (n *informerClient[T]) HasSynced() bool {
+ if !n.informer.HasSynced() {
+ return false
+ }
+ n.handlerMu.RLock()
+ defer n.handlerMu.RUnlock()
+ for _, g := range n.registeredHandlers {
+ if !g.registration.HasSynced() {
+ return false
+ }
+ }
+ return true
+}
+
func (n *informerClient[T]) HasSyncedIgnoringHandlers() bool {
return n.informer.HasSynced()
}
diff --git a/pkg/kube/kclient/interfaces.go b/pkg/kube/kclient/interfaces.go
index 95439df..b50e57c 100644
--- a/pkg/kube/kclient/interfaces.go
+++ b/pkg/kube/kclient/interfaces.go
@@ -52,6 +52,7 @@
Start(stop <-chan struct{})
ShutdownHandlers()
ShutdownHandler(registration cache.ResourceEventHandlerRegistration)
+ HasSynced() bool
HasSyncedIgnoringHandlers() bool
AddEventHandler(h cache.ResourceEventHandler) cache.ResourceEventHandlerRegistration
Index(name string, extract func(o T) []string) RawIndexer
diff --git a/pkg/kube/kubetypes/types.go b/pkg/kube/kubetypes/types.go
index 989de8c..5b6aec0 100644
--- a/pkg/kube/kubetypes/types.go
+++ b/pkg/kube/kubetypes/types.go
@@ -23,6 +23,7 @@
"github.com/apache/dubbo-kubernetes/pkg/util/sets"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
)
@@ -68,3 +69,24 @@
// AddHandler registers a handler on namespace, which will be triggered when namespace selected or deselected.
AddHandler(func(selected, deselected sets.String))
}
+
+type staticFilter struct {
+ f func(obj interface{}) bool
+}
+
+var _ DynamicObjectFilter = staticFilter{}
+
+func (s staticFilter) Filter(obj any) bool {
+ return s.f(obj)
+}
+
+func (s staticFilter) AddHandler(func(selected, deselected sets.String)) {
+ // Do nothing
+}
+
+type CrdWatcher interface {
+ HasSynced() bool
+ KnownOrCallback(s schema.GroupVersionResource, f func(stop <-chan struct{})) bool
+ WaitForCRD(s schema.GroupVersionResource, stop <-chan struct{}) bool
+ Run(stop <-chan struct{})
+}
diff --git a/pkg/kube/namespace/filter.go b/pkg/kube/namespace/filter.go
new file mode 100644
index 0000000..b4a2d66
--- /dev/null
+++ b/pkg/kube/namespace/filter.go
@@ -0,0 +1,282 @@
+package namespace
+
+import (
+ "fmt"
+ "k8s.io/klog/v2"
+ "sync"
+
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/apimachinery/pkg/selection"
+
+ "github.com/apache/dubbo-kubernetes/pkg/config/mesh"
+ "github.com/apache/dubbo-kubernetes/pkg/kube"
+ "github.com/apache/dubbo-kubernetes/pkg/kube/controllers"
+ "github.com/apache/dubbo-kubernetes/pkg/kube/kclient"
+ "github.com/apache/dubbo-kubernetes/pkg/kube/kubetypes"
+ "github.com/apache/dubbo-kubernetes/pkg/util/sets"
+ "github.com/apache/dubbo-kubernetes/pkg/util/slices"
+ meshapi "istio.io/api/mesh/v1alpha1"
+)
+
+type DiscoveryFilter func(obj any) bool
+
+type discoveryNamespacesFilter struct {
+ lock sync.RWMutex
+ namespaces kclient.Client[*corev1.Namespace]
+ discoveryNamespaces sets.String
+ discoverySelectors []labels.Selector // nil if discovery selectors are not specified, permits all namespaces for discovery
+ handlers []func(added, removed sets.String)
+}
+
+func NewDiscoveryNamespacesFilter(
+ namespaces kclient.Client[*corev1.Namespace],
+ mesh mesh.Watcher,
+ stop <-chan struct{},
+) kubetypes.DynamicObjectFilter {
+ // convert LabelSelectors to Selectors
+ f := &discoveryNamespacesFilter{
+ namespaces: namespaces,
+ discoveryNamespaces: sets.New[string](),
+ }
+ mesh.AddMeshHandler(func() {
+ f.selectorsChanged(mesh.Mesh().GetDiscoverySelectors(), true)
+ })
+
+ namespaces.AddEventHandler(controllers.EventHandler[*corev1.Namespace]{
+ AddFunc: func(ns *corev1.Namespace) {
+ f.lock.Lock()
+ created := f.namespaceCreatedLocked(ns.ObjectMeta)
+ f.lock.Unlock()
+ // In rare cases, a namespace may be created after objects in the namespace, because there is no synchronization between watches
+ // So we need to notify if we started selecting namespace
+ if created {
+ f.notifyHandlers(sets.New(ns.Name), nil)
+ }
+ },
+ UpdateFunc: func(oldObj, newObj *corev1.Namespace) {
+ f.lock.Lock()
+ membershipChanged, namespaceAdded := f.namespaceUpdatedLocked(oldObj.ObjectMeta, newObj.ObjectMeta)
+ f.lock.Unlock()
+ if membershipChanged {
+ added := sets.New(newObj.Name)
+ var removed sets.String
+ if !namespaceAdded {
+ removed = added
+ added = nil
+ }
+ f.notifyHandlers(added, removed)
+ }
+ },
+ DeleteFunc: func(ns *corev1.Namespace) {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ // No need to notify handlers for deletes. The namespace was deleted, so the object will be as well (and a delete could not de-select).
+ // Note that specifically for the edge case of a Namespace watcher that is filtering, this will ignore deletes we should
+ // otherwise send.
+ // See kclient.applyDynamicFilter for rationale.
+ f.namespaceDeletedLocked(ns.ObjectMeta)
+ },
+ })
+ // Start namespaces and wait for it to be ready now. This is required for subsequent users, so we want to block
+ namespaces.Start(stop)
+ kube.WaitForCacheSync("discovery filter", stop, namespaces.HasSynced)
+ f.selectorsChanged(mesh.Mesh().GetDiscoverySelectors(), false)
+ return f
+}
+
+func (d *discoveryNamespacesFilter) notifyHandlers(added sets.Set[string], removed sets.String) {
+ // Clone handlers; we handle dynamic handlers so they can change after the filter has started.
+ // Important: handlers are not called under the lock. If they are, then handlers which eventually call discoveryNamespacesFilter.Filter
+ // (as some do in the codebase currently, via kclient.List), will deadlock.
+ d.lock.RLock()
+ handlers := slices.Clone(d.handlers)
+ d.lock.RUnlock()
+ for _, h := range handlers {
+ h(added, removed)
+ }
+}
+
+func (d *discoveryNamespacesFilter) Filter(obj any) bool {
+ // When an object is deleted, obj could be a DeletionFinalStateUnknown marker item.
+ ns, ok := extractObjectNamespace(obj)
+ if !ok {
+ return false
+ }
+ if ns == "" {
+ // Cluster scoped resources. Always included
+ return true
+ }
+
+ d.lock.RLock()
+ defer d.lock.RUnlock()
+ // permit all objects if discovery selectors are not specified
+ if len(d.discoverySelectors) == 0 {
+ return true
+ }
+
+ // permit if object resides in a namespace labeled for discovery
+ return d.discoveryNamespaces.Contains(ns)
+}
+
+func extractObjectNamespace(obj any) (string, bool) {
+ if ns, ok := obj.(string); ok {
+ return ns, true
+ }
+ object := controllers.ExtractObject(obj)
+ if object == nil {
+ // When an object is deleted, obj could be a DeletionFinalStateUnknown marker item.
+ return "", false
+ }
+ if _, ok := object.(*corev1.Namespace); ok {
+ return object.GetName(), true
+ }
+ return object.GetNamespace(), true
+}
+
+func LabelSelectorAsSelector(ps *meshapi.LabelSelector) (labels.Selector, error) {
+ if ps == nil {
+ return labels.Nothing(), nil
+ }
+ if len(ps.MatchLabels)+len(ps.MatchExpressions) == 0 {
+ return labels.Everything(), nil
+ }
+ requirements := make([]labels.Requirement, 0, len(ps.MatchLabels)+len(ps.MatchExpressions))
+ for k, v := range ps.MatchLabels {
+ r, err := labels.NewRequirement(k, selection.Equals, []string{v})
+ if err != nil {
+ return nil, err
+ }
+ requirements = append(requirements, *r)
+ }
+ for _, expr := range ps.MatchExpressions {
+ var op selection.Operator
+ switch metav1.LabelSelectorOperator(expr.Operator) {
+ case metav1.LabelSelectorOpIn:
+ op = selection.In
+ case metav1.LabelSelectorOpNotIn:
+ op = selection.NotIn
+ case metav1.LabelSelectorOpExists:
+ op = selection.Exists
+ case metav1.LabelSelectorOpDoesNotExist:
+ op = selection.DoesNotExist
+ default:
+ return nil, fmt.Errorf("%q is not a valid label selector operator", expr.Operator)
+ }
+ r, err := labels.NewRequirement(expr.Key, op, append([]string(nil), expr.Values...))
+ if err != nil {
+ return nil, err
+ }
+ requirements = append(requirements, *r)
+ }
+ selector := labels.NewSelector()
+ selector = selector.Add(requirements...)
+ return selector, nil
+}
+
+// SelectorsChanged initializes the discovery filter state with the discovery selectors and selected namespaces
+func (d *discoveryNamespacesFilter) selectorsChanged(
+ discoverySelectors []*meshapi.LabelSelector,
+ notify bool,
+) {
+ // Call closure to allow safe defer lock handling
+ selectedNamespaces, deselectedNamespaces := func() (sets.String, sets.String) {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+ var selectors []labels.Selector
+ newDiscoveryNamespaces := sets.New[string]()
+
+ namespaceList := d.namespaces.List("", labels.Everything())
+
+ // convert LabelSelectors to Selectors
+ for _, selector := range discoverySelectors {
+ ls, err := LabelSelectorAsSelector(selector)
+ if err != nil {
+ klog.Errorf("error initializing discovery namespaces filter, invalid discovery selector: %v", err)
+ return nil, nil
+ }
+ selectors = append(selectors, ls)
+ }
+
+ // range over all namespaces to get discovery namespaces
+ for _, ns := range namespaceList {
+ for _, selector := range selectors {
+ if selector.Matches(labels.Set(ns.Labels)) {
+ newDiscoveryNamespaces.Insert(ns.Name)
+ }
+ }
+ // omitting discoverySelectors indicates discovering all namespaces
+ if len(selectors) == 0 {
+ for _, ns := range namespaceList {
+ newDiscoveryNamespaces.Insert(ns.Name)
+ }
+ }
+ }
+
+ // update filter state
+ oldDiscoveryNamespaces := d.discoveryNamespaces
+ d.discoveryNamespaces = newDiscoveryNamespaces
+ d.discoverySelectors = selectors
+ if notify {
+ selectedNamespaces := newDiscoveryNamespaces.Difference(oldDiscoveryNamespaces)
+ deselectedNamespaces := oldDiscoveryNamespaces.Difference(newDiscoveryNamespaces)
+ return selectedNamespaces, deselectedNamespaces
+ }
+ return nil, nil
+ }()
+ if notify {
+ d.notifyHandlers(selectedNamespaces, deselectedNamespaces)
+ }
+}
+
+// namespaceCreated: if newly created namespace is selected, update namespace membership
+func (d *discoveryNamespacesFilter) namespaceCreatedLocked(ns metav1.ObjectMeta) (membershipChanged bool) {
+ if d.isSelectedLocked(ns.Labels) {
+ d.discoveryNamespaces.Insert(ns.Name)
+ // Do not trigger update when there are no selectors. This avoids possibility of double namespace ADDs
+ return len(d.discoverySelectors) != 0
+ }
+ return false
+}
+
+// namespaceUpdatedLocked : if updated namespace was a member and no longer selected, or was not a member and now selected, update namespace membership
+func (d *discoveryNamespacesFilter) namespaceUpdatedLocked(oldNs, newNs metav1.ObjectMeta) (membershipChanged bool, namespaceAdded bool) {
+ if d.discoveryNamespaces.Contains(oldNs.Name) && !d.isSelectedLocked(newNs.Labels) {
+ d.discoveryNamespaces.Delete(oldNs.Name)
+ return true, false
+ }
+ if !d.discoveryNamespaces.Contains(oldNs.Name) && d.isSelectedLocked(newNs.Labels) {
+ d.discoveryNamespaces.Insert(oldNs.Name)
+ return true, true
+ }
+ return false, false
+}
+
+// namespaceDeletedLocked : if deleted namespace was a member, remove it
+func (d *discoveryNamespacesFilter) namespaceDeletedLocked(ns metav1.ObjectMeta) {
+ d.discoveryNamespaces.Delete(ns.Name)
+}
+
+// AddHandler registers a handler on namespace, which will be triggered when namespace selected or deselected.
+// If the namespaces have been synced, trigger the new added handler.
+func (d *discoveryNamespacesFilter) AddHandler(f func(added, removed sets.String)) {
+ d.lock.Lock()
+ defer d.lock.Unlock()
+ d.handlers = append(d.handlers, f)
+}
+
+func (d *discoveryNamespacesFilter) isSelectedLocked(labels labels.Set) bool {
+ // permit all objects if discovery selectors are not specified
+ if len(d.discoverySelectors) == 0 {
+ return true
+ }
+
+ for _, selector := range d.discoverySelectors {
+ if selector.Matches(labels) {
+ return true
+ }
+ }
+
+ return false
+}