This is an automated email from the ASF dual-hosted git repository.
mfordjody pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git
The following commit(s) were added to refs/heads/master by this push:
new be2e9808 Add breaker features (#929)
be2e9808 is described below
commit be2e9808f94ed2dc3d99f9181c638daa568d29a8
Author: mfordjody <[email protected]>
AuthorDate: Mon Jun 29 11:26:21 2026 +0800
Add breaker features (#929)
* Rename xds client and server
* Add breaker features
---
.../pkg/bootstrap/proxyless_grpc_controller.go | 2 +-
dubbod/discovery/pkg/bootstrap/server.go | 5 +-
.../pkg/config/kube/crdclient/types.gen.go | 53 ++++++
.../config/kube/gateway/deployment_controller.go | 183 ++++++++++++++++++++-
.../kube/gateway/deployment_controller_test.go | 98 ++++++++++-
go.mod | 3 +
manifests/charts/base/files/crd-all.gen.yaml | 151 +++++++++++++++++
manifests/charts/dubbod/templates/clusterrole.yaml | 3 +
.../schema/codegen/templates/clients.go.tmpl | 1 +
.../schema/codegen/templates/crdclient.go.tmpl | 1 +
pkg/config/schema/codegen/templates/types.go.tmpl | 1 +
pkg/config/schema/collections/collections.gen.go | 20 +++
pkg/config/schema/gvk/resources.gen.go | 7 +
pkg/config/schema/gvr/resources.gen.go | 3 +
pkg/config/schema/kind/resources.gen.go | 5 +
pkg/config/schema/kubeclient/resources.gen.go | 14 ++
pkg/config/schema/kubetypes/resources.gen.go | 6 +
pkg/config/schema/metadata.yaml | 9 +
18 files changed, 554 insertions(+), 11 deletions(-)
diff --git a/dubbod/discovery/pkg/bootstrap/proxyless_grpc_controller.go
b/dubbod/discovery/pkg/bootstrap/proxyless_grpc_controller.go
index 616c3f74..57b68813 100644
--- a/dubbod/discovery/pkg/bootstrap/proxyless_grpc_controller.go
+++ b/dubbod/discovery/pkg/bootstrap/proxyless_grpc_controller.go
@@ -238,7 +238,7 @@ func proxylessGRPCRuntimeConfigNeedsUpdate(req
*discoverymodel.PushRequest) bool
}
for cfg := range req.ConfigsUpdated {
switch cfg.Kind {
- case kind.HTTPRoute, kind.PeerAuthentication,
kind.RequestAuthentication, kind.AuthorizationPolicy, kind.Service,
kind.EndpointSlice, kind.Endpoints, kind.Pod, kind.Namespace:
+ case kind.HTTPRoute, kind.CircuitBreakerPolicy,
kind.PeerAuthentication, kind.RequestAuthentication, kind.AuthorizationPolicy,
kind.Service, kind.EndpointSlice, kind.Endpoints, kind.Pod, kind.Namespace:
return true
}
}
diff --git a/dubbod/discovery/pkg/bootstrap/server.go
b/dubbod/discovery/pkg/bootstrap/server.go
index f1330ac9..f17a7827 100644
--- a/dubbod/discovery/pkg/bootstrap/server.go
+++ b/dubbod/discovery/pkg/bootstrap/server.go
@@ -511,6 +511,8 @@ func (s *Server) initRegistryEventHandlers() {
configKind = kind.KubernetesGateway
case "HTTPRoute":
configKind = kind.HTTPRoute
+ case "CircuitBreakerPolicy":
+ configKind = kind.CircuitBreakerPolicy
default:
log.Debugf("unknown schema identifier %s for %v,
skipping", schemaID, cfg.GroupVersionKind)
return
@@ -532,7 +534,8 @@ func (s *Server) initRegistryEventHandlers() {
needsFullPush := configKind == kind.PeerAuthentication ||
configKind == kind.RequestAuthentication ||
configKind == kind.AuthorizationPolicy ||
- configKind == kind.HTTPRoute
+ configKind == kind.HTTPRoute ||
+ configKind == kind.CircuitBreakerPolicy
// Trigger ConfigUpdate to push changes to all connected proxies
s.XDSServer.ConfigUpdate(&model.PushRequest{
diff --git a/dubbod/discovery/pkg/config/kube/crdclient/types.gen.go
b/dubbod/discovery/pkg/config/kube/crdclient/types.gen.go
index 23ad57da..c5bf20ef 100755
--- a/dubbod/discovery/pkg/config/kube/crdclient/types.gen.go
+++ b/dubbod/discovery/pkg/config/kube/crdclient/types.gen.go
@@ -15,7 +15,9 @@ import (
"github.com/apache/dubbo-kubernetes/pkg/kube"
githubcomkdubboapimetav1alpha1 "github.com/kdubbo/api/meta/v1alpha1"
+ githubcomkdubboapinetworkingv1alpha3
"github.com/kdubbo/api/networking/v1alpha3"
githubcomkdubboapisecurityv1alpha3
"github.com/kdubbo/api/security/v1alpha3"
+ apigithubcomapachedubbokubernetesapinetworkingv1alpha3
"github.com/kdubbo/client-go/pkg/apis/networking/v1alpha3"
apigithubcomapachedubbokubernetesapisecurityv1alpha3
"github.com/kdubbo/client-go/pkg/apis/security/v1alpha3"
k8sioapiadmissionregistrationv1 "k8s.io/api/admissionregistration/v1"
k8sioapiappsv1 "k8s.io/api/apps/v1"
@@ -35,6 +37,11 @@ func create(c kube.Client, cfg config.Config, objMeta
metav1.ObjectMeta) (metav1
ObjectMeta: objMeta,
Spec:
*(cfg.Spec.(*githubcomkdubboapisecurityv1alpha3.AuthorizationPolicy)),
}, metav1.CreateOptions{})
+ case gvk.CircuitBreakerPolicy:
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(cfg.Namespace).Create(context.TODO(),
&apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy{
+ ObjectMeta: objMeta,
+ Spec:
*(cfg.Spec.(*githubcomkdubboapinetworkingv1alpha3.CircuitBreakerPolicy)),
+ }, metav1.CreateOptions{})
case gvk.GatewayClass:
return
c.GatewayAPI().GatewayV1().GatewayClasses().Create(context.TODO(),
&sigsk8siogatewayapiapisv1.GatewayClass{
ObjectMeta: objMeta,
@@ -72,6 +79,11 @@ func update(c kube.Client, cfg config.Config, objMeta
metav1.ObjectMeta) (metav1
ObjectMeta: objMeta,
Spec:
*(cfg.Spec.(*githubcomkdubboapisecurityv1alpha3.AuthorizationPolicy)),
}, metav1.UpdateOptions{})
+ case gvk.CircuitBreakerPolicy:
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(cfg.Namespace).Update(context.TODO(),
&apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy{
+ ObjectMeta: objMeta,
+ Spec:
*(cfg.Spec.(*githubcomkdubboapinetworkingv1alpha3.CircuitBreakerPolicy)),
+ }, metav1.UpdateOptions{})
case gvk.GatewayClass:
return
c.GatewayAPI().GatewayV1().GatewayClasses().Update(context.TODO(),
&sigsk8siogatewayapiapisv1.GatewayClass{
ObjectMeta: objMeta,
@@ -109,6 +121,11 @@ func updateStatus(c kube.Client, cfg config.Config,
objMeta metav1.ObjectMeta) (
ObjectMeta: objMeta,
Status:
*(cfg.Status.(*githubcomkdubboapimetav1alpha1.DubboStatus)),
}, metav1.UpdateOptions{})
+ case gvk.CircuitBreakerPolicy:
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(cfg.Namespace).UpdateStatus(context.TODO(),
&apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy{
+ ObjectMeta: objMeta,
+ Status:
*(cfg.Status.(*githubcomkdubboapimetav1alpha1.DubboStatus)),
+ }, metav1.UpdateOptions{})
case gvk.GatewayClass:
return
c.GatewayAPI().GatewayV1().GatewayClasses().UpdateStatus(context.TODO(),
&sigsk8siogatewayapiapisv1.GatewayClass{
ObjectMeta: objMeta,
@@ -159,6 +176,21 @@ func patch(c kube.Client, orig config.Config, origMeta
metav1.ObjectMeta, mod co
}
return
c.Dubbo().SecurityV1alpha3().AuthorizationPolicies(orig.Namespace).
Patch(context.TODO(), orig.Name, typ, patchBytes,
metav1.PatchOptions{FieldManager: "pilot-discovery"})
+ case gvk.CircuitBreakerPolicy:
+ oldRes :=
&apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy{
+ ObjectMeta: origMeta,
+ Spec:
*(orig.Spec.(*githubcomkdubboapinetworkingv1alpha3.CircuitBreakerPolicy)),
+ }
+ modRes :=
&apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy{
+ ObjectMeta: modMeta,
+ Spec:
*(mod.Spec.(*githubcomkdubboapinetworkingv1alpha3.CircuitBreakerPolicy)),
+ }
+ patchBytes, err := genPatchBytes(oldRes, modRes, typ)
+ if err != nil {
+ return nil, err
+ }
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(orig.Namespace).
+ Patch(context.TODO(), orig.Name, typ, patchBytes,
metav1.PatchOptions{FieldManager: "pilot-discovery"})
case gvk.GatewayClass:
oldRes := &sigsk8siogatewayapiapisv1.GatewayClass{
ObjectMeta: origMeta,
@@ -247,6 +279,8 @@ func delete(c kube.Client, typ config.GroupVersionKind,
name, namespace string,
switch typ {
case gvk.AuthorizationPolicy:
return
c.Dubbo().SecurityV1alpha3().AuthorizationPolicies(namespace).Delete(context.TODO(),
name, deleteOptions)
+ case gvk.CircuitBreakerPolicy:
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(namespace).Delete(context.TODO(),
name, deleteOptions)
case gvk.GatewayClass:
return
c.GatewayAPI().GatewayV1().GatewayClasses().Delete(context.TODO(), name,
deleteOptions)
case gvk.HTTPRoute:
@@ -282,6 +316,25 @@ var translationMap = map[config.GroupVersionKind]func(r
runtime.Object) config.C
Status: &obj.Status,
}
},
+ gvk.CircuitBreakerPolicy: func(r runtime.Object) config.Config {
+ obj :=
r.(*apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy)
+ return config.Config{
+ Meta: config.Meta{
+ GroupVersionKind: gvk.CircuitBreakerPolicy,
+ Name: obj.Name,
+ Namespace: obj.Namespace,
+ Labels: obj.Labels,
+ Annotations: obj.Annotations,
+ ResourceVersion: obj.ResourceVersion,
+ CreationTimestamp: obj.CreationTimestamp.Time,
+ OwnerReferences: obj.OwnerReferences,
+ UID: string(obj.UID),
+ Generation: obj.Generation,
+ },
+ Spec: &obj.Spec,
+ Status: &obj.Status,
+ }
+ },
gvk.ConfigMap: func(r runtime.Object) config.Config {
obj := r.(*k8sioapicorev1.ConfigMap)
return config.Config{
diff --git a/dubbod/discovery/pkg/config/kube/gateway/deployment_controller.go
b/dubbod/discovery/pkg/config/kube/gateway/deployment_controller.go
index e6020d7b..324e07ec 100644
--- a/dubbod/discovery/pkg/config/kube/gateway/deployment_controller.go
+++ b/dubbod/discovery/pkg/config/kube/gateway/deployment_controller.go
@@ -42,13 +42,19 @@ import (
"github.com/apache/dubbo-kubernetes/dubbod/discovery/pkg/features"
"github.com/apache/dubbo-kubernetes/dubbod/discovery/pkg/model"
"github.com/apache/dubbo-kubernetes/pkg/cluster"
+ "github.com/apache/dubbo-kubernetes/pkg/config"
"github.com/apache/dubbo-kubernetes/pkg/config/constants"
+ "github.com/apache/dubbo-kubernetes/pkg/config/schema/gvk"
"github.com/apache/dubbo-kubernetes/pkg/config/schema/gvr"
"github.com/apache/dubbo-kubernetes/pkg/kube"
"github.com/apache/dubbo-kubernetes/pkg/kube/controllers"
"github.com/apache/dubbo-kubernetes/pkg/kube/inject"
"github.com/apache/dubbo-kubernetes/pkg/kube/kclient"
dubbolog "github.com/apache/dubbo-kubernetes/pkg/log"
+ networking "github.com/kdubbo/api/networking/v1alpha3"
+ clientnetworking
"github.com/kdubbo/client-go/pkg/apis/networking/v1alpha3"
+ "google.golang.org/protobuf/types/known/durationpb"
+ "google.golang.org/protobuf/types/known/wrapperspb"
)
var logger = dubbolog.RegisterScope("gateway-deployment-controller", "gateway
deployment controller debugging")
@@ -117,6 +123,7 @@ type DeploymentController struct {
serviceAccounts kclient.Client[*corev1.ServiceAccount]
configMaps kclient.Client[*corev1.ConfigMap]
httpRoutes kclient.Client[*gateway.HTTPRoute]
+ circuitBreakers kclient.Client[*clientnetworking.CircuitBreakerPolicy]
namespaces kclient.Client[*corev1.Namespace]
tagWatcher TagWatcher
revision string
@@ -221,6 +228,13 @@ func NewDeploymentController(
}
}))
+ dc.circuitBreakers =
kclient.NewFiltered[*clientnetworking.CircuitBreakerPolicy](client, filter)
+ dc.circuitBreakers.AddEventHandler(controllers.ObjectHandler(func(o
controllers.Object) {
+ for _, gw := range dc.gateways.List(metav1.NamespaceAll,
klabels.Everything()) {
+ dc.queue.AddObject(gw)
+ }
+ }))
+
// Namespace is a cluster-scoped resource, use New instead of
NewFiltered
dc.namespaces = kclient.New[*corev1.Namespace](client)
dc.namespaces.AddEventHandler(controllers.ObjectHandler(func(o
controllers.Object) {
@@ -270,6 +284,7 @@ func (d *DeploymentController) Run(stop <-chan struct{}) {
d.serviceAccounts.HasSynced,
d.configMaps.HasSynced,
d.httpRoutes.HasSynced,
+ d.circuitBreakers.HasSynced,
d.gateways.HasSynced,
d.gatewayClasses.HasSynced,
)
@@ -285,6 +300,7 @@ func (d *DeploymentController) Run(stop <-chan struct{}) {
d.serviceAccounts,
d.configMaps,
d.httpRoutes,
+ d.circuitBreakers,
d.gateways,
d.gatewayClasses,
)
@@ -479,8 +495,26 @@ type dxgateWeightedCluster struct {
}
type dxgateCluster struct {
- Name string `json:"name" yaml:"name"`
- Endpoints []dxgateEndpoint `json:"endpoints" yaml:"endpoints"`
+ Name string `json:"name" yaml:"name"`
+ Endpoints []dxgateEndpoint `json:"endpoints"
yaml:"endpoints"`
+ CircuitBreaker *dxgateCircuitBreaker
`json:"circuit_breaker,omitempty" yaml:"circuit_breaker,omitempty"`
+ Outlier *dxgateOutlierDetection
`json:"outlier_detection,omitempty" yaml:"outlier_detection,omitempty"`
+}
+
+type dxgateCircuitBreaker struct {
+ MaxConnections int32 `json:"max_connections,omitempty"
yaml:"max_connections,omitempty"`
+ HTTP1MaxPendingRequests int32
`json:"http1_max_pending_requests,omitempty"
yaml:"http1_max_pending_requests,omitempty"`
+ HTTP2MaxRequests int32 `json:"http2_max_requests,omitempty"
yaml:"http2_max_requests,omitempty"`
+ MaxRequestsPerConnection int32
`json:"max_requests_per_connection,omitempty"
yaml:"max_requests_per_connection,omitempty"`
+ MaxRetries int32 `json:"max_retries,omitempty"
yaml:"max_retries,omitempty"`
+}
+
+type dxgateOutlierDetection struct {
+ Consecutive5xxErrors uint32 `json:"consecutive_5xx_errors,omitempty"
yaml:"consecutive_5xx_errors,omitempty"`
+ Interval string `json:"interval,omitempty"
yaml:"interval,omitempty"`
+ BaseEjectionTime string `json:"base_ejection_time,omitempty"
yaml:"base_ejection_time,omitempty"`
+ MaxEjectionPercent int32 `json:"max_ejection_percent,omitempty"
yaml:"max_ejection_percent,omitempty"`
+ MinHealthPercent int32 `json:"min_health_percent,omitempty"
yaml:"min_health_percent,omitempty"`
}
type dxgateEndpoint struct {
@@ -567,13 +601,44 @@ func formatGatewayServicePorts(ports
[]corev1.ServicePort) string {
func (d *DeploymentController) buildDxgateRuntimeConfig(gw gateway.Gateway)
(string, string, error) {
routes := d.httpRoutes.List(metav1.NamespaceAll, klabels.Everything())
- return buildDxgateRuntimeConfig(gw, routes, d.domainSuffix())
+ return buildDxgateRuntimeConfig(gw, routes,
d.circuitBreakerPolicyConfigs(), d.domainSuffix())
+}
+
+func (d *DeploymentController) circuitBreakerPolicyConfigs() []config.Config {
+ if d.circuitBreakers != nil {
+ policies := d.circuitBreakers.List(metav1.NamespaceAll,
klabels.Everything())
+ out := make([]config.Config, 0, len(policies))
+ for _, policy := range policies {
+ out = append(out, config.Config{
+ Meta: config.Meta{
+ GroupVersionKind:
gvk.CircuitBreakerPolicy,
+ Name: policy.Name,
+ Namespace: policy.Namespace,
+ Labels: policy.Labels,
+ Annotations: policy.Annotations,
+ ResourceVersion:
policy.ResourceVersion,
+ CreationTimestamp:
policy.CreationTimestamp.Time,
+ OwnerReferences:
policy.OwnerReferences,
+ UID: string(policy.UID),
+ Generation: policy.Generation,
+ },
+ Spec: policy.Spec.DeepCopy(),
+ Status: policy.Status.DeepCopy(),
+ })
+ }
+ return out
+ }
+ if d.env != nil {
+ return d.env.List(gvk.CircuitBreakerPolicy, model.NamespaceAll)
+ }
+ return nil
}
-func buildDxgateRuntimeConfig(gw gateway.Gateway, routes []*gateway.HTTPRoute,
domainSuffix string) (string, string, error) {
+func buildDxgateRuntimeConfig(gw gateway.Gateway, routes []*gateway.HTTPRoute,
policies []config.Config, domainSuffix string) (string, string, error) {
if domainSuffix == "" {
domainSuffix = constants.DefaultClusterLocalDomain
}
+ circuitBreakers := circuitBreakerPoliciesByTarget(policies)
sort.Slice(routes, func(i, j int) bool {
if routes[i].Namespace != routes[j].Namespace {
@@ -601,7 +666,7 @@ func buildDxgateRuntimeConfig(gw gateway.Gateway, routes
[]*gateway.HTTPRoute, d
if !httpRouteReferencesGateway(hr, &gw) {
continue
}
- vh, clusters := buildDxgateVirtualHost(gw, hr, domainSuffix)
+ vh, clusters := buildDxgateVirtualHost(gw, hr, circuitBreakers,
domainSuffix)
if len(vh.Routes) == 0 {
continue
}
@@ -635,7 +700,7 @@ func dxgateRuntimeVersion(gw gateway.Gateway, routes
[]*gateway.HTTPRoute) strin
return strings.Join(parts, ";")
}
-func buildDxgateVirtualHost(gw gateway.Gateway, hr *gateway.HTTPRoute,
domainSuffix string) (dxgateVirtualHost, []dxgateCluster) {
+func buildDxgateVirtualHost(gw gateway.Gateway, hr *gateway.HTTPRoute,
circuitBreakers map[string]dxgateBackendCircuitBreaker, domainSuffix string)
(dxgateVirtualHost, []dxgateCluster) {
vh := dxgateVirtualHost{
Name: fmt.Sprintf("%s-%s", hr.Namespace, hr.Name),
Domains: dxgateRouteDomains(gw, hr),
@@ -668,13 +733,16 @@ func buildDxgateVirtualHost(gw gateway.Gateway, hr
*gateway.HTTPRoute, domainSuf
}
port := uint16(*backendRef.Port)
clusterName := fmt.Sprintf("%s-%s-%d-%d",
hr.Namespace, hr.Name, ruleIdx, backendIdx)
+ policy :=
circuitBreakers[namespacedServiceKey(backendNamespace, string(backendRef.Name))]
route.WeightedClusters =
append(route.WeightedClusters, dxgateWeightedCluster{
Name: clusterName,
Weight: weight,
})
clusters = append(clusters, dxgateCluster{
- Name: clusterName,
+ Name: clusterName,
+ CircuitBreaker: policy.CircuitBreaker,
+ Outlier: policy.Outlier,
Endpoints: []dxgateEndpoint{
{
Address:
fmt.Sprintf("%s.%s.svc.%s", backendRef.Name, backendNamespace, domainSuffix),
@@ -692,6 +760,107 @@ func buildDxgateVirtualHost(gw gateway.Gateway, hr
*gateway.HTTPRoute, domainSuf
return vh, clusters
}
+type dxgateBackendCircuitBreaker struct {
+ CircuitBreaker *dxgateCircuitBreaker
+ Outlier *dxgateOutlierDetection
+}
+
+func circuitBreakerPoliciesByTarget(policies []config.Config)
map[string]dxgateBackendCircuitBreaker {
+ out := map[string]dxgateBackendCircuitBreaker{}
+ sort.Slice(policies, func(i, j int) bool {
+ if policies[i].CreationTimestamp !=
policies[j].CreationTimestamp {
+ return
policies[i].CreationTimestamp.Before(policies[j].CreationTimestamp)
+ }
+ if policies[i].Namespace != policies[j].Namespace {
+ return policies[i].Namespace < policies[j].Namespace
+ }
+ return policies[i].Name < policies[j].Name
+ })
+ for _, cfg := range policies {
+ spec, ok := cfg.Spec.(*networking.CircuitBreakerPolicy)
+ if !ok || spec == nil {
+ continue
+ }
+ policy := dxgateCircuitBreakerFromPolicy(spec)
+ if policy.CircuitBreaker == nil && policy.Outlier == nil {
+ continue
+ }
+ for _, target := range spec.TargetRefs {
+ if !isCircuitBreakerServiceTarget(target) {
+ continue
+ }
+ key := namespacedServiceKey(cfg.Namespace, target.Name)
+ if _, found := out[key]; !found {
+ out[key] = policy
+ }
+ }
+ }
+ return out
+}
+
+func isCircuitBreakerServiceTarget(target *networking.PolicyTargetReference)
bool {
+ if target == nil || target.Name == "" || target.SectionName != "" {
+ return false
+ }
+ group := strings.TrimSpace(target.Group)
+ kind := strings.TrimSpace(target.Kind)
+ return (group == "" || group == "core") && strings.EqualFold(kind,
"Service")
+}
+
+func dxgateCircuitBreakerFromPolicy(policy *networking.CircuitBreakerPolicy)
dxgateBackendCircuitBreaker {
+ out := dxgateBackendCircuitBreaker{}
+ if cp := policy.GetConnectionPool(); cp != nil {
+ cb := &dxgateCircuitBreaker{
+ MaxConnections:
positiveInt32(cp.GetMaxConnections()),
+ HTTP1MaxPendingRequests:
positiveInt32(cp.GetHttp1MaxPendingRequests()),
+ HTTP2MaxRequests:
positiveInt32(cp.GetHttp2MaxRequests()),
+ MaxRequestsPerConnection:
positiveInt32(cp.GetMaxRequestsPerConnection()),
+ MaxRetries:
positiveInt32(cp.GetMaxRetries()),
+ }
+ if cb.MaxConnections > 0 || cb.HTTP1MaxPendingRequests > 0 ||
cb.HTTP2MaxRequests > 0 || cb.MaxRequestsPerConnection > 0 || cb.MaxRetries > 0
{
+ out.CircuitBreaker = cb
+ }
+ }
+ if od := policy.GetOutlierDetection(); od != nil {
+ outlier := &dxgateOutlierDetection{
+ Consecutive5xxErrors:
uint32Value(od.GetConsecutive_5XxErrors()),
+ Interval: durationString(od.GetInterval()),
+ BaseEjectionTime:
durationString(od.GetBaseEjectionTime()),
+ MaxEjectionPercent:
positiveInt32(od.GetMaxEjectionPercent()),
+ MinHealthPercent:
positiveInt32(od.GetMinHealthPercent()),
+ }
+ if outlier.Consecutive5xxErrors > 0 || outlier.Interval != ""
|| outlier.BaseEjectionTime != "" || outlier.MaxEjectionPercent > 0 ||
outlier.MinHealthPercent > 0 {
+ out.Outlier = outlier
+ }
+ }
+ return out
+}
+
+func positiveInt32(value int32) int32 {
+ if value <= 0 {
+ return 0
+ }
+ return value
+}
+
+func uint32Value(value *wrapperspb.UInt32Value) uint32 {
+ if value == nil {
+ return 0
+ }
+ return value.GetValue()
+}
+
+func durationString(value *durationpb.Duration) string {
+ if value == nil {
+ return ""
+ }
+ return value.AsDuration().String()
+}
+
+func namespacedServiceKey(namespace, name string) string {
+ return namespace + "/" + name
+}
+
func dxgateRouteDomains(gw gateway.Gateway, hr *gateway.HTTPRoute) []string {
domains := map[string]struct{}{}
for _, hostname := range hr.Spec.Hostnames {
diff --git
a/dubbod/discovery/pkg/config/kube/gateway/deployment_controller_test.go
b/dubbod/discovery/pkg/config/kube/gateway/deployment_controller_test.go
index 7d5879a9..1764c6e6 100644
--- a/dubbod/discovery/pkg/config/kube/gateway/deployment_controller_test.go
+++ b/dubbod/discovery/pkg/config/kube/gateway/deployment_controller_test.go
@@ -22,9 +22,15 @@ import (
"path/filepath"
"strings"
"testing"
+ "time"
+ "github.com/apache/dubbo-kubernetes/pkg/config"
+ "github.com/apache/dubbo-kubernetes/pkg/config/schema/gvk"
"github.com/apache/dubbo-kubernetes/pkg/kube/inject"
"github.com/google/go-cmp/cmp"
+ networking "github.com/kdubbo/api/networking/v1alpha3"
+ "google.golang.org/protobuf/types/known/durationpb"
+ "google.golang.org/protobuf/types/known/wrapperspb"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
@@ -116,7 +122,7 @@ func TestBuildDxgateRuntimeConfigFromHTTPRoute(t
*testing.T) {
},
}
- raw, hash, err := buildDxgateRuntimeConfig(gw,
[]*gatewayv1.HTTPRoute{route}, "cluster.local")
+ raw, hash, err := buildDxgateRuntimeConfig(gw,
[]*gatewayv1.HTTPRoute{route}, nil, "cluster.local")
if err != nil {
t.Fatal(err)
}
@@ -153,6 +159,94 @@ func TestBuildDxgateRuntimeConfigFromHTTPRoute(t
*testing.T) {
}
}
+func TestBuildDxgateRuntimeConfigAppliesCircuitBreakerPolicy(t *testing.T) {
+ backendPort := gatewayv1.PortNumber(9080)
+ gw := gatewayv1.Gateway{
+ ObjectMeta: metav1.ObjectMeta{Name: "public", Namespace: "app",
ResourceVersion: "10"},
+ Spec: gatewayv1.GatewaySpec{
+ GatewayClassName: "dubbo",
+ Listeners: []gatewayv1.Listener{
+ {Name: "http", Protocol:
gatewayv1.HTTPProtocolType, Port: 80},
+ },
+ },
+ }
+ route := &gatewayv1.HTTPRoute{
+ ObjectMeta: metav1.ObjectMeta{Name: "reviews", Namespace:
"app", ResourceVersion: "20"},
+ Spec: gatewayv1.HTTPRouteSpec{
+ CommonRouteSpec: gatewayv1.CommonRouteSpec{
+ ParentRefs: []gatewayv1.ParentReference{{Name:
"public"}},
+ },
+ Rules: []gatewayv1.HTTPRouteRule{
+ {
+ BackendRefs: []gatewayv1.HTTPBackendRef{
+ {
+ BackendRef:
gatewayv1.BackendRef{
+
BackendObjectReference: gatewayv1.BackendObjectReference{
+ Name:
"reviews",
+ Port:
&backendPort,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ policies := []config.Config{
+ {
+ Meta: config.Meta{
+ GroupVersionKind: gvk.CircuitBreakerPolicy,
+ Name: "reviews-circuit-breaker",
+ Namespace: "app",
+ CreationTimestamp: time.Unix(1, 0),
+ },
+ Spec: &networking.CircuitBreakerPolicy{
+ TargetRefs: []*networking.PolicyTargetReference{
+ {Kind: "Service", Name: "reviews"},
+ },
+ ConnectionPool:
&networking.ConnectionPoolSettings{
+ MaxConnections: 1,
+ Http1MaxPendingRequests: 1,
+ Http2MaxRequests: 2,
+ MaxRetries: 3,
+ },
+ OutlierDetection: &networking.OutlierDetection{
+ Consecutive_5XxErrors:
wrapperspb.UInt32(1),
+ Interval:
durationpb.New(time.Second),
+ BaseEjectionTime:
durationpb.New(30 * time.Second),
+ MaxEjectionPercent: 100,
+ },
+ },
+ },
+ }
+
+ raw, _, err := buildDxgateRuntimeConfig(gw,
[]*gatewayv1.HTTPRoute{route}, policies, "cluster.local")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var cfg dxgateRuntimeConfig
+ if err := yaml.Unmarshal([]byte(raw), &cfg); err != nil {
+ t.Fatal(err)
+ }
+ if len(cfg.Clusters) != 1 {
+ t.Fatalf("clusters = %d, want 1", len(cfg.Clusters))
+ }
+ cb := cfg.Clusters[0].CircuitBreaker
+ if cb == nil {
+ t.Fatal("cluster circuit_breaker is nil")
+ }
+ if cb.MaxConnections != 1 || cb.HTTP1MaxPendingRequests != 1 ||
cb.HTTP2MaxRequests != 2 || cb.MaxRetries != 3 {
+ t.Fatalf("unexpected circuit breaker: %#v", cb)
+ }
+ outlier := cfg.Clusters[0].Outlier
+ if outlier == nil {
+ t.Fatal("cluster outlier_detection is nil")
+ }
+ if outlier.Consecutive5xxErrors != 1 || outlier.Interval != "1s" ||
outlier.BaseEjectionTime != "30s" || outlier.MaxEjectionPercent != 100 {
+ t.Fatalf("unexpected outlier detection: %#v", outlier)
+ }
+}
+
func TestBuildDxgateRuntimeConfigFiltersUnattachedHTTPRoutes(t *testing.T) {
backendPort := gatewayv1.PortNumber(8080)
gw := gatewayv1.Gateway{
@@ -184,7 +278,7 @@ func
TestBuildDxgateRuntimeConfigFiltersUnattachedHTTPRoutes(t *testing.T) {
},
}
- raw, _, err := buildDxgateRuntimeConfig(gw,
[]*gatewayv1.HTTPRoute{route}, "cluster.local")
+ raw, _, err := buildDxgateRuntimeConfig(gw,
[]*gatewayv1.HTTPRoute{route}, nil, "cluster.local")
if err != nil {
t.Fatal(err)
}
diff --git a/go.mod b/go.mod
index 842f6187..6d0f075a 100644
--- a/go.mod
+++ b/go.mod
@@ -254,6 +254,9 @@ replace (
github.com/docker/distribution => github.com/docker/distribution
v2.8.2+incompatible
github.com/docker/docker => github.com/docker/docker
v23.0.1+incompatible
github.com/google/go-containerregistry =>
github.com/google/go-containerregistry v0.20.2
+ github.com/kdubbo/api => ../api
+ github.com/kdubbo/client-go => ../client-go
+ github.com/kdubbo/xds-api => ../xds-api
github.com/moby/buildkit => github.com/moby/buildkit v0.10.6
github.com/moby/dockerfile => github.com/moby/dockerfile v1.4.1
)
diff --git a/manifests/charts/base/files/crd-all.gen.yaml
b/manifests/charts/base/files/crd-all.gen.yaml
index 29a1408d..43b20ca4 100644
--- a/manifests/charts/base/files/crd-all.gen.yaml
+++ b/manifests/charts/base/files/crd-all.gen.yaml
@@ -1,6 +1,157 @@
# DO NOT EDIT - Generated by Cue OpenAPI generator based on Dubbo APIs.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
+metadata:
+ annotations:
+ "helm.sh/resource-policy": keep
+ labels:
+ app: dubbo
+ chart: dubbo
+ dubbo: networking
+ heritage: Tiller
+ release: dubbo
+ name: circuitbreakerpolicies.networking.dubbo.apache.org
+spec:
+ group: networking.dubbo.apache.org
+ names:
+ categories:
+ - dubbo
+ - networking
+ kind: CircuitBreakerPolicy
+ listKind: CircuitBreakerPolicyList
+ plural: circuitbreakerpolicies
+ shortNames:
+ - cbp
+ singular: circuitbreakerpolicy
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - description: Gateway API targets.
+ jsonPath: .spec.targetRefs[*].name
+ name: Targets
+ type: string
+ - description: CreationTimestamp is a timestamp representing the server
time when
+ this object was created.
+ jsonPath: .metadata.creationTimestamp
+ name: Age
+ type: date
+ name: v1alpha3
+ schema:
+ openAPIV3Schema:
+ properties:
+ spec:
+ description: 'Gateway API policy attachment for backend circuit
breaking.
+ See more details at: '
+ properties:
+ connectionPool:
+ description: Connection pool limits.
+ properties:
+ http1MaxPendingRequests:
+ description: Maximum queued requests waiting for an
upstream connection.
+ format: int32
+ type: integer
+ http2MaxRequests:
+ description: Maximum concurrent requests for HTTP/2 or
gRPC upstreams.
+ format: int32
+ type: integer
+ maxConnections:
+ description: Maximum concurrent upstream connections.
+ format: int32
+ type: integer
+ maxRequestsPerConnection:
+ description: Maximum requests before a connection is
drained.
+ format: int32
+ type: integer
+ maxRetries:
+ description: Maximum retries allowed to the backend.
+ format: int32
+ type: integer
+ type: object
+ outlierDetection:
+ description: Outlier detection controls passive ejection of
failing
+ endpoints.
+ properties:
+ baseEjectionTime:
+ description: Minimum ejection time for an unhealthy
endpoint.
+ type: string
+ x-kubernetes-validations:
+ - message: must be a valid duration greater than 1ms
+ rule: duration(self) >= duration('1ms')
+ consecutive5xxErrors:
+ description: Number of consecutive 5xx responses before an
endpoint
+ is considered an outlier.
+ maximum: 4294967295
+ minimum: 0
+ nullable: true
+ type: integer
+ interval:
+ description: Time between outlier detection sweeps.
+ type: string
+ x-kubernetes-validations:
+ - message: must be a valid duration greater than 1ms
+ rule: duration(self) >= duration('1ms')
+ maxEjectionPercent:
+ description: Maximum percentage of endpoints that can be
ejected.
+ format: int32
+ type: integer
+ minHealthPercent:
+ description: Minimum healthy percentage before outlier
detection
+ is disabled.
+ format: int32
+ type: integer
+ type: object
+ targetRefs:
+ description: Gateway API policy targets.
+ items:
+ properties:
+ group:
+ description: API group of the target.
+ type: string
+ kind:
+ description: Kind of the target.
+ type: string
+ name:
+ description: Name of the target object.
+ type: string
+ sectionName:
+ description: Optional section name for future per-port
attachment.
+ type: string
+ required:
+ - kind
+ - name
+ type: object
+ type: array
+ required:
+ - targetRefs
+ type: object
+ status:
+ properties:
+ conditions:
+ items:
+ properties:
+ observedGeneration:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ reason:
+ type: string
+ status:
+ type: string
+ type:
+ type: string
+ type: object
+ type: array
+ type: object
+ x-kubernetes-preserve-unknown-fields: true
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
metadata:
annotations:
"helm.sh/resource-policy": keep
diff --git a/manifests/charts/dubbod/templates/clusterrole.yaml
b/manifests/charts/dubbod/templates/clusterrole.yaml
index 7b365dfa..5e525070 100644
--- a/manifests/charts/dubbod/templates/clusterrole.yaml
+++ b/manifests/charts/dubbod/templates/clusterrole.yaml
@@ -21,6 +21,9 @@ rules:
- apiGroups: [ "security.dubbo.apache.org" ]
verbs: [ "get", "watch", "list" ]
resources: [ "*" ]
+ - apiGroups: [ "networking.dubbo.apache.org" ]
+ verbs: [ "get", "watch", "list" ]
+ resources: [ "*" ]
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations"]
verbs: ["get", "list", "watch", "update", "patch"]
diff --git a/pkg/config/schema/codegen/templates/clients.go.tmpl
b/pkg/config/schema/codegen/templates/clients.go.tmpl
index 4308f610..9f51bfd5 100644
--- a/pkg/config/schema/codegen/templates/clients.go.tmpl
+++ b/pkg/config/schema/codegen/templates/clients.go.tmpl
@@ -17,6 +17,7 @@ import (
ktypes "github.com/apache/dubbo-kubernetes/pkg/kube/kubetypes"
"github.com/apache/dubbo-kubernetes/pkg/util/ptr"
+ apigithubcomapachedubbokubernetesapinetworkingv1alpha3
"github.com/kdubbo/client-go/pkg/apis/networking/v1alpha3"
apigithubcomapachedubbokubernetesapisecurityv1alpha3
"github.com/kdubbo/client-go/pkg/apis/security/v1alpha3"
{{- range .Packages}}
{{.ImportName}} "{{.PackageName}}"
diff --git a/pkg/config/schema/codegen/templates/crdclient.go.tmpl
b/pkg/config/schema/codegen/templates/crdclient.go.tmpl
index fc2a4c84..4a439f08 100644
--- a/pkg/config/schema/codegen/templates/crdclient.go.tmpl
+++ b/pkg/config/schema/codegen/templates/crdclient.go.tmpl
@@ -14,6 +14,7 @@ import (
"github.com/apache/dubbo-kubernetes/pkg/config/schema/gvk"
"github.com/apache/dubbo-kubernetes/pkg/kube"
+ apigithubcomapachedubbokubernetesapinetworkingv1alpha3
"github.com/kdubbo/client-go/pkg/apis/networking/v1alpha3"
apigithubcomapachedubbokubernetesapisecurityv1alpha3
"github.com/kdubbo/client-go/pkg/apis/security/v1alpha3"
{{- range .Packages}}
{{.ImportName}} "{{.PackageName}}"
diff --git a/pkg/config/schema/codegen/templates/types.go.tmpl
b/pkg/config/schema/codegen/templates/types.go.tmpl
index f064a420..0dbf5e19 100644
--- a/pkg/config/schema/codegen/templates/types.go.tmpl
+++ b/pkg/config/schema/codegen/templates/types.go.tmpl
@@ -8,6 +8,7 @@ import (
{{- range .Packages}}
{{.ImportName}} "{{.PackageName}}"
{{- end}}
+ apigithubcomapachedubbokubernetesapinetworkingv1alpha3
"github.com/kdubbo/client-go/pkg/apis/networking/v1alpha3"
apigithubcomapachedubbokubernetesapisecurityv1alpha3
"github.com/kdubbo/client-go/pkg/apis/security/v1alpha3"
)
diff --git a/pkg/config/schema/collections/collections.gen.go
b/pkg/config/schema/collections/collections.gen.go
index 3deca42d..60ace61c 100755
--- a/pkg/config/schema/collections/collections.gen.go
+++ b/pkg/config/schema/collections/collections.gen.go
@@ -13,6 +13,7 @@ import (
"github.com/apache/dubbo-kubernetes/pkg/config/validation"
githubcomkdubboapimeshv1alpha1 "github.com/kdubbo/api/mesh/v1alpha1"
githubcomkdubboapimetav1alpha1 "github.com/kdubbo/api/meta/v1alpha1"
+ githubcomkdubboapinetworkingv1alpha3
"github.com/kdubbo/api/networking/v1alpha3"
githubcomkdubboapisecurityv1alpha3
"github.com/kdubbo/api/security/v1alpha3"
k8sioapiadmissionregistrationv1 "k8s.io/api/admissionregistration/v1"
k8sioapiappsv1 "k8s.io/api/apps/v1"
@@ -41,6 +42,21 @@ var (
ValidateProto: validation.EmptyValidate,
}.MustBuild()
+ CircuitBreakerPolicy = resource.Builder{
+ Identifier: "CircuitBreakerPolicy",
+ Group: "networking.dubbo.apache.org",
+ Kind: "CircuitBreakerPolicy",
+ Plural: "circuitbreakerpolicies",
+ Version: "v1alpha3",
+ Proto: "dubbo.networking.v1alpha3.CircuitBreakerPolicy",
StatusProto: "dubbo.meta.v1alpha1.DubboStatus",
+ ReflectType:
reflect.TypeOf(&githubcomkdubboapinetworkingv1alpha3.CircuitBreakerPolicy{}).Elem(),
StatusType:
reflect.TypeOf(&githubcomkdubboapimetav1alpha1.DubboStatus{}).Elem(),
+ ProtoPackage: "github.com/kdubbo/api/networking/v1alpha3",
StatusPackage: "github.com/kdubbo/api/meta/v1alpha1",
+ ClusterScoped: false,
+ Synthetic: false,
+ Builtin: false,
+ ValidateProto: validation.EmptyValidate,
+ }.MustBuild()
+
ConfigMap = resource.Builder{
Identifier: "ConfigMap",
Group: "",
@@ -413,6 +429,7 @@ var (
// All contains all collections in the system.
All = collection.NewSchemasBuilder().
MustAdd(AuthorizationPolicy).
+ MustAdd(CircuitBreakerPolicy).
MustAdd(ConfigMap).
MustAdd(CustomResourceDefinition).
MustAdd(DaemonSet).
@@ -467,6 +484,7 @@ var (
// Dubbo contains only collections used by Dubbo.
Dubbo = collection.NewSchemasBuilder().
MustAdd(AuthorizationPolicy).
+ MustAdd(CircuitBreakerPolicy).
MustAdd(PeerAuthentication).
MustAdd(RequestAuthentication).
Build()
@@ -474,6 +492,7 @@ var (
// dubboGatewayAPI contains only collections used by Dubbo, including
the full Gateway API.
dubboGatewayAPI = collection.NewSchemasBuilder().
MustAdd(AuthorizationPolicy).
+ MustAdd(CircuitBreakerPolicy).
MustAdd(GatewayClass).
MustAdd(HTTPRoute).
MustAdd(KubernetesGateway).
@@ -484,6 +503,7 @@ var (
// dubboStableGatewayAPI contains only collections used by Dubbo,
including beta+ Gateway API.
dubboStableGatewayAPI = collection.NewSchemasBuilder().
MustAdd(AuthorizationPolicy).
+ MustAdd(CircuitBreakerPolicy).
MustAdd(GatewayClass).
MustAdd(HTTPRoute).
MustAdd(KubernetesGateway).
diff --git a/pkg/config/schema/gvk/resources.gen.go
b/pkg/config/schema/gvk/resources.gen.go
index 777f04e2..f1540b62 100755
--- a/pkg/config/schema/gvk/resources.gen.go
+++ b/pkg/config/schema/gvk/resources.gen.go
@@ -11,6 +11,7 @@ import (
var (
AuthorizationPolicy = config.GroupVersionKind{Group:
"security.dubbo.apache.org", Version: "v1alpha3", Kind: "AuthorizationPolicy"}
+ CircuitBreakerPolicy = config.GroupVersionKind{Group:
"networking.dubbo.apache.org", Version: "v1alpha3", Kind:
"CircuitBreakerPolicy"}
ConfigMap = config.GroupVersionKind{Group: "",
Version: "v1", Kind: "ConfigMap"}
CustomResourceDefinition = config.GroupVersionKind{Group:
"apiextensions.k8s.io", Version: "v1", Kind: "CustomResourceDefinition"}
DaemonSet = config.GroupVersionKind{Group: "apps",
Version: "v1", Kind: "DaemonSet"}
@@ -45,6 +46,8 @@ func ToGVR(g config.GroupVersionKind)
(schema.GroupVersionResource, bool) {
switch g {
case AuthorizationPolicy:
return gvr.AuthorizationPolicy, true
+ case CircuitBreakerPolicy:
+ return gvr.CircuitBreakerPolicy, true
case ConfigMap:
return gvr.ConfigMap, true
case CustomResourceDefinition:
@@ -108,6 +111,8 @@ func MustToKind(g config.GroupVersionKind) kind.Kind {
switch g {
case AuthorizationPolicy:
return kind.AuthorizationPolicy
+ case CircuitBreakerPolicy:
+ return kind.CircuitBreakerPolicy
case ConfigMap:
return kind.ConfigMap
case CustomResourceDefinition:
@@ -176,6 +181,8 @@ func FromGVR(g schema.GroupVersionResource)
(config.GroupVersionKind, bool) {
switch g {
case gvr.AuthorizationPolicy:
return AuthorizationPolicy, true
+ case gvr.CircuitBreakerPolicy:
+ return CircuitBreakerPolicy, true
case gvr.ConfigMap:
return ConfigMap, true
case gvr.CustomResourceDefinition:
diff --git a/pkg/config/schema/gvr/resources.gen.go
b/pkg/config/schema/gvr/resources.gen.go
index 5affdbcc..52be18a4 100755
--- a/pkg/config/schema/gvr/resources.gen.go
+++ b/pkg/config/schema/gvr/resources.gen.go
@@ -6,6 +6,7 @@ import "k8s.io/apimachinery/pkg/runtime/schema"
var (
AuthorizationPolicy = schema.GroupVersionResource{Group:
"security.dubbo.apache.org", Version: "v1alpha3", Resource:
"authorizationpolicies"}
+ CircuitBreakerPolicy = schema.GroupVersionResource{Group:
"networking.dubbo.apache.org", Version: "v1alpha3", Resource:
"circuitbreakerpolicies"}
ConfigMap = schema.GroupVersionResource{Group: "",
Version: "v1", Resource: "configmaps"}
CustomResourceDefinition = schema.GroupVersionResource{Group:
"apiextensions.k8s.io", Version: "v1", Resource: "customresourcedefinitions"}
DaemonSet = schema.GroupVersionResource{Group:
"apps", Version: "v1", Resource: "daemonsets"}
@@ -39,6 +40,8 @@ func IsClusterScoped(g schema.GroupVersionResource) bool {
switch g {
case AuthorizationPolicy:
return false
+ case CircuitBreakerPolicy:
+ return false
case ConfigMap:
return false
case CustomResourceDefinition:
diff --git a/pkg/config/schema/kind/resources.gen.go
b/pkg/config/schema/kind/resources.gen.go
index 4707c01f..f31e2742 100755
--- a/pkg/config/schema/kind/resources.gen.go
+++ b/pkg/config/schema/kind/resources.gen.go
@@ -6,6 +6,7 @@ const (
Unknown Kind = iota
Address
AuthorizationPolicy
+ CircuitBreakerPolicy
ConfigMap
CustomResourceDefinition
DNSName
@@ -39,6 +40,8 @@ func (k Kind) String() string {
return "Address"
case AuthorizationPolicy:
return "AuthorizationPolicy"
+ case CircuitBreakerPolicy:
+ return "CircuitBreakerPolicy"
case ConfigMap:
return "ConfigMap"
case CustomResourceDefinition:
@@ -100,6 +103,8 @@ func FromString(s string) Kind {
return Address
case "AuthorizationPolicy":
return AuthorizationPolicy
+ case "CircuitBreakerPolicy":
+ return CircuitBreakerPolicy
case "ConfigMap":
return ConfigMap
case "CustomResourceDefinition":
diff --git a/pkg/config/schema/kubeclient/resources.gen.go
b/pkg/config/schema/kubeclient/resources.gen.go
index 23ac843a..e07946d8 100755
--- a/pkg/config/schema/kubeclient/resources.gen.go
+++ b/pkg/config/schema/kubeclient/resources.gen.go
@@ -17,6 +17,7 @@ import (
ktypes "github.com/apache/dubbo-kubernetes/pkg/kube/kubetypes"
"github.com/apache/dubbo-kubernetes/pkg/util/ptr"
+ apigithubcomapachedubbokubernetesapinetworkingv1alpha3
"github.com/kdubbo/client-go/pkg/apis/networking/v1alpha3"
apigithubcomapachedubbokubernetesapisecurityv1alpha3
"github.com/kdubbo/client-go/pkg/apis/security/v1alpha3"
k8sioapiadmissionregistrationv1 "k8s.io/api/admissionregistration/v1"
k8sioapiappsv1 "k8s.io/api/apps/v1"
@@ -33,6 +34,8 @@ func GetWriteClient[T runtime.Object](c ClientGetter,
namespace string) ktypes.W
switch any(ptr.Empty[T]()).(type) {
case
*apigithubcomapachedubbokubernetesapisecurityv1alpha3.AuthorizationPolicy:
return
c.Dubbo().SecurityV1alpha3().AuthorizationPolicies(namespace).(ktypes.WriteAPI[T])
+ case
*apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy:
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(namespace).(ktypes.WriteAPI[T])
case *k8sioapicorev1.ConfigMap:
return
c.Kube().CoreV1().ConfigMaps(namespace).(ktypes.WriteAPI[T])
case
*k8sioapiextensionsapiserverpkgapisapiextensionsv1.CustomResourceDefinition:
@@ -88,6 +91,8 @@ func GetClient[T, TL runtime.Object](c ClientGetter,
namespace string) ktypes.Re
switch any(ptr.Empty[T]()).(type) {
case
*apigithubcomapachedubbokubernetesapisecurityv1alpha3.AuthorizationPolicy:
return
c.Dubbo().SecurityV1alpha3().AuthorizationPolicies(namespace).(ktypes.ReadWriteAPI[T,
TL])
+ case
*apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy:
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(namespace).(ktypes.ReadWriteAPI[T,
TL])
case *k8sioapicorev1.ConfigMap:
return
c.Kube().CoreV1().ConfigMaps(namespace).(ktypes.ReadWriteAPI[T, TL])
case
*k8sioapiextensionsapiserverpkgapisapiextensionsv1.CustomResourceDefinition:
@@ -143,6 +148,8 @@ func gvrToObject(g schema.GroupVersionResource)
runtime.Object {
switch g {
case gvr.AuthorizationPolicy:
return
&apigithubcomapachedubbokubernetesapisecurityv1alpha3.AuthorizationPolicy{}
+ case gvr.CircuitBreakerPolicy:
+ return
&apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy{}
case gvr.ConfigMap:
return &k8sioapicorev1.ConfigMap{}
case gvr.CustomResourceDefinition:
@@ -206,6 +213,13 @@ func getInformerFiltered(c ClientGetter, opts
ktypes.InformerOptions, g schema.G
w = func(options metav1.ListOptions) (watch.Interface, error) {
return
c.Dubbo().SecurityV1alpha3().AuthorizationPolicies(opts.Namespace).Watch(context.Background(),
options)
}
+ case gvr.CircuitBreakerPolicy:
+ l = func(options metav1.ListOptions) (runtime.Object, error) {
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(opts.Namespace).List(context.Background(),
options)
+ }
+ w = func(options metav1.ListOptions) (watch.Interface, error) {
+ return
c.Dubbo().NetworkingV1alpha3().CircuitBreakerPolicies(opts.Namespace).Watch(context.Background(),
options)
+ }
case gvr.ConfigMap:
l = func(options metav1.ListOptions) (runtime.Object, error) {
return
c.Kube().CoreV1().ConfigMaps(opts.Namespace).List(context.Background(), options)
diff --git a/pkg/config/schema/kubetypes/resources.gen.go
b/pkg/config/schema/kubetypes/resources.gen.go
index 00b5cac3..910b664f 100755
--- a/pkg/config/schema/kubetypes/resources.gen.go
+++ b/pkg/config/schema/kubetypes/resources.gen.go
@@ -6,7 +6,9 @@ import (
"github.com/apache/dubbo-kubernetes/pkg/config"
"github.com/apache/dubbo-kubernetes/pkg/config/schema/gvk"
githubcomkdubboapimeshv1alpha1 "github.com/kdubbo/api/mesh/v1alpha1"
+ githubcomkdubboapinetworkingv1alpha3
"github.com/kdubbo/api/networking/v1alpha3"
githubcomkdubboapisecurityv1alpha3
"github.com/kdubbo/api/security/v1alpha3"
+ apigithubcomapachedubbokubernetesapinetworkingv1alpha3
"github.com/kdubbo/client-go/pkg/apis/networking/v1alpha3"
apigithubcomapachedubbokubernetesapisecurityv1alpha3
"github.com/kdubbo/client-go/pkg/apis/security/v1alpha3"
k8sioapiadmissionregistrationv1 "k8s.io/api/admissionregistration/v1"
k8sioapiappsv1 "k8s.io/api/apps/v1"
@@ -25,6 +27,10 @@ func getGvk(obj any) (config.GroupVersionKind, bool) {
return gvk.AuthorizationPolicy, true
case
*apigithubcomapachedubbokubernetesapisecurityv1alpha3.AuthorizationPolicy:
return gvk.AuthorizationPolicy, true
+ case *githubcomkdubboapinetworkingv1alpha3.CircuitBreakerPolicy:
+ return gvk.CircuitBreakerPolicy, true
+ case
*apigithubcomapachedubbokubernetesapinetworkingv1alpha3.CircuitBreakerPolicy:
+ return gvk.CircuitBreakerPolicy, true
case *k8sioapicorev1.ConfigMap:
return gvk.ConfigMap, true
case
*k8sioapiextensionsapiserverpkgapisapiextensionsv1.CustomResourceDefinition:
diff --git a/pkg/config/schema/metadata.yaml b/pkg/config/schema/metadata.yaml
index 36059afa..c62921b0 100644
--- a/pkg/config/schema/metadata.yaml
+++ b/pkg/config/schema/metadata.yaml
@@ -201,6 +201,15 @@ resources:
statusProto: "dubbo.meta.v1alpha1.DubboStatus"
statusProtoPackage: "github.com/kdubbo/api/meta/v1alpha1"
+ - kind: CircuitBreakerPolicy
+ plural: "circuitbreakerpolicies"
+ group: "networking.dubbo.apache.org"
+ version: "v1alpha3"
+ proto: "dubbo.networking.v1alpha3.CircuitBreakerPolicy"
+ protoPackage: "github.com/kdubbo/api/networking/v1alpha3"
+ statusProto: "dubbo.meta.v1alpha1.DubboStatus"
+ statusProtoPackage: "github.com/kdubbo/api/meta/v1alpha1"
+
- kind: "MeshConfig"
plural: "meshconfigs"
group: ""