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 28cb2cc3 add dubbo mesh cni (#918)
28cb2cc3 is described below
commit 28cb2cc3b3d0dd8aa0157bd92c8aa57fba770a5b
Author: mfordjody <[email protected]>
AuthorDate: Thu Jun 18 19:59:48 2026 +0800
add dubbo mesh cni (#918)
* delete logo
* Update moviereview sample
* add dubbo mesh cni
---
Makefile | 7 +-
dubbo-cni/main.go | 139 ++++
dubbod/discovery/docker/dockerfile.dubbod | 5 +
.../charts/dubbod/templates/cni-daemonset.yaml | 124 ++++
.../charts/dubbod/templates/configmap-values.yaml | 24 +
dubboinstaller/charts/dubbod/values.yaml | 14 +
dubbooperator/pkg/apis/proto/values_types.proto | 30 +
dubbooperator/pkg/apis/values_types.pb.go | 743 +++++++++++----------
dubbooperator/pkg/render/manifest_test.go | 90 +++
pkg/cni/config.go | 182 +++++
pkg/cni/config_test.go | 66 ++
pkg/cni/install.go | 497 ++++++++++++++
pkg/cni/install_test.go | 149 +++++
pkg/cni/iptables.go | 170 +++++
pkg/cni/iptables_test.go | 72 ++
pkg/cni/kubernetes.go | 72 ++
pkg/cni/plugin.go | 144 ++++
pkg/cni/plugin_test.go | 139 ++++
pkg/cni/state.go | 99 +++
pkg/kube/inject/proxyless.go | 2 +
pkg/kube/inject/proxyless_test.go | 8 +
pkg/kube/inject/webhook.go | 8 +
release/downloadDubboCandidate.sh | 32 +-
samples/app/deployment.yaml | 16 -
24 files changed, 2439 insertions(+), 393 deletions(-)
diff --git a/Makefile b/Makefile
index 39b62ecf..abc13722 100644
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,12 @@ build-dubboctl:
-ldflags "-X
github.com/apache/dubbo-kubernetes/pkg/version.gitTag=$(GIT_VERSION)" \
-o bin/dubboctl dubboctl/main.go
+.PHONY: build-dubbo-cni
+build-dubbo-cni:
+ CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build \
+ -o bin/dubbo-cni dubbo-cni/main.go
+
.PHONY: clone-sample
clone-sample:
mkdir -p bin
- cp -r samples bin/samples
\ No newline at end of file
+ cp -r samples bin/samples
diff --git a/dubbo-cni/main.go b/dubbo-cni/main.go
new file mode 100644
index 00000000..7e512f4e
--- /dev/null
+++ b/dubbo-cni/main.go
@@ -0,0 +1,139 @@
+// 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.
+
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+
+ "github.com/apache/dubbo-kubernetes/pkg/cni"
+)
+
+func main() {
+ if len(os.Args) > 1 {
+ switch os.Args[1] {
+ case "install":
+ if err := runInstall(os.Args[2:]); err != nil {
+ exitErr(err)
+ }
+ return
+ case "uninstall":
+ if err := runUninstall(os.Args[2:]); err != nil {
+ exitErr(err)
+ }
+ return
+ }
+ }
+
+ stdin, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ exitErr(fmt.Errorf("read stdin: %w", err))
+ }
+
+ conf, err := cni.ParseNetConf(stdin)
+ if err != nil {
+ exitErr(err)
+ }
+ env := cni.EnvFromOS()
+ if env.Command == "VERSION" {
+ out, err := cni.Plugin{}.Run(context.Background(), env, conf)
+ if err != nil {
+ exitErr(err)
+ }
+ if _, err := os.Stdout.Write(out); err != nil {
+ exitErr(fmt.Errorf("write stdout: %w", err))
+ }
+ return
+ }
+
+ plugin := cni.Plugin{
+ RuleManager: cni.NewIPTablesRuleManager(conf),
+ StateStore: cni.NewFileStateStore(conf.StateDirectory()),
+ }
+ if (env.Command == "ADD" || env.Command == "CHECK") &&
cni.EnvHasKubernetesPod(env) {
+ provider, err :=
cni.NewKubernetesPodInfoProvider(conf.KubeConfigPath())
+ if err != nil {
+ exitErr(err)
+ }
+ plugin.PodInfoProvider = provider
+ }
+ out, err := plugin.Run(context.Background(), env, conf)
+ if err != nil {
+ exitErr(err)
+ }
+ if len(out) > 0 {
+ if _, err := os.Stdout.Write(out); err != nil {
+ exitErr(fmt.Errorf("write stdout: %w", err))
+ }
+ }
+}
+
+func runInstall(args []string) error {
+ opts := cni.DefaultInstallerOptions()
+ var watch bool
+ var interval time.Duration
+ flags := installerFlagSet("install", &opts)
+ flags.BoolVar(&watch, "watch", false, "keep installer running and
refresh service account credentials")
+ flags.DurationVar(&interval, "refresh-interval",
cni.DefaultInstallerInterval(), "credential refresh interval")
+ if err := flags.Parse(args); err != nil {
+ return err
+ }
+ ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt,
syscall.SIGTERM)
+ defer stop()
+ if watch {
+ return cni.InstallLoop(ctx, opts, interval)
+ }
+ return cni.Install(ctx, opts)
+}
+
+func runUninstall(args []string) error {
+ opts := cni.DefaultInstallerOptions()
+ flags := installerFlagSet("uninstall", &opts)
+ if err := flags.Parse(args); err != nil {
+ return err
+ }
+ return cni.Uninstall(opts)
+}
+
+func installerFlagSet(name string, opts *cni.InstallerOptions) *flag.FlagSet {
+ flags := flag.NewFlagSet(name, flag.ContinueOnError)
+ flags.StringVar(&opts.BinDir, "bin-dir", opts.BinDir, "host CNI binary
directory")
+ flags.StringVar(&opts.ConfDir, "conf-dir", opts.ConfDir, "host CNI
config directory")
+ flags.StringVar(&opts.StateDir, "state-dir", opts.StateDir, "host state
directory")
+ flags.StringVar(&opts.KubeConfigPath, "kubeconfig",
opts.KubeConfigPath, "host kubeconfig path used by the CNI plugin")
+ flags.StringVar(&opts.TokenFile, "token-file", opts.TokenFile, "host
service account token file")
+ flags.StringVar(&opts.CAFile, "ca-file", opts.CAFile, "host Kubernetes
CA file")
+ flags.StringVar(&opts.ServiceAccountTokenPath, "service-account-token",
opts.ServiceAccountTokenPath, "mounted service account token source")
+ flags.StringVar(&opts.ServiceAccountCAPath, "service-account-ca",
opts.ServiceAccountCAPath, "mounted service account CA source")
+ flags.StringVar(&opts.APIServer, "api-server", opts.APIServer,
"Kubernetes API server URL")
+ flags.StringVar(&opts.ManagedLabel, "managed-label", opts.ManagedLabel,
"label key that marks mesh-managed Pods")
+ flags.StringVar(&opts.ManagedLabelValue, "managed-label-value",
opts.ManagedLabelValue, "label value that marks mesh-managed Pods")
+ flags.StringVar(&opts.IPTablesPath, "iptables-path", opts.IPTablesPath,
"iptables binary used by the CNI plugin")
+ flags.StringVar(&opts.IPSetPath, "ipset-path", opts.IPSetPath, "ipset
binary used by the CNI plugin")
+ flags.IntVar(&opts.XServerPort, "xserver-port", opts.XServerPort,
"xserver inbound port")
+ return flags
+}
+
+func exitErr(err error) {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+}
diff --git a/dubbod/discovery/docker/dockerfile.dubbod
b/dubbod/discovery/docker/dockerfile.dubbod
index af1ed5d6..a1d823fa 100644
--- a/dubbod/discovery/docker/dockerfile.dubbod
+++ b/dubbod/discovery/docker/dockerfile.dubbod
@@ -33,9 +33,14 @@ RUN go build -v -trimpath -ldflags="-s -w" \
-o /out/dubbod \
./dubbod/discovery/cmd/main.go
+RUN go build -v -trimpath -ldflags="-s -w" \
+ -o /out/dubbo-cni \
+ ./dubbo-cni/main.go
+
FROM scratch
COPY --from=builder /out/dubbod /usr/local/bin/dubbod
+COPY --from=builder /out/dubbo-cni /usr/local/bin/dubbo-cni
USER 65532:65532
ENTRYPOINT ["/usr/local/bin/dubbod"]
diff --git a/dubboinstaller/charts/dubbod/templates/cni-daemonset.yaml
b/dubboinstaller/charts/dubbod/templates/cni-daemonset.yaml
new file mode 100644
index 00000000..a4e9a777
--- /dev/null
+++ b/dubboinstaller/charts/dubbod/templates/cni-daemonset.yaml
@@ -0,0 +1,124 @@
+# 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.
+
+{{- $defaults := .Values._internal_default_values_not_set | default dict }}
+{{- $defaultGlobal := $defaults.global | default dict }}
+{{- $defaultProxyless := $defaultGlobal.proxyless | default dict }}
+{{- $defaultCNI := $defaultProxyless.cni | default dict }}
+{{- $global := .Values.global | default dict }}
+{{- $proxyless := $global.proxyless | default dict }}
+{{- $cni := $proxyless.cni | default dict }}
+{{- $enabled := false }}
+{{- if hasKey $defaultCNI "enabled" }}
+{{- $enabled = $defaultCNI.enabled }}
+{{- end }}
+{{- if hasKey $cni "enabled" }}
+{{- $enabled = $cni.enabled }}
+{{- end }}
+{{- if $enabled }}
+{{- $image := coalesce $cni.image $defaultCNI.image "kdubbo/dubbod:debug" }}
+{{- $binDir := coalesce $cni.binDir $defaultCNI.binDir "/opt/cni/bin" }}
+{{- $confDir := coalesce $cni.confDir $defaultCNI.confDir "/etc/cni/net.d" }}
+{{- $stateDir := coalesce $cni.stateDir $defaultCNI.stateDir
"/var/run/dubbo-cni" }}
+{{- $xserverPort := int (coalesce $cni.xserverPort $defaultCNI.xserverPort
15080) }}
+{{- $managedLabel := coalesce $cni.managedLabel $defaultCNI.managedLabel
"proxyless.dubbo.apache.org/managed" }}
+{{- $managedLabelValue := coalesce $cni.managedLabelValue
$defaultCNI.managedLabelValue "true" }}
+{{- $iptablesPath := coalesce $cni.iptablesPath $defaultCNI.iptablesPath
"iptables" }}
+{{- $ipsetPath := coalesce $cni.ipsetPath $defaultCNI.ipsetPath "ipset" }}
+{{- $refreshInterval := coalesce $cni.refreshInterval
$defaultCNI.refreshInterval "1m" }}
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: dubbo-cni-node
+ namespace: dubbo-system
+ labels:
+ app: dubbo-cni
+ dubbo.apache.org/rev: default
+spec:
+ selector:
+ matchLabels:
+ app: dubbo-cni
+ updateStrategy:
+ type: RollingUpdate
+ template:
+ metadata:
+ labels:
+ app: dubbo-cni
+ dubbo.apache.org/rev: default
+ spec:
+ serviceAccountName: dubbod
+ tolerations:
+ - operator: Exists
+ containers:
+ - name: install-cni
+ image: {{ $image | quote }}
+ imagePullPolicy: IfNotPresent
+ command:
+ - /usr/local/bin/dubbo-cni
+ args:
+ - install
+ - --watch
+ - --bin-dir={{ $binDir }}
+ - --conf-dir={{ $confDir }}
+ - --state-dir={{ $stateDir }}
+ - --kubeconfig={{ printf "%s/dubbo-cni-kubeconfig" $confDir }}
+ - --token-file={{ printf "%s/token" $stateDir }}
+ - --ca-file={{ printf "%s/ca.crt" $stateDir }}
+ - --xserver-port={{ $xserverPort }}
+ - --managed-label={{ $managedLabel }}
+ - --managed-label-value={{ $managedLabelValue }}
+ - --iptables-path={{ $iptablesPath }}
+ - --ipset-path={{ $ipsetPath }}
+ - --refresh-interval={{ $refreshInterval }}
+ lifecycle:
+ preStop:
+ exec:
+ command:
+ - /usr/local/bin/dubbo-cni
+ - uninstall
+ - --bin-dir={{ $binDir }}
+ - --conf-dir={{ $confDir }}
+ - --state-dir={{ $stateDir }}
+ - --kubeconfig={{ printf "%s/dubbo-cni-kubeconfig" $confDir
}}
+ - --token-file={{ printf "%s/token" $stateDir }}
+ - --ca-file={{ printf "%s/ca.crt" $stateDir }}
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ volumeMounts:
+ - name: cni-bin-dir
+ mountPath: {{ $binDir | quote }}
+ - name: cni-conf-dir
+ mountPath: {{ $confDir | quote }}
+ - name: cni-state-dir
+ mountPath: {{ $stateDir | quote }}
+ volumes:
+ - name: cni-bin-dir
+ hostPath:
+ path: {{ $binDir | quote }}
+ type: DirectoryOrCreate
+ - name: cni-conf-dir
+ hostPath:
+ path: {{ $confDir | quote }}
+ type: DirectoryOrCreate
+ - name: cni-state-dir
+ hostPath:
+ path: {{ $stateDir | quote }}
+ type: DirectoryOrCreate
+{{- end }}
diff --git a/dubboinstaller/charts/dubbod/templates/configmap-values.yaml
b/dubboinstaller/charts/dubbod/templates/configmap-values.yaml
index f3bb5129..c740eea3 100644
--- a/dubboinstaller/charts/dubbod/templates/configmap-values.yaml
+++ b/dubboinstaller/charts/dubbod/templates/configmap-values.yaml
@@ -16,15 +16,26 @@
{{- $defaults := .Values._internal_default_values_not_set | default dict }}
{{- $defaultGlobal := $defaults.global | default dict }}
{{- $defaultProxy := $defaultGlobal.proxy | default dict }}
+{{- $defaultProxyless := $defaultGlobal.proxyless | default dict }}
+{{- $defaultCNI := $defaultProxyless.cni | default dict }}
{{- $defaultGUI := $defaultGlobal.gui | default dict }}
{{- $global := .Values.global | default dict }}
{{- $proxy := $global.proxy | default dict }}
+{{- $proxyless := $global.proxyless | default dict }}
+{{- $cni := $proxyless.cni | default dict }}
{{- $gui := $global.gui | default dict }}
{{- $clusterDomain := coalesce $proxy.clusterDomain
$defaultProxy.clusterDomain "cluster.local" }}
{{- $revision := .Values.revision | default "default" }}
{{- $statusPort := coalesce $global.statusPort $defaultGlobal.statusPort 26020
}}
{{- $guiPort := int (coalesce $gui.port $defaultGUI.port 26080) }}
{{- $guiNodePort := int (coalesce $gui.nodePort $defaultGUI.nodePort 30080) }}
+{{- $cniEnabled := false }}
+{{- if hasKey $defaultCNI "enabled" }}
+{{- $cniEnabled = $defaultCNI.enabled }}
+{{- end }}
+{{- if hasKey $cni "enabled" }}
+{{- $cniEnabled = $cni.enabled }}
+{{- end }}
{{- $original := omit .Values "_internal_default_values_not_set" }}
apiVersion: v1
kind: ConfigMap
@@ -40,6 +51,19 @@ data:
global:
proxy:
clusterDomain: {{ $clusterDomain | quote }}
+ proxyless:
+ cni:
+ enabled: {{ $cniEnabled }}
+ image: {{ coalesce $cni.image $defaultCNI.image
"kdubbo/dubbod:debug" | quote }}
+ binDir: {{ coalesce $cni.binDir $defaultCNI.binDir "/opt/cni/bin" |
quote }}
+ confDir: {{ coalesce $cni.confDir $defaultCNI.confDir
"/etc/cni/net.d" | quote }}
+ stateDir: {{ coalesce $cni.stateDir $defaultCNI.stateDir
"/var/run/dubbo-cni" | quote }}
+ xserverPort: {{ int (coalesce $cni.xserverPort
$defaultCNI.xserverPort 15080) }}
+ managedLabel: {{ coalesce $cni.managedLabel $defaultCNI.managedLabel
"proxyless.dubbo.apache.org/managed" | quote }}
+ managedLabelValue: {{ coalesce $cni.managedLabelValue
$defaultCNI.managedLabelValue "true" | quote }}
+ iptablesPath: {{ coalesce $cni.iptablesPath $defaultCNI.iptablesPath
"iptables" | quote }}
+ ipsetPath: {{ coalesce $cni.ipsetPath $defaultCNI.ipsetPath "ipset"
| quote }}
+ refreshInterval: {{ coalesce $cni.refreshInterval
$defaultCNI.refreshInterval "1m" | quote }}
gui:
port: {{ $guiPort }}
nodePort: {{ $guiNodePort }}
diff --git a/dubboinstaller/charts/dubbod/values.yaml
b/dubboinstaller/charts/dubbod/values.yaml
index 83090e11..78b4c1cf 100644
--- a/dubboinstaller/charts/dubbod/values.yaml
+++ b/dubboinstaller/charts/dubbod/values.yaml
@@ -20,6 +20,20 @@ _internal_default_values_not_set:
proxy:
clusterDomain: "cluster.local"
+ proxyless:
+ cni:
+ enabled: true
+ image: "kdubbo/dubbod:debug"
+ binDir: "/opt/cni/bin"
+ confDir: "/etc/cni/net.d"
+ stateDir: "/var/run/dubbo-cni"
+ xserverPort: 15080
+ managedLabel: "proxyless.dubbo.apache.org/managed"
+ managedLabelValue: "true"
+ iptablesPath: "iptables"
+ ipsetPath: "ipset"
+ refreshInterval: "1m"
+
statusPort: 26020
gui:
diff --git a/dubbooperator/pkg/apis/proto/values_types.proto
b/dubbooperator/pkg/apis/proto/values_types.proto
index 8aa6c120..a3c85162 100644
--- a/dubbooperator/pkg/apis/proto/values_types.proto
+++ b/dubbooperator/pkg/apis/proto/values_types.proto
@@ -34,6 +34,34 @@ message ProxyConfig {
string clusterDomain = 1;
}
+message ProxylessConfig {
+ MeshCNIConfig cni = 1;
+}
+
+message MeshCNIConfig {
+ bool enabled = 1;
+
+ string image = 2;
+
+ string binDir = 3;
+
+ string confDir = 4;
+
+ string stateDir = 5;
+
+ int64 xserverPort = 6;
+
+ string managedLabel = 7;
+
+ string managedLabelValue = 8;
+
+ string iptablesPath = 9;
+
+ string ipsetPath = 10;
+
+ string refreshInterval = 11;
+}
+
message GlobalConfig {
ProxyConfig proxy = 1;
@@ -44,6 +72,8 @@ message GlobalConfig {
bool configValidation = 4;
MulticlusterConfig multicluster = 5;
+
+ ProxylessConfig proxyless = 6;
}
message RemoteAccessConfig {
diff --git a/dubbooperator/pkg/apis/values_types.pb.go
b/dubbooperator/pkg/apis/values_types.pb.go
index 0dcc0f62..bb578791 100644
--- a/dubbooperator/pkg/apis/values_types.pb.go
+++ b/dubbooperator/pkg/apis/values_types.pb.go
@@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.31.0
+// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: values_types.proto
@@ -28,6 +28,7 @@ import (
wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
reflect "reflect"
sync "sync"
+ unsafe "unsafe"
)
const (
@@ -38,21 +39,18 @@ const (
)
type GUIConfig struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Port int64
`protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"`
+ NodePort int64
`protobuf:"varint,2,opt,name=nodePort,proto3" json:"nodePort,omitempty"`
unknownFields protoimpl.UnknownFields
-
- Port int64 `protobuf:"varint,1,opt,name=port,proto3"
json:"port,omitempty"`
- NodePort int64 `protobuf:"varint,2,opt,name=nodePort,proto3"
json:"nodePort,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *GUIConfig) Reset() {
*x = GUIConfig{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *GUIConfig) String() string {
@@ -63,7 +61,7 @@ func (*GUIConfig) ProtoMessage() {}
func (x *GUIConfig) ProtoReflect() protoreflect.Message {
mi := &file_values_types_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -93,20 +91,17 @@ func (x *GUIConfig) GetNodePort() int64 {
}
type ProxyConfig struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ ClusterDomain string
`protobuf:"bytes,1,opt,name=clusterDomain,proto3"
json:"clusterDomain,omitempty"`
unknownFields protoimpl.UnknownFields
-
- ClusterDomain string `protobuf:"bytes,1,opt,name=clusterDomain,proto3"
json:"clusterDomain,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *ProxyConfig) Reset() {
*x = ProxyConfig{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *ProxyConfig) String() string {
@@ -117,7 +112,7 @@ func (*ProxyConfig) ProtoMessage() {}
func (x *ProxyConfig) ProtoReflect() protoreflect.Message {
mi := &file_values_types_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -139,25 +134,191 @@ func (x *ProxyConfig) GetClusterDomain() string {
return ""
}
-type GlobalConfig struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+type ProxylessConfig struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Cni *MeshCNIConfig
`protobuf:"bytes,1,opt,name=cni,proto3" json:"cni,omitempty"`
unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
- Proxy *ProxyConfig
`protobuf:"bytes,1,opt,name=proxy,proto3" json:"proxy,omitempty"`
- StatusPort int64
`protobuf:"varint,2,opt,name=statusPort,proto3" json:"statusPort,omitempty"`
- Gui *GUIConfig
`protobuf:"bytes,3,opt,name=gui,proto3" json:"gui,omitempty"`
- ConfigValidation bool
`protobuf:"varint,4,opt,name=configValidation,proto3"
json:"configValidation,omitempty"`
- Multicluster *MulticlusterConfig
`protobuf:"bytes,5,opt,name=multicluster,proto3" json:"multicluster,omitempty"`
+func (x *ProxylessConfig) Reset() {
+ *x = ProxylessConfig{}
+ mi := &file_values_types_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
-func (x *GlobalConfig) Reset() {
- *x = GlobalConfig{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[2]
+func (x *ProxylessConfig) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ProxylessConfig) ProtoMessage() {}
+
+func (x *ProxylessConfig) ProtoReflect() protoreflect.Message {
+ mi := &file_values_types_proto_msgTypes[2]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ProxylessConfig.ProtoReflect.Descriptor instead.
+func (*ProxylessConfig) Descriptor() ([]byte, []int) {
+ return file_values_types_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ProxylessConfig) GetCni() *MeshCNIConfig {
+ if x != nil {
+ return x.Cni
+ }
+ return nil
+}
+
+type MeshCNIConfig struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Enabled bool
`protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ Image string
`protobuf:"bytes,2,opt,name=image,proto3" json:"image,omitempty"`
+ BinDir string
`protobuf:"bytes,3,opt,name=binDir,proto3" json:"binDir,omitempty"`
+ ConfDir string
`protobuf:"bytes,4,opt,name=confDir,proto3" json:"confDir,omitempty"`
+ StateDir string
`protobuf:"bytes,5,opt,name=stateDir,proto3" json:"stateDir,omitempty"`
+ XserverPort int64
`protobuf:"varint,6,opt,name=xserverPort,proto3" json:"xserverPort,omitempty"`
+ ManagedLabel string
`protobuf:"bytes,7,opt,name=managedLabel,proto3" json:"managedLabel,omitempty"`
+ ManagedLabelValue string
`protobuf:"bytes,8,opt,name=managedLabelValue,proto3"
json:"managedLabelValue,omitempty"`
+ IptablesPath string
`protobuf:"bytes,9,opt,name=iptablesPath,proto3" json:"iptablesPath,omitempty"`
+ IpsetPath string
`protobuf:"bytes,10,opt,name=ipsetPath,proto3" json:"ipsetPath,omitempty"`
+ RefreshInterval string
`protobuf:"bytes,11,opt,name=refreshInterval,proto3"
json:"refreshInterval,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *MeshCNIConfig) Reset() {
+ *x = MeshCNIConfig{}
+ mi := &file_values_types_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *MeshCNIConfig) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MeshCNIConfig) ProtoMessage() {}
+
+func (x *MeshCNIConfig) ProtoReflect() protoreflect.Message {
+ mi := &file_values_types_proto_msgTypes[3]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use MeshCNIConfig.ProtoReflect.Descriptor instead.
+func (*MeshCNIConfig) Descriptor() ([]byte, []int) {
+ return file_values_types_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *MeshCNIConfig) GetEnabled() bool {
+ if x != nil {
+ return x.Enabled
+ }
+ return false
+}
+
+func (x *MeshCNIConfig) GetImage() string {
+ if x != nil {
+ return x.Image
+ }
+ return ""
+}
+
+func (x *MeshCNIConfig) GetBinDir() string {
+ if x != nil {
+ return x.BinDir
+ }
+ return ""
+}
+
+func (x *MeshCNIConfig) GetConfDir() string {
+ if x != nil {
+ return x.ConfDir
+ }
+ return ""
+}
+
+func (x *MeshCNIConfig) GetStateDir() string {
+ if x != nil {
+ return x.StateDir
+ }
+ return ""
+}
+
+func (x *MeshCNIConfig) GetXserverPort() int64 {
+ if x != nil {
+ return x.XserverPort
+ }
+ return 0
+}
+
+func (x *MeshCNIConfig) GetManagedLabel() string {
+ if x != nil {
+ return x.ManagedLabel
+ }
+ return ""
+}
+
+func (x *MeshCNIConfig) GetManagedLabelValue() string {
+ if x != nil {
+ return x.ManagedLabelValue
+ }
+ return ""
+}
+
+func (x *MeshCNIConfig) GetIptablesPath() string {
+ if x != nil {
+ return x.IptablesPath
+ }
+ return ""
+}
+
+func (x *MeshCNIConfig) GetIpsetPath() string {
+ if x != nil {
+ return x.IpsetPath
}
+ return ""
+}
+
+func (x *MeshCNIConfig) GetRefreshInterval() string {
+ if x != nil {
+ return x.RefreshInterval
+ }
+ return ""
+}
+
+type GlobalConfig struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Proxy *ProxyConfig
`protobuf:"bytes,1,opt,name=proxy,proto3" json:"proxy,omitempty"`
+ StatusPort int64
`protobuf:"varint,2,opt,name=statusPort,proto3" json:"statusPort,omitempty"`
+ Gui *GUIConfig
`protobuf:"bytes,3,opt,name=gui,proto3" json:"gui,omitempty"`
+ ConfigValidation bool
`protobuf:"varint,4,opt,name=configValidation,proto3"
json:"configValidation,omitempty"`
+ Multicluster *MulticlusterConfig
`protobuf:"bytes,5,opt,name=multicluster,proto3" json:"multicluster,omitempty"`
+ Proxyless *ProxylessConfig
`protobuf:"bytes,6,opt,name=proxyless,proto3" json:"proxyless,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *GlobalConfig) Reset() {
+ *x = GlobalConfig{}
+ mi := &file_values_types_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *GlobalConfig) String() string {
@@ -167,8 +328,8 @@ func (x *GlobalConfig) String() string {
func (*GlobalConfig) ProtoMessage() {}
func (x *GlobalConfig) ProtoReflect() protoreflect.Message {
- mi := &file_values_types_proto_msgTypes[2]
- if protoimpl.UnsafeEnabled && x != nil {
+ mi := &file_values_types_proto_msgTypes[4]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -180,7 +341,7 @@ func (x *GlobalConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use GlobalConfig.ProtoReflect.Descriptor instead.
func (*GlobalConfig) Descriptor() ([]byte, []int) {
- return file_values_types_proto_rawDescGZIP(), []int{2}
+ return file_values_types_proto_rawDescGZIP(), []int{4}
}
func (x *GlobalConfig) GetProxy() *ProxyConfig {
@@ -218,26 +379,30 @@ func (x *GlobalConfig) GetMulticluster()
*MulticlusterConfig {
return nil
}
-type RemoteAccessConfig struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+func (x *GlobalConfig) GetProxyless() *ProxylessConfig {
+ if x != nil {
+ return x.Proxyless
+ }
+ return nil
+}
- Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3"
json:"enabled,omitempty"`
- ServiceType string
`protobuf:"bytes,2,opt,name=serviceType,proto3" json:"serviceType,omitempty"`
- XdsPort int64 `protobuf:"varint,3,opt,name=xdsPort,proto3"
json:"xdsPort,omitempty"`
- WebhookPort int64
`protobuf:"varint,4,opt,name=webhookPort,proto3" json:"webhookPort,omitempty"`
- CertificateHosts []string
`protobuf:"bytes,5,rep,name=certificateHosts,proto3"
json:"certificateHosts,omitempty"`
- GrpcPort int64 `protobuf:"varint,6,opt,name=grpcPort,proto3"
json:"grpcPort,omitempty"`
+type RemoteAccessConfig struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Enabled bool
`protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ ServiceType string
`protobuf:"bytes,2,opt,name=serviceType,proto3" json:"serviceType,omitempty"`
+ XdsPort int64
`protobuf:"varint,3,opt,name=xdsPort,proto3" json:"xdsPort,omitempty"`
+ WebhookPort int64
`protobuf:"varint,4,opt,name=webhookPort,proto3" json:"webhookPort,omitempty"`
+ CertificateHosts []string
`protobuf:"bytes,5,rep,name=certificateHosts,proto3"
json:"certificateHosts,omitempty"`
+ GrpcPort int64
`protobuf:"varint,6,opt,name=grpcPort,proto3" json:"grpcPort,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *RemoteAccessConfig) Reset() {
*x = RemoteAccessConfig{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[3]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *RemoteAccessConfig) String() string {
@@ -247,8 +412,8 @@ func (x *RemoteAccessConfig) String() string {
func (*RemoteAccessConfig) ProtoMessage() {}
func (x *RemoteAccessConfig) ProtoReflect() protoreflect.Message {
- mi := &file_values_types_proto_msgTypes[3]
- if protoimpl.UnsafeEnabled && x != nil {
+ mi := &file_values_types_proto_msgTypes[5]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -260,7 +425,7 @@ func (x *RemoteAccessConfig) ProtoReflect()
protoreflect.Message {
// Deprecated: Use RemoteAccessConfig.ProtoReflect.Descriptor instead.
func (*RemoteAccessConfig) Descriptor() ([]byte, []int) {
- return file_values_types_proto_rawDescGZIP(), []int{3}
+ return file_values_types_proto_rawDescGZIP(), []int{5}
}
func (x *RemoteAccessConfig) GetEnabled() bool {
@@ -306,22 +471,19 @@ func (x *RemoteAccessConfig) GetGrpcPort() int64 {
}
type EastWestGatewayEndpoint struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ ClusterName string
`protobuf:"bytes,1,opt,name=clusterName,proto3" json:"clusterName,omitempty"`
+ Address string
`protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
+ Port int64
`protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
unknownFields protoimpl.UnknownFields
-
- ClusterName string `protobuf:"bytes,1,opt,name=clusterName,proto3"
json:"clusterName,omitempty"`
- Address string `protobuf:"bytes,2,opt,name=address,proto3"
json:"address,omitempty"`
- Port int64 `protobuf:"varint,3,opt,name=port,proto3"
json:"port,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *EastWestGatewayEndpoint) Reset() {
*x = EastWestGatewayEndpoint{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[4]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *EastWestGatewayEndpoint) String() string {
@@ -331,8 +493,8 @@ func (x *EastWestGatewayEndpoint) String() string {
func (*EastWestGatewayEndpoint) ProtoMessage() {}
func (x *EastWestGatewayEndpoint) ProtoReflect() protoreflect.Message {
- mi := &file_values_types_proto_msgTypes[4]
- if protoimpl.UnsafeEnabled && x != nil {
+ mi := &file_values_types_proto_msgTypes[6]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -344,7 +506,7 @@ func (x *EastWestGatewayEndpoint) ProtoReflect()
protoreflect.Message {
// Deprecated: Use EastWestGatewayEndpoint.ProtoReflect.Descriptor instead.
func (*EastWestGatewayEndpoint) Descriptor() ([]byte, []int) {
- return file_values_types_proto_rawDescGZIP(), []int{4}
+ return file_values_types_proto_rawDescGZIP(), []int{6}
}
func (x *EastWestGatewayEndpoint) GetClusterName() string {
@@ -369,26 +531,23 @@ func (x *EastWestGatewayEndpoint) GetPort() int64 {
}
type EastWestGatewayConfig struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Enabled bool
`protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ ServiceType string
`protobuf:"bytes,2,opt,name=serviceType,proto3" json:"serviceType,omitempty"`
+ Port int64
`protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
+ TargetPort int64
`protobuf:"varint,4,opt,name=targetPort,proto3" json:"targetPort,omitempty"`
+ NodePort int64
`protobuf:"varint,5,opt,name=nodePort,proto3" json:"nodePort,omitempty"`
+ Gateways []*EastWestGatewayEndpoint
`protobuf:"bytes,6,rep,name=gateways,proto3" json:"gateways,omitempty"`
+ XdsAddress string
`protobuf:"bytes,7,opt,name=xdsAddress,proto3" json:"xdsAddress,omitempty"`
unknownFields protoimpl.UnknownFields
-
- Enabled bool
`protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
- ServiceType string
`protobuf:"bytes,2,opt,name=serviceType,proto3" json:"serviceType,omitempty"`
- Port int64
`protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
- TargetPort int64
`protobuf:"varint,4,opt,name=targetPort,proto3" json:"targetPort,omitempty"`
- NodePort int64
`protobuf:"varint,5,opt,name=nodePort,proto3" json:"nodePort,omitempty"`
- Gateways []*EastWestGatewayEndpoint
`protobuf:"bytes,6,rep,name=gateways,proto3" json:"gateways,omitempty"`
- XdsAddress string
`protobuf:"bytes,7,opt,name=xdsAddress,proto3" json:"xdsAddress,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *EastWestGatewayConfig) Reset() {
*x = EastWestGatewayConfig{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[5]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *EastWestGatewayConfig) String() string {
@@ -398,8 +557,8 @@ func (x *EastWestGatewayConfig) String() string {
func (*EastWestGatewayConfig) ProtoMessage() {}
func (x *EastWestGatewayConfig) ProtoReflect() protoreflect.Message {
- mi := &file_values_types_proto_msgTypes[5]
- if protoimpl.UnsafeEnabled && x != nil {
+ mi := &file_values_types_proto_msgTypes[7]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -411,7 +570,7 @@ func (x *EastWestGatewayConfig) ProtoReflect()
protoreflect.Message {
// Deprecated: Use EastWestGatewayConfig.ProtoReflect.Descriptor instead.
func (*EastWestGatewayConfig) Descriptor() ([]byte, []int) {
- return file_values_types_proto_rawDescGZIP(), []int{5}
+ return file_values_types_proto_rawDescGZIP(), []int{7}
}
func (x *EastWestGatewayConfig) GetEnabled() bool {
@@ -464,21 +623,18 @@ func (x *EastWestGatewayConfig) GetXdsAddress() string {
}
type MulticlusterConfig struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
RemoteAccess *RemoteAccessConfig
`protobuf:"bytes,1,opt,name=remoteAccess,proto3" json:"remoteAccess,omitempty"`
EastWestGateway *EastWestGatewayConfig
`protobuf:"bytes,2,opt,name=eastWestGateway,proto3"
json:"eastWestGateway,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *MulticlusterConfig) Reset() {
*x = MulticlusterConfig{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[6]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *MulticlusterConfig) String() string {
@@ -488,8 +644,8 @@ func (x *MulticlusterConfig) String() string {
func (*MulticlusterConfig) ProtoMessage() {}
func (x *MulticlusterConfig) ProtoReflect() protoreflect.Message {
- mi := &file_values_types_proto_msgTypes[6]
- if protoimpl.UnsafeEnabled && x != nil {
+ mi := &file_values_types_proto_msgTypes[8]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -501,7 +657,7 @@ func (x *MulticlusterConfig) ProtoReflect()
protoreflect.Message {
// Deprecated: Use MulticlusterConfig.ProtoReflect.Descriptor instead.
func (*MulticlusterConfig) Descriptor() ([]byte, []int) {
- return file_values_types_proto_rawDescGZIP(), []int{6}
+ return file_values_types_proto_rawDescGZIP(), []int{8}
}
func (x *MulticlusterConfig) GetRemoteAccess() *RemoteAccessConfig {
@@ -519,23 +675,20 @@ func (x *MulticlusterConfig) GetEastWestGateway()
*EastWestGatewayConfig {
}
type Values struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
+ state protoimpl.MessageState `protogen:"open.v1"`
// Global configuration for dubbo components.
Global *GlobalConfig `protobuf:"bytes,1,opt,name=global,proto3"
json:"global,omitempty"`
// Revision for rendered control plane resources.
- Revision string `protobuf:"bytes,2,opt,name=revision,proto3"
json:"revision,omitempty"`
+ Revision string `protobuf:"bytes,2,opt,name=revision,proto3"
json:"revision,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
}
func (x *Values) Reset() {
*x = Values{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[7]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *Values) String() string {
@@ -545,8 +698,8 @@ func (x *Values) String() string {
func (*Values) ProtoMessage() {}
func (x *Values) ProtoReflect() protoreflect.Message {
- mi := &file_values_types_proto_msgTypes[7]
- if protoimpl.UnsafeEnabled && x != nil {
+ mi := &file_values_types_proto_msgTypes[9]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -558,7 +711,7 @@ func (x *Values) ProtoReflect() protoreflect.Message {
// Deprecated: Use Values.ProtoReflect.Descriptor instead.
func (*Values) Descriptor() ([]byte, []int) {
- return file_values_types_proto_rawDescGZIP(), []int{7}
+ return file_values_types_proto_rawDescGZIP(), []int{9}
}
func (x *Values) GetGlobal() *GlobalConfig {
@@ -585,22 +738,19 @@ func (x *Values) GetRevision() string {
// +protobuf.options.(gogoproto.goproto_stringer)=false
// +k8s:openapi-gen=true
type IntOrString struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Type int64
`protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"`
+ IntVal *wrapperspb.Int32Value
`protobuf:"bytes,2,opt,name=intVal,proto3" json:"intVal,omitempty"`
+ StrVal *wrapperspb.StringValue
`protobuf:"bytes,3,opt,name=strVal,proto3" json:"strVal,omitempty"`
unknownFields protoimpl.UnknownFields
-
- Type int64
`protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"`
- IntVal *wrapperspb.Int32Value
`protobuf:"bytes,2,opt,name=intVal,proto3" json:"intVal,omitempty"`
- StrVal *wrapperspb.StringValue
`protobuf:"bytes,3,opt,name=strVal,proto3" json:"strVal,omitempty"`
+ sizeCache protoimpl.SizeCache
}
func (x *IntOrString) Reset() {
*x = IntOrString{}
- if protoimpl.UnsafeEnabled {
- mi := &file_values_types_proto_msgTypes[8]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+ mi := &file_values_types_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
func (x *IntOrString) String() string {
@@ -610,8 +760,8 @@ func (x *IntOrString) String() string {
func (*IntOrString) ProtoMessage() {}
func (x *IntOrString) ProtoReflect() protoreflect.Message {
- mi := &file_values_types_proto_msgTypes[8]
- if protoimpl.UnsafeEnabled && x != nil {
+ mi := &file_values_types_proto_msgTypes[10]
+ if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -623,7 +773,7 @@ func (x *IntOrString) ProtoReflect() protoreflect.Message {
// Deprecated: Use IntOrString.ProtoReflect.Descriptor instead.
func (*IntOrString) Descriptor() ([]byte, []int) {
- return file_values_types_proto_rawDescGZIP(), []int{8}
+ return file_values_types_proto_rawDescGZIP(), []int{10}
}
func (x *IntOrString) GetType() int64 {
@@ -649,149 +799,117 @@ func (x *IntOrString) GetStrVal()
*wrapperspb.StringValue {
var File_values_types_proto protoreflect.FileDescriptor
-var file_values_types_proto_rawDesc = []byte{
- 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5f, 0x74, 0x79, 0x70,
0x65, 0x73, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e,
0x6f, 0x70, 0x65, 0x72,
- 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x1a, 0x1e, 0x67,
- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2f, 0x77,
- 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x22, 0x3b, 0x0a,
- 0x09, 0x47, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12,
0x0a, 0x04, 0x70, 0x6f,
- 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x70, 0x6f,
0x72, 0x74, 0x12, 0x1a,
- 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x03,
- 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x33,
0x0a, 0x0b, 0x50, 0x72,
- 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a,
0x0d, 0x63, 0x6c, 0x75,
- 0x73, 0x74, 0x65, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x44, 0x6f, 0x6d,
0x61, 0x69, 0x6e, 0x22,
- 0x9d, 0x02, 0x0a, 0x0c, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67,
- 0x12, 0x3a, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32,
- 0x24, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x72,
0x61, 0x74, 0x6f, 0x72,
- 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72,
0x6f, 0x78, 0x79, 0x43,
- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x78, 0x79,
0x12, 0x1e, 0x0a, 0x0a,
- 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x03,
- 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x6f, 0x72, 0x74,
0x12, 0x34, 0x0a, 0x03,
- 0x67, 0x75, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e,
0x64, 0x75, 0x62, 0x62,
- 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70,
- 0x68, 0x61, 0x31, 0x2e, 0x47, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x52, 0x03, 0x67,
- 0x75, 0x69, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x56, 0x61, 0x6c, 0x69,
- 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
0x52, 0x10, 0x63, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x12, 0x4f,
- 0x0a, 0x0c, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74,
0x65, 0x72, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f,
0x2e, 0x6f, 0x70, 0x65,
- 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x4d,
- 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43,
0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x52, 0x0c, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x6c, 0x75, 0x73,
0x74, 0x65, 0x72, 0x22,
- 0xd4, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x63,
0x63, 0x65, 0x73, 0x73,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e,
0x61, 0x62, 0x6c, 0x65,
- 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61,
0x62, 0x6c, 0x65, 0x64,
- 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54,
0x79, 0x70, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x54, 0x79,
- 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x78, 0x64, 0x73, 0x50, 0x6f, 0x72,
0x74, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x07, 0x78, 0x64, 0x73, 0x50, 0x6f, 0x72, 0x74,
0x12, 0x20, 0x0a, 0x0b,
- 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x50, 0x6f, 0x72, 0x74, 0x18,
0x04, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x0b, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x50, 0x6f,
0x72, 0x74, 0x12, 0x2a,
- 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x65, 0x48, 0x6f, 0x73,
- 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, 0x65,
0x72, 0x74, 0x69, 0x66,
- 0x69, 0x63, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1a,
0x0a, 0x08, 0x67, 0x72,
- 0x70, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
0x52, 0x08, 0x67, 0x72,
- 0x70, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x69, 0x0a, 0x17, 0x45, 0x61,
0x73, 0x74, 0x57, 0x65,
- 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x6e, 0x64,
0x70, 0x6f, 0x69, 0x6e,
- 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
0x4e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73,
0x74, 0x65, 0x72, 0x4e,
- 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
0x73, 0x12, 0x12, 0x0a,
- 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
0x04, 0x70, 0x6f, 0x72,
- 0x74, 0x22, 0x91, 0x02, 0x0a, 0x15, 0x45, 0x61, 0x73, 0x74, 0x57, 0x65,
0x73, 0x74, 0x47, 0x61,
- 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x18, 0x0a, 0x07, 0x65,
- 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
0x52, 0x07, 0x65, 0x6e,
- 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65,
- 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
0x73, 0x65, 0x72, 0x76,
- 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70,
0x6f, 0x72, 0x74, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12,
0x1e, 0x0a, 0x0a, 0x74,
- 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20,
0x01, 0x28, 0x03, 0x52,
- 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12,
0x1a, 0x0a, 0x08, 0x6e,
- 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
0x03, 0x52, 0x08, 0x6e,
- 0x6f, 0x64, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x4c, 0x0a, 0x08, 0x67,
0x61, 0x74, 0x65, 0x77,
- 0x61, 0x79, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e,
0x64, 0x75, 0x62, 0x62,
- 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70,
- 0x68, 0x61, 0x31, 0x2e, 0x45, 0x61, 0x73, 0x74, 0x57, 0x65, 0x73, 0x74,
0x47, 0x61, 0x74, 0x65,
- 0x77, 0x61, 0x79, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52,
0x08, 0x67, 0x61, 0x74,
- 0x65, 0x77, 0x61, 0x79, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x78, 0x64, 0x73,
0x41, 0x64, 0x64, 0x72,
- 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x78,
0x64, 0x73, 0x41, 0x64,
- 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xbf, 0x01, 0x0a, 0x12, 0x4d, 0x75,
0x6c, 0x74, 0x69, 0x63,
- 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x4f, 0x0a, 0x0c,
- 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x6f,
0x70, 0x65, 0x72, 0x61,
- 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x52, 0x65, 0x6d,
- 0x6f, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x52,
- 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73,
0x73, 0x12, 0x58, 0x0a,
- 0x0f, 0x65, 0x61, 0x73, 0x74, 0x57, 0x65, 0x73, 0x74, 0x47, 0x61, 0x74,
0x65, 0x77, 0x61, 0x79,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x64, 0x75, 0x62,
0x62, 0x6f, 0x2e, 0x6f,
- 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31,
- 0x2e, 0x45, 0x61, 0x73, 0x74, 0x57, 0x65, 0x73, 0x74, 0x47, 0x61, 0x74,
0x65, 0x77, 0x61, 0x79,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x65, 0x61, 0x73, 0x74,
0x57, 0x65, 0x73, 0x74,
- 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x22, 0x63, 0x0a, 0x06, 0x56,
0x61, 0x6c, 0x75, 0x65,
- 0x73, 0x12, 0x3d, 0x0a, 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x18,
0x01, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x25, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x6f, 0x70,
0x65, 0x72, 0x61, 0x74,
- 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x47, 0x6c, 0x6f, 0x62,
- 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x67, 0x6c,
0x6f, 0x62, 0x61, 0x6c,
- 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x22, 0x8c, 0x01, 0x0a,
- 0x0b, 0x49, 0x6e, 0x74, 0x4f, 0x72, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x12, 0x12, 0x0a, 0x04,
- 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04,
0x74, 0x79, 0x70, 0x65,
- 0x12, 0x33, 0x0a, 0x06, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62,
- 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x52, 0x06, 0x69,
- 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x72,
0x56, 0x61, 0x6c, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x56, 0x61,
- 0x6c, 0x75, 0x65, 0x52, 0x06, 0x73, 0x74, 0x72, 0x56, 0x61, 0x6c, 0x42,
0x2f, 0x5a, 0x2d, 0x64,
- 0x75, 0x62, 0x62, 0x6f, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e,
0x6f, 0x72, 0x67, 0x2f,
- 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x6f,
0x70, 0x65, 0x72, 0x61,
- 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x73,
0x62, 0x06, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x33,
-}
+const file_values_types_proto_rawDesc = "" +
+ "\n" +
+
"\x12values_types.proto\x12\x17dubbo.operator.v1alpha1\x1a\x1egoogle/protobuf/wrappers.proto\";\n"
+
+ "\tGUIConfig\x12\x12\n" +
+ "\x04port\x18\x01 \x01(\x03R\x04port\x12\x1a\n" +
+ "\bnodePort\x18\x02 \x01(\x03R\bnodePort\"3\n" +
+ "\vProxyConfig\x12$\n" +
+ "\rclusterDomain\x18\x01 \x01(\tR\rclusterDomain\"K\n" +
+ "\x0fProxylessConfig\x128\n" +
+ "\x03cni\x18\x01
\x01(\v2&.dubbo.operator.v1alpha1.MeshCNIConfigR\x03cni\"\xed\x02\n" +
+ "\rMeshCNIConfig\x12\x18\n" +
+ "\aenabled\x18\x01 \x01(\bR\aenabled\x12\x14\n" +
+ "\x05image\x18\x02 \x01(\tR\x05image\x12\x16\n" +
+ "\x06binDir\x18\x03 \x01(\tR\x06binDir\x12\x18\n" +
+ "\aconfDir\x18\x04 \x01(\tR\aconfDir\x12\x1a\n" +
+ "\bstateDir\x18\x05 \x01(\tR\bstateDir\x12 \n" +
+ "\vxserverPort\x18\x06 \x01(\x03R\vxserverPort\x12\"\n" +
+ "\fmanagedLabel\x18\a \x01(\tR\fmanagedLabel\x12,\n" +
+ "\x11managedLabelValue\x18\b \x01(\tR\x11managedLabelValue\x12\"\n" +
+ "\fiptablesPath\x18\t \x01(\tR\fiptablesPath\x12\x1c\n" +
+ "\tipsetPath\x18\n" +
+ " \x01(\tR\tipsetPath\x12(\n" +
+ "\x0frefreshInterval\x18\v \x01(\tR\x0frefreshInterval\"\xe5\x02\n" +
+ "\fGlobalConfig\x12:\n" +
+ "\x05proxy\x18\x01
\x01(\v2$.dubbo.operator.v1alpha1.ProxyConfigR\x05proxy\x12\x1e\n" +
+ "\n" +
+ "statusPort\x18\x02 \x01(\x03R\n" +
+ "statusPort\x124\n" +
+ "\x03gui\x18\x03
\x01(\v2\".dubbo.operator.v1alpha1.GUIConfigR\x03gui\x12*\n" +
+ "\x10configValidation\x18\x04 \x01(\bR\x10configValidation\x12O\n" +
+ "\fmulticluster\x18\x05
\x01(\v2+.dubbo.operator.v1alpha1.MulticlusterConfigR\fmulticluster\x12F\n" +
+ "\tproxyless\x18\x06
\x01(\v2(.dubbo.operator.v1alpha1.ProxylessConfigR\tproxyless\"\xd4\x01\n" +
+ "\x12RemoteAccessConfig\x12\x18\n" +
+ "\aenabled\x18\x01 \x01(\bR\aenabled\x12 \n" +
+ "\vserviceType\x18\x02 \x01(\tR\vserviceType\x12\x18\n" +
+ "\axdsPort\x18\x03 \x01(\x03R\axdsPort\x12 \n" +
+ "\vwebhookPort\x18\x04 \x01(\x03R\vwebhookPort\x12*\n" +
+ "\x10certificateHosts\x18\x05 \x03(\tR\x10certificateHosts\x12\x1a\n" +
+ "\bgrpcPort\x18\x06 \x01(\x03R\bgrpcPort\"i\n" +
+ "\x17EastWestGatewayEndpoint\x12 \n" +
+ "\vclusterName\x18\x01 \x01(\tR\vclusterName\x12\x18\n" +
+ "\aaddress\x18\x02 \x01(\tR\aaddress\x12\x12\n" +
+ "\x04port\x18\x03 \x01(\x03R\x04port\"\x91\x02\n" +
+ "\x15EastWestGatewayConfig\x12\x18\n" +
+ "\aenabled\x18\x01 \x01(\bR\aenabled\x12 \n" +
+ "\vserviceType\x18\x02 \x01(\tR\vserviceType\x12\x12\n" +
+ "\x04port\x18\x03 \x01(\x03R\x04port\x12\x1e\n" +
+ "\n" +
+ "targetPort\x18\x04 \x01(\x03R\n" +
+ "targetPort\x12\x1a\n" +
+ "\bnodePort\x18\x05 \x01(\x03R\bnodePort\x12L\n" +
+ "\bgateways\x18\x06
\x03(\v20.dubbo.operator.v1alpha1.EastWestGatewayEndpointR\bgateways\x12\x1e\n"
+
+ "\n" +
+ "xdsAddress\x18\a \x01(\tR\n" +
+ "xdsAddress\"\xbf\x01\n" +
+ "\x12MulticlusterConfig\x12O\n" +
+ "\fremoteAccess\x18\x01
\x01(\v2+.dubbo.operator.v1alpha1.RemoteAccessConfigR\fremoteAccess\x12X\n" +
+ "\x0feastWestGateway\x18\x02
\x01(\v2..dubbo.operator.v1alpha1.EastWestGatewayConfigR\x0feastWestGateway\"c\n"
+
+ "\x06Values\x12=\n" +
+ "\x06global\x18\x01
\x01(\v2%.dubbo.operator.v1alpha1.GlobalConfigR\x06global\x12\x1a\n" +
+ "\brevision\x18\x02 \x01(\tR\brevision\"\x8c\x01\n" +
+ "\vIntOrString\x12\x12\n" +
+ "\x04type\x18\x01 \x01(\x03R\x04type\x123\n" +
+ "\x06intVal\x18\x02
\x01(\v2\x1b.google.protobuf.Int32ValueR\x06intVal\x124\n" +
+ "\x06strVal\x18\x03
\x01(\v2\x1c.google.protobuf.StringValueR\x06strValB/Z-dubbo.apache.org/dubbo/dubbooperator/pkg/apisb\x06proto3"
var (
file_values_types_proto_rawDescOnce sync.Once
- file_values_types_proto_rawDescData = file_values_types_proto_rawDesc
+ file_values_types_proto_rawDescData []byte
)
func file_values_types_proto_rawDescGZIP() []byte {
file_values_types_proto_rawDescOnce.Do(func() {
- file_values_types_proto_rawDescData =
protoimpl.X.CompressGZIP(file_values_types_proto_rawDescData)
+ file_values_types_proto_rawDescData =
protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_values_types_proto_rawDesc),
len(file_values_types_proto_rawDesc)))
})
return file_values_types_proto_rawDescData
}
-var file_values_types_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
-var file_values_types_proto_goTypes = []interface{}{
+var file_values_types_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
+var file_values_types_proto_goTypes = []any{
(*GUIConfig)(nil), // 0: dubbo.operator.v1alpha1.GUIConfig
(*ProxyConfig)(nil), // 1:
dubbo.operator.v1alpha1.ProxyConfig
- (*GlobalConfig)(nil), // 2:
dubbo.operator.v1alpha1.GlobalConfig
- (*RemoteAccessConfig)(nil), // 3:
dubbo.operator.v1alpha1.RemoteAccessConfig
- (*EastWestGatewayEndpoint)(nil), // 4:
dubbo.operator.v1alpha1.EastWestGatewayEndpoint
- (*EastWestGatewayConfig)(nil), // 5:
dubbo.operator.v1alpha1.EastWestGatewayConfig
- (*MulticlusterConfig)(nil), // 6:
dubbo.operator.v1alpha1.MulticlusterConfig
- (*Values)(nil), // 7: dubbo.operator.v1alpha1.Values
- (*IntOrString)(nil), // 8:
dubbo.operator.v1alpha1.IntOrString
- (*wrapperspb.Int32Value)(nil), // 9: google.protobuf.Int32Value
- (*wrapperspb.StringValue)(nil), // 10: google.protobuf.StringValue
+ (*ProxylessConfig)(nil), // 2:
dubbo.operator.v1alpha1.ProxylessConfig
+ (*MeshCNIConfig)(nil), // 3:
dubbo.operator.v1alpha1.MeshCNIConfig
+ (*GlobalConfig)(nil), // 4:
dubbo.operator.v1alpha1.GlobalConfig
+ (*RemoteAccessConfig)(nil), // 5:
dubbo.operator.v1alpha1.RemoteAccessConfig
+ (*EastWestGatewayEndpoint)(nil), // 6:
dubbo.operator.v1alpha1.EastWestGatewayEndpoint
+ (*EastWestGatewayConfig)(nil), // 7:
dubbo.operator.v1alpha1.EastWestGatewayConfig
+ (*MulticlusterConfig)(nil), // 8:
dubbo.operator.v1alpha1.MulticlusterConfig
+ (*Values)(nil), // 9: dubbo.operator.v1alpha1.Values
+ (*IntOrString)(nil), // 10:
dubbo.operator.v1alpha1.IntOrString
+ (*wrapperspb.Int32Value)(nil), // 11: google.protobuf.Int32Value
+ (*wrapperspb.StringValue)(nil), // 12: google.protobuf.StringValue
}
var file_values_types_proto_depIdxs = []int32{
- 1, // 0: dubbo.operator.v1alpha1.GlobalConfig.proxy:type_name ->
dubbo.operator.v1alpha1.ProxyConfig
- 0, // 1: dubbo.operator.v1alpha1.GlobalConfig.gui:type_name ->
dubbo.operator.v1alpha1.GUIConfig
- 6, // 2: dubbo.operator.v1alpha1.GlobalConfig.multicluster:type_name
-> dubbo.operator.v1alpha1.MulticlusterConfig
- 4, // 3:
dubbo.operator.v1alpha1.EastWestGatewayConfig.gateways:type_name ->
dubbo.operator.v1alpha1.EastWestGatewayEndpoint
- 3, // 4:
dubbo.operator.v1alpha1.MulticlusterConfig.remoteAccess:type_name ->
dubbo.operator.v1alpha1.RemoteAccessConfig
- 5, // 5:
dubbo.operator.v1alpha1.MulticlusterConfig.eastWestGateway:type_name ->
dubbo.operator.v1alpha1.EastWestGatewayConfig
- 2, // 6: dubbo.operator.v1alpha1.Values.global:type_name ->
dubbo.operator.v1alpha1.GlobalConfig
- 9, // 7: dubbo.operator.v1alpha1.IntOrString.intVal:type_name ->
google.protobuf.Int32Value
- 10, // 8: dubbo.operator.v1alpha1.IntOrString.strVal:type_name ->
google.protobuf.StringValue
- 9, // [9:9] is the sub-list for method output_type
- 9, // [9:9] is the sub-list for method input_type
- 9, // [9:9] is the sub-list for extension type_name
- 9, // [9:9] is the sub-list for extension extendee
- 0, // [0:9] is the sub-list for field type_name
+ 3, // 0: dubbo.operator.v1alpha1.ProxylessConfig.cni:type_name ->
dubbo.operator.v1alpha1.MeshCNIConfig
+ 1, // 1: dubbo.operator.v1alpha1.GlobalConfig.proxy:type_name ->
dubbo.operator.v1alpha1.ProxyConfig
+ 0, // 2: dubbo.operator.v1alpha1.GlobalConfig.gui:type_name ->
dubbo.operator.v1alpha1.GUIConfig
+ 8, // 3: dubbo.operator.v1alpha1.GlobalConfig.multicluster:type_name
-> dubbo.operator.v1alpha1.MulticlusterConfig
+ 2, // 4: dubbo.operator.v1alpha1.GlobalConfig.proxyless:type_name ->
dubbo.operator.v1alpha1.ProxylessConfig
+ 6, // 5:
dubbo.operator.v1alpha1.EastWestGatewayConfig.gateways:type_name ->
dubbo.operator.v1alpha1.EastWestGatewayEndpoint
+ 5, // 6:
dubbo.operator.v1alpha1.MulticlusterConfig.remoteAccess:type_name ->
dubbo.operator.v1alpha1.RemoteAccessConfig
+ 7, // 7:
dubbo.operator.v1alpha1.MulticlusterConfig.eastWestGateway:type_name ->
dubbo.operator.v1alpha1.EastWestGatewayConfig
+ 4, // 8: dubbo.operator.v1alpha1.Values.global:type_name ->
dubbo.operator.v1alpha1.GlobalConfig
+ 11, // 9: dubbo.operator.v1alpha1.IntOrString.intVal:type_name ->
google.protobuf.Int32Value
+ 12, // 10: dubbo.operator.v1alpha1.IntOrString.strVal:type_name ->
google.protobuf.StringValue
+ 11, // [11:11] is the sub-list for method output_type
+ 11, // [11:11] is the sub-list for method input_type
+ 11, // [11:11] is the sub-list for extension type_name
+ 11, // [11:11] is the sub-list for extension extendee
+ 0, // [0:11] is the sub-list for field type_name
}
func init() { file_values_types_proto_init() }
@@ -799,123 +917,13 @@ func file_values_types_proto_init() {
if File_values_types_proto != nil {
return
}
- if !protoimpl.UnsafeEnabled {
- file_values_types_proto_msgTypes[0].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*GUIConfig); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[1].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*ProxyConfig); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[2].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*GlobalConfig); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[3].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*RemoteAccessConfig); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[4].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*EastWestGatewayEndpoint); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[5].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*EastWestGatewayConfig); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[6].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*MulticlusterConfig); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[7].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*Values); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_values_types_proto_msgTypes[8].Exporter = func(v
interface{}, i int) interface{} {
- switch v := v.(*IntOrString); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_values_types_proto_rawDesc,
+ RawDescriptor:
unsafe.Slice(unsafe.StringData(file_values_types_proto_rawDesc),
len(file_values_types_proto_rawDesc)),
NumEnums: 0,
- NumMessages: 9,
+ NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},
@@ -924,7 +932,6 @@ func file_values_types_proto_init() {
MessageInfos: file_values_types_proto_msgTypes,
}.Build()
File_values_types_proto = out.File
- file_values_types_proto_rawDesc = nil
file_values_types_proto_goTypes = nil
file_values_types_proto_depIdxs = nil
}
diff --git a/dubbooperator/pkg/render/manifest_test.go
b/dubbooperator/pkg/render/manifest_test.go
index 313b19c8..076e37b9 100644
--- a/dubbooperator/pkg/render/manifest_test.go
+++ b/dubbooperator/pkg/render/manifest_test.go
@@ -191,6 +191,73 @@ func TestGenerateManifestEastWestGatewayConfig(t
*testing.T) {
}
}
+func TestGenerateManifestProxylessCNIIsGlobalByDefault(t *testing.T) {
+ manifests, _, err := GenerateManifest(nil, nil, nil, nil)
+ if err != nil {
+ t.Fatalf("GenerateManifest() error = %v", err)
+ }
+ if !hasManifest(manifests, "DaemonSet", "dubbo-cni-node") {
+ t.Fatal("dubbo-cni-node not rendered by default")
+ }
+
+ manifests, _, err = GenerateManifest(nil,
[]string{"values.global.proxyless.cni.enabled=false"}, nil, nil)
+ if err != nil {
+ t.Fatalf("GenerateManifest() with proxyless CNI disabled error
= %v", err)
+ }
+ if hasManifest(manifests, "DaemonSet", "dubbo-cni-node") {
+ t.Fatal("dubbo-cni-node rendered while proxyless CNI is
explicitly disabled")
+ }
+
+ manifests, _, err = GenerateManifest(nil, []string{
+ "values.global.proxyless.cni.enabled=true",
+ "values.global.proxyless.cni.image=kdubbo/dubbod:cni-test",
+ "values.global.proxyless.cni.binDir=/var/lib/cni/bin",
+ "values.global.proxyless.cni.confDir=/var/lib/cni/net.d",
+ "values.global.proxyless.cni.stateDir=/run/dubbo-cni",
+ "values.global.proxyless.cni.xserverPort=16080",
+ "values.global.proxyless.cni.ipsetPath=/usr/sbin/ipset",
+ "values.global.proxyless.cni.refreshInterval=30s",
+ }, nil, nil)
+ if err != nil {
+ t.Fatalf("GenerateManifest() with proxyless CNI error = %v",
err)
+ }
+ daemonSet := findManifest(t, manifests, "DaemonSet", "dubbo-cni-node")
+ containers, ok, err := unstructured.NestedSlice(daemonSet.Object,
"spec", "template", "spec", "containers")
+ if err != nil || !ok || len(containers) == 0 {
+ t.Fatalf("daemonset containers missing: ok=%v err=%v", ok, err)
+ }
+ installer := containers[0].(map[string]interface{})
+ image, _, _ := unstructured.NestedString(installer, "image")
+ if image != "kdubbo/dubbod:cni-test" {
+ t.Fatalf("CNI installer image = %q, want
kdubbo/dubbod:cni-test", image)
+ }
+ args, ok, err := unstructured.NestedStringSlice(installer, "args")
+ if err != nil || !ok {
+ t.Fatalf("installer args missing: ok=%v err=%v", ok, err)
+ }
+ for _, want := range []string{
+ "--bin-dir=/var/lib/cni/bin",
+ "--conf-dir=/var/lib/cni/net.d",
+ "--state-dir=/run/dubbo-cni",
+ "--xserver-port=16080",
+ "--ipset-path=/usr/sbin/ipset",
+ "--refresh-interval=30s",
+ } {
+ if !containsString(args, want) {
+ t.Fatalf("installer args missing %q: %v", want, args)
+ }
+ }
+ volumes, ok, err := unstructured.NestedSlice(daemonSet.Object, "spec",
"template", "spec", "volumes")
+ if err != nil || !ok {
+ t.Fatalf("daemonset volumes missing: ok=%v err=%v", ok, err)
+ }
+ for _, want := range []string{"/var/lib/cni/bin", "/var/lib/cni/net.d",
"/run/dubbo-cni"} {
+ if !hasHostPathVolume(volumes, want) {
+ t.Fatalf("daemonset missing hostPath volume %s", want)
+ }
+ }
+}
+
func TestGenerateManifestSetOverridesHelmValues(t *testing.T) {
manifests, _, err := GenerateManifest(nil, []string{
"values.global.gui.port=26081",
@@ -380,3 +447,26 @@ func hasContainerPort(ports []interface{}, name string,
number int64) bool {
}
return false
}
+
+func containsString(items []string, want string) bool {
+ for _, item := range items {
+ if item == want {
+ return true
+ }
+ }
+ return false
+}
+
+func hasHostPathVolume(volumes []interface{}, path string) bool {
+ for _, item := range volumes {
+ volume, ok := item.(map[string]interface{})
+ if !ok {
+ continue
+ }
+ got, _, _ := unstructured.NestedString(volume, "hostPath",
"path")
+ if got == path {
+ return true
+ }
+ }
+ return false
+}
diff --git a/pkg/cni/config.go b/pkg/cni/config.go
new file mode 100644
index 00000000..eda915fd
--- /dev/null
+++ b/pkg/cni/config.go
@@ -0,0 +1,182 @@
+// 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.
+
+package cni
+
+import (
+ "encoding/json"
+ "fmt"
+ "net"
+ "os"
+ "strings"
+
+ "github.com/apache/dubbo-kubernetes/pkg/kube/inject"
+)
+
+const (
+ defaultCNIVersion = "1.0.0"
+ defaultStateDir = "/var/run/dubbo-cni"
+ defaultIPTablesPath = "iptables"
+ defaultIPSetPath = "ipset"
+ PluginType = "dubbo-cni"
+)
+
+type NetConf struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+ Name string `json:"name,omitempty"`
+ Type string `json:"type,omitempty"`
+ PrevResult json.RawMessage `json:"prevResult,omitempty"`
+ Kubernetes KubernetesConf `json:"kubernetes,omitempty"`
+ KubeConfig string `json:"kubeconfig,omitempty"`
+ ManagedLabel string `json:"managedLabel,omitempty"`
+ ManagedLabelValue string `json:"managedLabelValue,omitempty"`
+ XServerPort int `json:"xserverPort,omitempty"`
+ StateDir string `json:"stateDir,omitempty"`
+ IPTablesPath string `json:"iptablesPath,omitempty"`
+ IPSetPath string `json:"ipsetPath,omitempty"`
+ DryRun bool `json:"dryRun,omitempty"`
+}
+
+type KubernetesConf struct {
+ KubeConfig string `json:"kubeconfig,omitempty"`
+}
+
+func ParseNetConf(data []byte) (NetConf, error) {
+ conf := NetConf{}
+ if len(strings.TrimSpace(string(data))) > 0 {
+ if err := json.Unmarshal(data, &conf); err != nil {
+ return conf, fmt.Errorf("parse CNI config: %w", err)
+ }
+ }
+ if conf.CNIVersion == "" {
+ conf.CNIVersion = defaultCNIVersion
+ }
+ if conf.ManagedLabel == "" {
+ conf.ManagedLabel = inject.ProxylessManagedLabel
+ }
+ if conf.ManagedLabelValue == "" {
+ conf.ManagedLabelValue = inject.ProxylessManagedLabelValue
+ }
+ if conf.XServerPort == 0 {
+ conf.XServerPort = inject.ProxylessXServerPort
+ }
+ if conf.IPTablesPath == "" {
+ conf.IPTablesPath = defaultIPTablesPath
+ }
+ if conf.IPSetPath == "" {
+ conf.IPSetPath = defaultIPSetPath
+ }
+ return conf, nil
+}
+
+func (c NetConf) KubeConfigPath() string {
+ if c.Kubernetes.KubeConfig != "" {
+ return c.Kubernetes.KubeConfig
+ }
+ return c.KubeConfig
+}
+
+func (c NetConf) StateDirectory() string {
+ if c.StateDir != "" {
+ return c.StateDir
+ }
+ return defaultStateDir
+}
+
+func ResultOutput(conf NetConf) []byte {
+ if len(conf.PrevResult) > 0 {
+ return append([]byte(nil), conf.PrevResult...)
+ }
+ result := map[string]string{"cniVersion": conf.CNIVersion}
+ out, _ := json.Marshal(result)
+ return out
+}
+
+func PodIPsFromPrevResult(prev json.RawMessage) []string {
+ if len(prev) == 0 {
+ return nil
+ }
+ var result struct {
+ IPs []struct {
+ Address string `json:"address"`
+ } `json:"ips"`
+ }
+ if err := json.Unmarshal(prev, &result); err != nil {
+ return nil
+ }
+ ips := make([]string, 0, len(result.IPs))
+ for _, item := range result.IPs {
+ ip := strings.TrimSpace(item.Address)
+ if ip == "" {
+ continue
+ }
+ if parsedIP, _, err := net.ParseCIDR(ip); err == nil {
+ ips = append(ips, parsedIP.String())
+ continue
+ }
+ if parsedIP := net.ParseIP(ip); parsedIP != nil {
+ ips = append(ips, parsedIP.String())
+ }
+ }
+ return ips
+}
+
+type Env struct {
+ Command string
+ ContainerID string
+ NetNS string
+ IfName string
+ Args string
+}
+
+func EnvFromOS() Env {
+ return Env{
+ Command: os.Getenv("CNI_COMMAND"),
+ ContainerID: os.Getenv("CNI_CONTAINERID"),
+ NetNS: os.Getenv("CNI_NETNS"),
+ IfName: os.Getenv("CNI_IFNAME"),
+ Args: os.Getenv("CNI_ARGS"),
+ }
+}
+
+func EnvHasKubernetesPod(env Env) bool {
+ _, ok := PodRefFromCNIArgs(env.Args)
+ return ok
+}
+
+type PodRef struct {
+ Namespace string
+ Name string
+}
+
+func PodRefFromCNIArgs(args string) (PodRef, bool) {
+ values := map[string]string{}
+ for _, item := range strings.Split(args, ";") {
+ item = strings.TrimSpace(item)
+ if item == "" {
+ continue
+ }
+ key, value, ok := strings.Cut(item, "=")
+ if !ok {
+ continue
+ }
+ values[key] = value
+ }
+ ref := PodRef{
+ Namespace: values["K8S_POD_NAMESPACE"],
+ Name: values["K8S_POD_NAME"],
+ }
+ return ref, ref.Namespace != "" && ref.Name != ""
+}
diff --git a/pkg/cni/config_test.go b/pkg/cni/config_test.go
new file mode 100644
index 00000000..f4454a91
--- /dev/null
+++ b/pkg/cni/config_test.go
@@ -0,0 +1,66 @@
+// 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.
+
+package cni
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/apache/dubbo-kubernetes/pkg/kube/inject"
+)
+
+func TestParseNetConfDefaults(t *testing.T) {
+ conf, err := ParseNetConf([]byte(`{"name":"dubbo"}`))
+ if err != nil {
+ t.Fatalf("ParseNetConf() failed: %v", err)
+ }
+ if conf.CNIVersion != defaultCNIVersion {
+ t.Fatalf("cniVersion = %q, want %q", conf.CNIVersion,
defaultCNIVersion)
+ }
+ if conf.ManagedLabel != inject.ProxylessManagedLabel ||
conf.ManagedLabelValue != inject.ProxylessManagedLabelValue {
+ t.Fatalf("managed label = %s/%s, want %s/%s",
conf.ManagedLabel, conf.ManagedLabelValue,
+ inject.ProxylessManagedLabel,
inject.ProxylessManagedLabelValue)
+ }
+ if conf.XServerPort != inject.ProxylessXServerPort {
+ t.Fatalf("xserverPort = %d, want %d", conf.XServerPort,
inject.ProxylessXServerPort)
+ }
+ if conf.IPTablesPath != defaultIPTablesPath || conf.IPSetPath !=
defaultIPSetPath {
+ t.Fatalf("iptables/ipset path = %s/%s, want %s/%s",
conf.IPTablesPath, conf.IPSetPath, defaultIPTablesPath, defaultIPSetPath)
+ }
+}
+
+func TestPodRefFromCNIArgs(t *testing.T) {
+ ref, ok :=
PodRefFromCNIArgs("IgnoreUnknown=1;K8S_POD_NAMESPACE=app;K8S_POD_NAME=nginx-v1")
+ if !ok {
+ t.Fatal("PodRefFromCNIArgs() ok = false, want true")
+ }
+ if ref.Namespace != "app" || ref.Name != "nginx-v1" {
+ t.Fatalf("pod ref = %#v, want app/nginx-v1", ref)
+ }
+}
+
+func TestPodIPsFromPrevResult(t *testing.T) {
+ prev, _ := json.Marshal(map[string]any{
+ "cniVersion": "1.0.0",
+ "ips": []map[string]string{
+ {"address": "10.244.0.12/24"},
+ },
+ })
+ ips := PodIPsFromPrevResult(prev)
+ if len(ips) != 1 || ips[0] != "10.244.0.12" {
+ t.Fatalf("ips = %v, want [10.244.0.12]", ips)
+ }
+}
diff --git a/pkg/cni/install.go b/pkg/cni/install.go
new file mode 100644
index 00000000..86ae9829
--- /dev/null
+++ b/pkg/cni/install.go
@@ -0,0 +1,497 @@
+// 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.
+
+package cni
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/apache/dubbo-kubernetes/pkg/kube/inject"
+)
+
+const (
+ defaultCNIBinDir = "/opt/cni/bin"
+ defaultCNIConfDir = "/etc/cni/net.d"
+ defaultInstallerInterval = time.Minute
+ defaultKubeConfigFileName = "dubbo-cni-kubeconfig"
+ installBackupSuffix = ".dubbo-cni.bak"
+)
+
+type InstallerOptions struct {
+ SourceBinary string
+ BinDir string
+ ConfDir string
+ StateDir string
+ KubeConfigPath string
+ TokenFile string
+ CAFile string
+ ServiceAccountTokenPath string
+ ServiceAccountCAPath string
+ APIServer string
+ ManagedLabel string
+ ManagedLabelValue string
+ IPTablesPath string
+ IPSetPath string
+ XServerPort int
+}
+
+func DefaultInstallerOptions() InstallerOptions {
+ return InstallerOptions{
+ BinDir: defaultCNIBinDir,
+ ConfDir: defaultCNIConfDir,
+ StateDir: defaultStateDir,
+ ServiceAccountTokenPath:
"/var/run/secrets/kubernetes.io/serviceaccount/token",
+ ServiceAccountCAPath:
"/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
+ ManagedLabel: inject.ProxylessManagedLabel,
+ ManagedLabelValue: inject.ProxylessManagedLabelValue,
+ IPTablesPath: defaultIPTablesPath,
+ IPSetPath: defaultIPSetPath,
+ XServerPort: inject.ProxylessXServerPort,
+ }
+}
+
+func DefaultInstallerInterval() time.Duration {
+ return defaultInstallerInterval
+}
+
+func (o *InstallerOptions) applyDefaults(requireAPIServer bool) error {
+ defaults := DefaultInstallerOptions()
+ if o.SourceBinary == "" {
+ exe, err := os.Executable()
+ if err != nil {
+ return fmt.Errorf("find current executable: %w", err)
+ }
+ o.SourceBinary = exe
+ }
+ if o.BinDir == "" {
+ o.BinDir = defaults.BinDir
+ }
+ if o.ConfDir == "" {
+ o.ConfDir = defaults.ConfDir
+ }
+ if o.StateDir == "" {
+ o.StateDir = defaults.StateDir
+ }
+ if o.KubeConfigPath == "" {
+ o.KubeConfigPath = filepath.Join(o.ConfDir,
defaultKubeConfigFileName)
+ }
+ if o.TokenFile == "" {
+ o.TokenFile = filepath.Join(o.StateDir, "token")
+ }
+ if o.CAFile == "" {
+ o.CAFile = filepath.Join(o.StateDir, "ca.crt")
+ }
+ if o.ServiceAccountTokenPath == "" {
+ o.ServiceAccountTokenPath = defaults.ServiceAccountTokenPath
+ }
+ if o.ServiceAccountCAPath == "" {
+ o.ServiceAccountCAPath = defaults.ServiceAccountCAPath
+ }
+ if o.APIServer == "" {
+ o.APIServer = kubernetesServiceHost()
+ }
+ if o.ManagedLabel == "" {
+ o.ManagedLabel = defaults.ManagedLabel
+ }
+ if o.ManagedLabelValue == "" {
+ o.ManagedLabelValue = defaults.ManagedLabelValue
+ }
+ if o.IPTablesPath == "" {
+ o.IPTablesPath = defaults.IPTablesPath
+ }
+ if o.IPSetPath == "" {
+ o.IPSetPath = defaults.IPSetPath
+ }
+ if o.XServerPort == 0 {
+ o.XServerPort = defaults.XServerPort
+ }
+ if requireAPIServer && o.APIServer == "" {
+ return fmt.Errorf("kubernetes API server is required")
+ }
+ return nil
+}
+
+func Install(ctx context.Context, opts InstallerOptions) error {
+ if err := opts.applyDefaults(true); err != nil {
+ return err
+ }
+ if err := ctx.Err(); err != nil {
+ return err
+ }
+ for _, dir := range []string{opts.BinDir, opts.ConfDir, opts.StateDir} {
+ if err := os.MkdirAll(dir, 0o755); err != nil {
+ return fmt.Errorf("create %s: %w", dir, err)
+ }
+ }
+ if err := copyFileAtomic(opts.SourceBinary, filepath.Join(opts.BinDir,
PluginType), 0o755); err != nil {
+ return err
+ }
+ if err := copyFileAtomic(opts.ServiceAccountTokenPath, opts.TokenFile,
0o600); err != nil {
+ return err
+ }
+ if err := copyFileAtomic(opts.ServiceAccountCAPath, opts.CAFile,
0o644); err != nil {
+ return err
+ }
+ if err := writeKubeConfig(opts); err != nil {
+ return err
+ }
+ return installCNIConfig(opts)
+}
+
+func InstallLoop(ctx context.Context, opts InstallerOptions, interval
time.Duration) error {
+ if interval <= 0 {
+ interval = defaultInstallerInterval
+ }
+ if err := Install(ctx, opts); err != nil {
+ return err
+ }
+ ticker := time.NewTicker(interval)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ctx.Done():
+ return nil
+ case <-ticker.C:
+ if err := Install(ctx, opts); err != nil {
+ return err
+ }
+ }
+ }
+}
+
+func Uninstall(opts InstallerOptions) error {
+ if err := opts.applyDefaults(false); err != nil {
+ return err
+ }
+ if err := uninstallCNIConfig(opts.ConfDir); err != nil {
+ return err
+ }
+ for _, path := range []string{
+ filepath.Join(opts.BinDir, PluginType),
+ opts.KubeConfigPath,
+ opts.TokenFile,
+ opts.CAFile,
+ } {
+ if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
+ return fmt.Errorf("remove %s: %w", path, err)
+ }
+ }
+ return nil
+}
+
+func writeKubeConfig(opts InstallerOptions) error {
+ data := fmt.Sprintf(`apiVersion: v1
+kind: Config
+clusters:
+- name: kubernetes
+ cluster:
+ certificate-authority: %s
+ server: %s
+users:
+- name: dubbo-cni
+ user:
+ tokenFile: %s
+contexts:
+- name: dubbo-cni
+ context:
+ cluster: kubernetes
+ user: dubbo-cni
+current-context: dubbo-cni
+`, opts.CAFile, opts.APIServer, opts.TokenFile)
+ return writeFileAtomic(opts.KubeConfigPath, []byte(data), 0o600)
+}
+
+func installCNIConfig(opts InstallerOptions) error {
+ target, err := findPrimaryCNIConfig(opts.ConfDir)
+ if err != nil {
+ return err
+ }
+ if strings.HasSuffix(target, ".conflist") {
+ return patchConflist(target, pluginConfig(opts), true)
+ }
+ return convertConfToConflist(target, pluginConfig(opts))
+}
+
+func uninstallCNIConfig(confDir string) error {
+ entries, err := os.ReadDir(confDir)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ }
+ return fmt.Errorf("read CNI config dir %s: %w", confDir, err)
+ }
+ sort.Slice(entries, func(i, j int) bool { return entries[i].Name() <
entries[j].Name() })
+ for _, entry := range entries {
+ if entry.IsDir() {
+ continue
+ }
+ path := filepath.Join(confDir, entry.Name())
+ if _, err := os.Stat(path); os.IsNotExist(err) {
+ continue
+ } else if err != nil {
+ return fmt.Errorf("stat %s: %w", path, err)
+ }
+ if strings.HasSuffix(entry.Name(), installBackupSuffix) {
+ original := strings.TrimSuffix(path,
installBackupSuffix)
+ if strings.HasSuffix(original, ".conf") {
+ _ = os.Remove(strings.TrimSuffix(original,
".conf") + ".conflist")
+ }
+ if err := os.Rename(path, original); err != nil {
+ return fmt.Errorf("restore %s: %w", original,
err)
+ }
+ continue
+ }
+ if strings.HasSuffix(entry.Name(), ".conflist") {
+ if err := patchConflist(path, nil, false); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func findPrimaryCNIConfig(confDir string) (string, error) {
+ entries, err := os.ReadDir(confDir)
+ if err != nil {
+ return "", fmt.Errorf("read CNI config dir %s: %w", confDir,
err)
+ }
+ var conflists, confs []string
+ for _, entry := range entries {
+ if entry.IsDir() || strings.HasSuffix(entry.Name(),
installBackupSuffix) {
+ continue
+ }
+ path := filepath.Join(confDir, entry.Name())
+ switch {
+ case strings.HasSuffix(entry.Name(), ".conflist"):
+ conflists = append(conflists, path)
+ case strings.HasSuffix(entry.Name(), ".conf"),
strings.HasSuffix(entry.Name(), ".json"):
+ confs = append(confs, path)
+ }
+ }
+ sort.Strings(conflists)
+ sort.Strings(confs)
+ for _, path := range append(conflists, confs...) {
+ if ok, err := isPrimaryCNIConfig(path); err != nil {
+ return "", err
+ } else if ok {
+ return path, nil
+ }
+ }
+ return "", fmt.Errorf("no primary CNI config found in %s", confDir)
+}
+
+func isPrimaryCNIConfig(path string) (bool, error) {
+ raw, err := os.ReadFile(path)
+ if err != nil {
+ return false, fmt.Errorf("read %s: %w", path, err)
+ }
+ var cfg map[string]any
+ if err := json.Unmarshal(raw, &cfg); err != nil {
+ return false, nil
+ }
+ if plugins, ok := cfg["plugins"].([]any); ok {
+ for _, item := range plugins {
+ plugin, ok := item.(map[string]any)
+ if !ok {
+ continue
+ }
+ if plugin["type"] == PluginType {
+ return true, nil
+ }
+ if plugin["type"] != "loopback" {
+ return true, nil
+ }
+ }
+ return false, nil
+ }
+ return cfg["type"] != PluginType && cfg["type"] != "loopback", nil
+}
+
+func patchConflist(path string, plugin map[string]any, backup bool) error {
+ raw, err := os.ReadFile(path)
+ if err != nil {
+ return fmt.Errorf("read %s: %w", path, err)
+ }
+ var cfg map[string]any
+ if err := json.Unmarshal(raw, &cfg); err != nil {
+ return fmt.Errorf("parse CNI conflist %s: %w", path, err)
+ }
+ plugins, _ := cfg["plugins"].([]any)
+ next := make([]any, 0, len(plugins)+1)
+ for _, item := range plugins {
+ existing, ok := item.(map[string]any)
+ if ok && existing["type"] == PluginType {
+ continue
+ }
+ next = append(next, item)
+ }
+ if plugin != nil {
+ next = append(next, plugin)
+ }
+ cfg["plugins"] = next
+ if backup {
+ if err := writeBackup(path, raw); err != nil {
+ return err
+ }
+ }
+ return writeJSONAtomic(path, cfg, 0o644)
+}
+
+func convertConfToConflist(path string, plugin map[string]any) error {
+ raw, err := os.ReadFile(path)
+ if err != nil {
+ return fmt.Errorf("read %s: %w", path, err)
+ }
+ var cfg map[string]any
+ if err := json.Unmarshal(raw, &cfg); err != nil {
+ return fmt.Errorf("parse CNI config %s: %w", path, err)
+ }
+ backupPath := path + installBackupSuffix
+ if _, err := os.Stat(backupPath); os.IsNotExist(err) {
+ if err := os.Rename(path, backupPath); err != nil {
+ return fmt.Errorf("backup %s: %w", path, err)
+ }
+ } else if err != nil {
+ return fmt.Errorf("stat %s: %w", backupPath, err)
+ }
+ conflist := map[string]any{
+ "cniVersion": stringValue(cfg["cniVersion"], defaultCNIVersion),
+ "name": stringValue(cfg["name"],
strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))),
+ "plugins": []any{cfg, plugin},
+ }
+ return writeJSONAtomic(strings.TrimSuffix(path,
filepath.Ext(path))+".conflist", conflist, 0o644)
+}
+
+func pluginConfig(opts InstallerOptions) map[string]any {
+ return map[string]any{
+ "type": PluginType,
+ "name": PluginType,
+ "kubernetes": map[string]any{"kubeconfig":
opts.KubeConfigPath},
+ "managedLabel": opts.ManagedLabel,
+ "managedLabelValue": opts.ManagedLabelValue,
+ "xserverPort": opts.XServerPort,
+ "stateDir": opts.StateDir,
+ "iptablesPath": opts.IPTablesPath,
+ "ipsetPath": opts.IPSetPath,
+ }
+}
+
+func writeBackup(path string, data []byte) error {
+ backup := path + installBackupSuffix
+ if _, err := os.Stat(backup); err == nil {
+ return nil
+ } else if !os.IsNotExist(err) {
+ return fmt.Errorf("stat %s: %w", backup, err)
+ }
+ return writeFileAtomic(backup, data, 0o644)
+}
+
+func writeJSONAtomic(path string, value any, mode os.FileMode) error {
+ data, err := json.MarshalIndent(value, "", " ")
+ if err != nil {
+ return err
+ }
+ data = append(data, '\n')
+ return writeFileAtomic(path, data, mode)
+}
+
+func copyFileAtomic(src, dst string, mode os.FileMode) error {
+ in, err := os.Open(src)
+ if err != nil {
+ return fmt.Errorf("open %s: %w", src, err)
+ }
+ defer in.Close()
+ if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
+ return fmt.Errorf("create %s: %w", filepath.Dir(dst), err)
+ }
+ tmp, err := os.CreateTemp(filepath.Dir(dst),
"."+filepath.Base(dst)+".tmp-*")
+ if err != nil {
+ return fmt.Errorf("create temp file for %s: %w", dst, err)
+ }
+ tmpName := tmp.Name()
+ defer os.Remove(tmpName)
+ if _, err := io.Copy(tmp, in); err != nil {
+ _ = tmp.Close()
+ return fmt.Errorf("copy %s to %s: %w", src, dst, err)
+ }
+ if err := tmp.Chmod(mode); err != nil {
+ _ = tmp.Close()
+ return fmt.Errorf("chmod %s: %w", tmpName, err)
+ }
+ if err := tmp.Close(); err != nil {
+ return fmt.Errorf("close %s: %w", tmpName, err)
+ }
+ if err := os.Rename(tmpName, dst); err != nil {
+ return fmt.Errorf("install %s: %w", dst, err)
+ }
+ return nil
+}
+
+func writeFileAtomic(path string, data []byte, mode os.FileMode) error {
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
+ return fmt.Errorf("create %s: %w", filepath.Dir(path), err)
+ }
+ tmp, err := os.CreateTemp(filepath.Dir(path),
"."+filepath.Base(path)+".tmp-*")
+ if err != nil {
+ return fmt.Errorf("create temp file for %s: %w", path, err)
+ }
+ tmpName := tmp.Name()
+ defer os.Remove(tmpName)
+ if _, err := tmp.Write(data); err != nil {
+ _ = tmp.Close()
+ return fmt.Errorf("write %s: %w", tmpName, err)
+ }
+ if err := tmp.Chmod(mode); err != nil {
+ _ = tmp.Close()
+ return fmt.Errorf("chmod %s: %w", tmpName, err)
+ }
+ if err := tmp.Close(); err != nil {
+ return fmt.Errorf("close %s: %w", tmpName, err)
+ }
+ if err := os.Rename(tmpName, path); err != nil {
+ return fmt.Errorf("write %s: %w", path, err)
+ }
+ return nil
+}
+
+func kubernetesServiceHost() string {
+ host := os.Getenv("KUBERNETES_SERVICE_HOST")
+ if host == "" {
+ return ""
+ }
+ port := os.Getenv("KUBERNETES_SERVICE_PORT_HTTPS")
+ if port == "" {
+ port = os.Getenv("KUBERNETES_SERVICE_PORT")
+ }
+ if port == "" {
+ port = "443"
+ }
+ return "https://" + host + ":" + port
+}
+
+func stringValue(value any, fallback string) string {
+ if s, ok := value.(string); ok && s != "" {
+ return s
+ }
+ return fallback
+}
diff --git a/pkg/cni/install_test.go b/pkg/cni/install_test.go
new file mode 100644
index 00000000..07a1f93e
--- /dev/null
+++ b/pkg/cni/install_test.go
@@ -0,0 +1,149 @@
+// 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.
+
+package cni
+
+import (
+ "context"
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "testing"
+)
+
+func TestInstallAddsPluginToConflist(t *testing.T) {
+ root := t.TempDir()
+ opts := installerTestOptions(t, root)
+ confPath := filepath.Join(opts.ConfDir, "10-primary.conflist")
+ writeTestFile(t, confPath, `{
+ "cniVersion": "1.0.0",
+ "name": "primary",
+ "plugins": [
+ {"type": "bridge", "name": "primary"}
+ ]
+}`)
+
+ if err := Install(context.Background(), opts); err != nil {
+ t.Fatalf("Install() error = %v", err)
+ }
+
+ if _, err := os.Stat(filepath.Join(opts.BinDir, PluginType)); err !=
nil {
+ t.Fatalf("plugin binary not installed: %v", err)
+ }
+ plugins := readPlugins(t, confPath)
+ if len(plugins) != 2 {
+ t.Fatalf("plugins length = %d, want 2", len(plugins))
+ }
+ if plugins[1]["type"] != PluginType {
+ t.Fatalf("last plugin type = %v, want %s", plugins[1]["type"],
PluginType)
+ }
+ kubernetes := plugins[1]["kubernetes"].(map[string]any)
+ if kubernetes["kubeconfig"] != opts.KubeConfigPath {
+ t.Fatalf("kubeconfig = %v, want %s", kubernetes["kubeconfig"],
opts.KubeConfigPath)
+ }
+ if plugins[1]["ipsetPath"] != defaultIPSetPath {
+ t.Fatalf("ipsetPath = %v, want %s", plugins[1]["ipsetPath"],
defaultIPSetPath)
+ }
+ if _, err := os.Stat(confPath + installBackupSuffix); err != nil {
+ t.Fatalf("backup not written: %v", err)
+ }
+}
+
+func TestInstallConvertsConfAndUninstallRestores(t *testing.T) {
+ root := t.TempDir()
+ opts := installerTestOptions(t, root)
+ confPath := filepath.Join(opts.ConfDir, "10-primary.conf")
+ writeTestFile(t, confPath,
`{"cniVersion":"1.0.0","name":"primary","type":"bridge"}`)
+
+ if err := Install(context.Background(), opts); err != nil {
+ t.Fatalf("Install() error = %v", err)
+ }
+ if _, err := os.Stat(confPath); !os.IsNotExist(err) {
+ t.Fatalf("primary .conf still exists: %v", err)
+ }
+ conflistPath := filepath.Join(opts.ConfDir, "10-primary.conflist")
+ plugins := readPlugins(t, conflistPath)
+ if len(plugins) != 2 || plugins[1]["type"] != PluginType {
+ t.Fatalf("converted plugins = %#v", plugins)
+ }
+
+ if err := Uninstall(opts); err != nil {
+ t.Fatalf("Uninstall() error = %v", err)
+ }
+ if _, err := os.Stat(confPath); err != nil {
+ t.Fatalf("primary .conf not restored: %v", err)
+ }
+ if _, err := os.Stat(conflistPath); !os.IsNotExist(err) {
+ t.Fatalf("converted conflist still exists: %v", err)
+ }
+ if _, err := os.Stat(filepath.Join(opts.BinDir, PluginType));
!os.IsNotExist(err) {
+ t.Fatalf("plugin binary still exists: %v", err)
+ }
+}
+
+func TestInstallRequiresPrimaryConfig(t *testing.T) {
+ root := t.TempDir()
+ opts := installerTestOptions(t, root)
+ if err := Install(context.Background(), opts); err == nil {
+ t.Fatal("Install() returned nil error")
+ }
+}
+
+func installerTestOptions(t *testing.T, root string) InstallerOptions {
+ t.Helper()
+ source := filepath.Join(root, "source-dubbo-cni")
+ writeTestFile(t, source, "binary")
+ token := filepath.Join(root, "service-account-token")
+ ca := filepath.Join(root, "service-account-ca.crt")
+ writeTestFile(t, token, "token")
+ writeTestFile(t, ca, "ca")
+ return InstallerOptions{
+ SourceBinary: source,
+ BinDir: filepath.Join(root, "bin"),
+ ConfDir: filepath.Join(root, "net.d"),
+ StateDir: filepath.Join(root, "state"),
+ KubeConfigPath: filepath.Join(root, "net.d",
"dubbo-cni-kubeconfig"),
+ TokenFile: filepath.Join(root, "state", "token"),
+ CAFile: filepath.Join(root, "state", "ca.crt"),
+ ServiceAccountTokenPath: token,
+ ServiceAccountCAPath: ca,
+ APIServer: "https://10.0.0.1:443",
+ }
+}
+
+func writeTestFile(t *testing.T, path, data string) {
+ t.Helper()
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
+ t.Fatalf("MkdirAll() error = %v", err)
+ }
+ if err := os.WriteFile(path, []byte(data), 0o644); err != nil {
+ t.Fatalf("WriteFile() error = %v", err)
+ }
+}
+
+func readPlugins(t *testing.T, path string) []map[string]any {
+ t.Helper()
+ raw, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatalf("ReadFile() error = %v", err)
+ }
+ var cfg struct {
+ Plugins []map[string]any `json:"plugins"`
+ }
+ if err := json.Unmarshal(raw, &cfg); err != nil {
+ t.Fatalf("Unmarshal() error = %v", err)
+ }
+ return cfg.Plugins
+}
diff --git a/pkg/cni/iptables.go b/pkg/cni/iptables.go
new file mode 100644
index 00000000..85f976f8
--- /dev/null
+++ b/pkg/cni/iptables.go
@@ -0,0 +1,170 @@
+// 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.
+
+package cni
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "net"
+ "os/exec"
+)
+
+const (
+ meshInboundChain = "DUBBO-XSERVER-INBOUND"
+ meshPodIPSet = "DUBBO-XSERVER-PODS"
+)
+
+type CommandRunner interface {
+ Run(ctx context.Context, name string, args ...string) ([]byte, error)
+}
+
+type execCommandRunner struct{}
+
+func (execCommandRunner) Run(ctx context.Context, name string, args ...string)
([]byte, error) {
+ cmd := exec.CommandContext(ctx, name, args...)
+ return cmd.CombinedOutput()
+}
+
+type IPTablesRuleManager struct {
+ path string
+ ipsetPath string
+ xserverPort int
+ dryRun bool
+ runner CommandRunner
+}
+
+func NewIPTablesRuleManager(conf NetConf) *IPTablesRuleManager {
+ return &IPTablesRuleManager{
+ path: conf.IPTablesPath,
+ ipsetPath: conf.IPSetPath,
+ xserverPort: conf.XServerPort,
+ dryRun: conf.DryRun,
+ runner: execCommandRunner{},
+ }
+}
+
+func NewIPTablesRuleManagerWithRunner(conf NetConf, runner CommandRunner)
*IPTablesRuleManager {
+ manager := NewIPTablesRuleManager(conf)
+ manager.runner = runner
+ return manager
+}
+
+func (m *IPTablesRuleManager) AddPodRules(ctx context.Context, podIP string)
error {
+ ip, err := normalizePodIP(podIP)
+ if err != nil {
+ return err
+ }
+ if err := m.ensureBase(ctx); err != nil {
+ return err
+ }
+ return m.runIPSet(ctx, "add", meshPodIPSet, ip, "-exist")
+}
+
+func (m *IPTablesRuleManager) DeletePodRules(ctx context.Context, podIP
string) error {
+ ip, err := normalizePodIP(podIP)
+ if err != nil {
+ return err
+ }
+ return m.runIPSet(ctx, "del", meshPodIPSet, ip, "-exist")
+}
+
+func (m *IPTablesRuleManager) ensureBase(ctx context.Context) error {
+ if err := m.runIPSet(ctx, "create", meshPodIPSet, "hash:ip", "-exist");
err != nil {
+ return err
+ }
+ if err := m.runIgnoreExists(ctx, "-w", "-t", "filter", "-N",
meshInboundChain); err != nil {
+ return err
+ }
+ for _, chain := range []string{"FORWARD", "OUTPUT"} {
+ if err := m.run(ctx, "-w", "-t", "filter", "-C", chain, "-j",
meshInboundChain); err == nil {
+ continue
+ }
+ if err := m.run(ctx, "-w", "-t", "filter", "-I", chain, "1",
"-j", meshInboundChain); err != nil {
+ return err
+ }
+ }
+ allowXServer := []string{"-m", "set", "--match-set", meshPodIPSet,
"dst", "-p", "tcp", "--dport", fmt.Sprint(m.xserverPort), "-j", "RETURN"}
+ rejectOtherTCP := []string{"-m", "set", "--match-set", meshPodIPSet,
"dst", "-p", "tcp", "-j", "REJECT"}
+ m.deleteRepeated(ctx, allowXServer...)
+ m.deleteRepeated(ctx, rejectOtherTCP...)
+ if err := m.appendRule(ctx, allowXServer...); err != nil {
+ return err
+ }
+ return m.appendRule(ctx, rejectOtherTCP...)
+}
+
+func (m *IPTablesRuleManager) deleteRepeated(ctx context.Context, args
...string) {
+ cmd := append([]string{"-w", "-t", "filter", "-D", meshInboundChain},
args...)
+ for i := 0; i < 20; i++ {
+ if err := m.run(ctx, cmd...); err != nil {
+ return
+ }
+ }
+}
+
+func (m *IPTablesRuleManager) appendRule(ctx context.Context, args ...string)
error {
+ cmd := append([]string{"-w", "-t", "filter", "-A", meshInboundChain},
args...)
+ return m.run(ctx, cmd...)
+}
+
+func (m *IPTablesRuleManager) runIgnoreExists(ctx context.Context, args
...string) error {
+ err := m.run(ctx, args...)
+ if err == nil {
+ return nil
+ }
+ if stringsContains(err.Error(), "Chain already exists") {
+ return nil
+ }
+ return err
+}
+
+func (m *IPTablesRuleManager) run(ctx context.Context, args ...string) error {
+ if m.dryRun {
+ return nil
+ }
+ out, err := m.runner.Run(ctx, m.path, args...)
+ if err != nil {
+ return fmt.Errorf("%s %v: %w: %s", m.path, args, err,
string(bytes.TrimSpace(out)))
+ }
+ return nil
+}
+
+func (m *IPTablesRuleManager) runIPSet(ctx context.Context, args ...string)
error {
+ if m.dryRun {
+ return nil
+ }
+ out, err := m.runner.Run(ctx, m.ipsetPath, args...)
+ if err != nil {
+ return fmt.Errorf("%s %v: %w: %s", m.ipsetPath, args, err,
string(bytes.TrimSpace(out)))
+ }
+ return nil
+}
+
+func normalizePodIP(podIP string) (string, error) {
+ ip := net.ParseIP(podIP)
+ if ip == nil {
+ return "", fmt.Errorf("invalid pod IP %q", podIP)
+ }
+ if ip.To4() == nil {
+ return "", fmt.Errorf("IPv6 pod IP %q is not supported yet",
podIP)
+ }
+ return ip.String(), nil
+}
+
+func stringsContains(s, substr string) bool {
+ return bytes.Contains([]byte(s), []byte(substr))
+}
diff --git a/pkg/cni/iptables_test.go b/pkg/cni/iptables_test.go
new file mode 100644
index 00000000..845104f8
--- /dev/null
+++ b/pkg/cni/iptables_test.go
@@ -0,0 +1,72 @@
+// 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.
+
+package cni
+
+import (
+ "context"
+ "strings"
+ "testing"
+)
+
+func TestIPTablesRuleManagerAddsXServerBoundaryRules(t *testing.T) {
+ runner := &recordingRunner{}
+ conf, err := ParseNetConf([]byte(`{"xserverPort":15080}`))
+ if err != nil {
+ t.Fatalf("ParseNetConf() failed: %v", err)
+ }
+ manager := NewIPTablesRuleManagerWithRunner(conf, runner)
+
+ if err := manager.AddPodRules(context.Background(), "10.244.0.12"); err
!= nil {
+ t.Fatalf("AddPodRules() failed: %v", err)
+ }
+
+ joined := strings.Join(runner.commands, "\n")
+ for _, want := range []string{
+ "ipset create DUBBO-XSERVER-PODS hash:ip -exist",
+ "-N DUBBO-XSERVER-INBOUND",
+ "-I FORWARD 1 -j DUBBO-XSERVER-INBOUND",
+ "-I OUTPUT 1 -j DUBBO-XSERVER-INBOUND",
+ "-A DUBBO-XSERVER-INBOUND -m set --match-set DUBBO-XSERVER-PODS
dst -p tcp --dport 15080 -j RETURN",
+ "-A DUBBO-XSERVER-INBOUND -m set --match-set DUBBO-XSERVER-PODS
dst -p tcp -j REJECT",
+ "ipset add DUBBO-XSERVER-PODS 10.244.0.12 -exist",
+ } {
+ if !strings.Contains(joined, want) {
+ t.Fatalf("commands missing %q:\n%s", want, joined)
+ }
+ }
+}
+
+type recordingRunner struct {
+ commands []string
+}
+
+func (r *recordingRunner) Run(_ context.Context, name string, args ...string)
([]byte, error) {
+ r.commands = append(r.commands, name+" "+strings.Join(args, " "))
+ for _, arg := range args {
+ if arg == "-C" || arg == "-D" {
+ return []byte("not found"), errCommandFailed
+ }
+ }
+ return nil, nil
+}
+
+var errCommandFailed = commandFailedError{}
+
+type commandFailedError struct{}
+
+func (commandFailedError) Error() string {
+ return "command failed"
+}
diff --git a/pkg/cni/kubernetes.go b/pkg/cni/kubernetes.go
new file mode 100644
index 00000000..422a58af
--- /dev/null
+++ b/pkg/cni/kubernetes.go
@@ -0,0 +1,72 @@
+// 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.
+
+package cni
+
+import (
+ "context"
+ "fmt"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/rest"
+ "k8s.io/client-go/tools/clientcmd"
+)
+
+type KubernetesPodInfoProvider struct {
+ client kubernetes.Interface
+}
+
+func NewKubernetesPodInfoProvider(kubeconfig string)
(*KubernetesPodInfoProvider, error) {
+ var (
+ cfg *rest.Config
+ err error
+ )
+ if kubeconfig != "" {
+ cfg, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
+ } else {
+ cfg, err = rest.InClusterConfig()
+ }
+ if err != nil {
+ return nil, fmt.Errorf("build Kubernetes client config: %w",
err)
+ }
+ client, err := kubernetes.NewForConfig(cfg)
+ if err != nil {
+ return nil, fmt.Errorf("create Kubernetes client: %w", err)
+ }
+ return &KubernetesPodInfoProvider{client: client}, nil
+}
+
+func (p *KubernetesPodInfoProvider) PodInfo(ctx context.Context, ref PodRef)
(PodInfo, error) {
+ pod, err := p.client.CoreV1().Pods(ref.Namespace).Get(ctx, ref.Name,
metav1.GetOptions{})
+ if err != nil {
+ return PodInfo{}, fmt.Errorf("get pod %s/%s: %w",
ref.Namespace, ref.Name, err)
+ }
+ ips := make([]string, 0, len(pod.Status.PodIPs))
+ for _, item := range pod.Status.PodIPs {
+ if item.IP != "" {
+ ips = append(ips, item.IP)
+ }
+ }
+ if pod.Status.PodIP != "" && len(ips) == 0 {
+ ips = append(ips, pod.Status.PodIP)
+ }
+ return PodInfo{
+ Namespace: pod.Namespace,
+ Name: pod.Name,
+ Labels: pod.Labels,
+ IPs: ips,
+ }, nil
+}
diff --git a/pkg/cni/plugin.go b/pkg/cni/plugin.go
new file mode 100644
index 00000000..99818923
--- /dev/null
+++ b/pkg/cni/plugin.go
@@ -0,0 +1,144 @@
+// 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.
+
+package cni
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+)
+
+type Plugin struct {
+ PodInfoProvider PodInfoProvider
+ RuleManager RuleManager
+ StateStore StateStore
+}
+
+type PodInfo struct {
+ Namespace string
+ Name string
+ Labels map[string]string
+ IPs []string
+}
+
+type PodInfoProvider interface {
+ PodInfo(ctx context.Context, ref PodRef) (PodInfo, error)
+}
+
+type RuleManager interface {
+ AddPodRules(ctx context.Context, podIP string) error
+ DeletePodRules(ctx context.Context, podIP string) error
+}
+
+type StateStore interface {
+ Write(PodState) error
+ Read(containerID string) (PodState, error)
+ Delete(containerID string) error
+}
+
+func (p Plugin) Run(ctx context.Context, env Env, conf NetConf) ([]byte,
error) {
+ switch env.Command {
+ case "VERSION":
+ return versionOutput(conf.CNIVersion), nil
+ case "ADD", "CHECK":
+ return p.addOrCheck(ctx, env, conf)
+ case "DEL":
+ return nil, p.del(ctx, env)
+ case "":
+ return nil, fmt.Errorf("CNI_COMMAND is required")
+ default:
+ return nil, fmt.Errorf("unsupported CNI_COMMAND %q",
env.Command)
+ }
+}
+
+func (p Plugin) addOrCheck(ctx context.Context, env Env, conf NetConf)
([]byte, error) {
+ out := ResultOutput(conf)
+ ref, ok := PodRefFromCNIArgs(env.Args)
+ if !ok {
+ return out, nil
+ }
+ if p.PodInfoProvider == nil {
+ return nil, fmt.Errorf("pod info provider is required")
+ }
+ pod, err := p.PodInfoProvider.PodInfo(ctx, ref)
+ if err != nil {
+ return nil, err
+ }
+ if pod.Labels[conf.ManagedLabel] != conf.ManagedLabelValue {
+ return out, nil
+ }
+ podIP := firstPodIP(conf, pod)
+ if podIP == "" {
+ return nil, fmt.Errorf("managed pod %s/%s has no IP in CNI
result or Kubernetes status", ref.Namespace, ref.Name)
+ }
+ if p.RuleManager == nil {
+ return nil, fmt.Errorf("rule manager is required")
+ }
+ if err := p.RuleManager.AddPodRules(ctx, podIP); err != nil {
+ return nil, err
+ }
+ if p.StateStore != nil && env.ContainerID != "" {
+ if err := p.StateStore.Write(PodState{
+ ContainerID: env.ContainerID,
+ Namespace: ref.Namespace,
+ Name: ref.Name,
+ IP: podIP,
+ }); err != nil {
+ return nil, err
+ }
+ }
+ return out, nil
+}
+
+func (p Plugin) del(ctx context.Context, env Env) error {
+ if p.StateStore == nil || env.ContainerID == "" {
+ return nil
+ }
+ state, err := p.StateStore.Read(env.ContainerID)
+ if err != nil {
+ if IsNotFound(err) {
+ return nil
+ }
+ return err
+ }
+ if p.RuleManager != nil && state.IP != "" {
+ if err := p.RuleManager.DeletePodRules(ctx, state.IP); err !=
nil {
+ return err
+ }
+ }
+ return p.StateStore.Delete(env.ContainerID)
+}
+
+func firstPodIP(conf NetConf, pod PodInfo) string {
+ if ips := PodIPsFromPrevResult(conf.PrevResult); len(ips) > 0 {
+ return ips[0]
+ }
+ if len(pod.IPs) > 0 {
+ return pod.IPs[0]
+ }
+ return ""
+}
+
+func versionOutput(cniVersion string) []byte {
+ if cniVersion == "" {
+ cniVersion = defaultCNIVersion
+ }
+ out, _ := json.Marshal(map[string]any{
+ "cniVersion": cniVersion,
+ "supportedVersions": []string{"0.3.1", "0.4.0", "1.0.0",
"1.1.0"},
+ })
+ return out
+}
diff --git a/pkg/cni/plugin_test.go b/pkg/cni/plugin_test.go
new file mode 100644
index 00000000..91904a33
--- /dev/null
+++ b/pkg/cni/plugin_test.go
@@ -0,0 +1,139 @@
+// 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.
+
+package cni
+
+import (
+ "context"
+ "encoding/json"
+ "testing"
+
+ "github.com/apache/dubbo-kubernetes/pkg/kube/inject"
+)
+
+func TestPluginAddInstallsRulesForManagedPod(t *testing.T) {
+ conf := testConf(t)
+ conf.StateDir = t.TempDir()
+ rules := &fakeRuleManager{}
+ plugin := Plugin{
+ PodInfoProvider: fakePodInfoProvider{pod: PodInfo{Labels:
map[string]string{
+ inject.ProxylessManagedLabel:
inject.ProxylessManagedLabelValue,
+ }}},
+ RuleManager: rules,
+ StateStore: NewFileStateStore(conf.StateDirectory()),
+ }
+
+ out, err := plugin.Run(context.Background(), Env{
+ Command: "ADD",
+ ContainerID: "container-a",
+ Args: "K8S_POD_NAMESPACE=app;K8S_POD_NAME=nginx",
+ }, conf)
+ if err != nil {
+ t.Fatalf("Run(ADD) failed: %v", err)
+ }
+ if len(out) == 0 {
+ t.Fatal("Run(ADD) returned empty result")
+ }
+ if len(rules.added) != 1 || rules.added[0] != "10.244.0.12" {
+ t.Fatalf("added rules = %v, want [10.244.0.12]", rules.added)
+ }
+ state, err := plugin.StateStore.Read("container-a")
+ if err != nil {
+ t.Fatalf("state read failed: %v", err)
+ }
+ if state.Namespace != "app" || state.Name != "nginx" || state.IP !=
"10.244.0.12" {
+ t.Fatalf("state = %#v, want app/nginx/10.244.0.12", state)
+ }
+}
+
+func TestPluginAddSkipsUnmanagedPod(t *testing.T) {
+ conf := testConf(t)
+ rules := &fakeRuleManager{}
+ plugin := Plugin{
+ PodInfoProvider: fakePodInfoProvider{pod: PodInfo{Labels:
map[string]string{"app": "nginx"}}},
+ RuleManager: rules,
+ StateStore: NewFileStateStore(t.TempDir()),
+ }
+
+ if _, err := plugin.Run(context.Background(), Env{
+ Command: "ADD",
+ ContainerID: "container-a",
+ Args: "K8S_POD_NAMESPACE=app;K8S_POD_NAME=nginx",
+ }, conf); err != nil {
+ t.Fatalf("Run(ADD) failed: %v", err)
+ }
+ if len(rules.added) != 0 {
+ t.Fatalf("added rules = %v, want none", rules.added)
+ }
+}
+
+func TestPluginDeleteCleansStoredRules(t *testing.T) {
+ store := NewFileStateStore(t.TempDir())
+ if err := store.Write(PodState{ContainerID: "container-a", Namespace:
"app", Name: "nginx", IP: "10.244.0.12"}); err != nil {
+ t.Fatalf("state write failed: %v", err)
+ }
+ rules := &fakeRuleManager{}
+ plugin := Plugin{RuleManager: rules, StateStore: store}
+
+ if _, err := plugin.Run(context.Background(), Env{Command: "DEL",
ContainerID: "container-a"}, NetConf{}); err != nil {
+ t.Fatalf("Run(DEL) failed: %v", err)
+ }
+ if len(rules.deleted) != 1 || rules.deleted[0] != "10.244.0.12" {
+ t.Fatalf("deleted rules = %v, want [10.244.0.12]",
rules.deleted)
+ }
+ if _, err := store.Read("container-a"); !IsNotFound(err) {
+ t.Fatalf("state read err = %v, want not found", err)
+ }
+}
+
+func testConf(t *testing.T) NetConf {
+ t.Helper()
+ prev, _ := json.Marshal(map[string]any{
+ "cniVersion": "1.0.0",
+ "ips": []map[string]string{
+ {"address": "10.244.0.12/24"},
+ },
+ })
+ conf, err := ParseNetConf([]byte(`{"cniVersion":"1.0.0"}`))
+ if err != nil {
+ t.Fatalf("ParseNetConf() failed: %v", err)
+ }
+ conf.PrevResult = prev
+ return conf
+}
+
+type fakePodInfoProvider struct {
+ pod PodInfo
+ err error
+}
+
+func (f fakePodInfoProvider) PodInfo(context.Context, PodRef) (PodInfo, error)
{
+ return f.pod, f.err
+}
+
+type fakeRuleManager struct {
+ added []string
+ deleted []string
+}
+
+func (f *fakeRuleManager) AddPodRules(_ context.Context, podIP string) error {
+ f.added = append(f.added, podIP)
+ return nil
+}
+
+func (f *fakeRuleManager) DeletePodRules(_ context.Context, podIP string)
error {
+ f.deleted = append(f.deleted, podIP)
+ return nil
+}
diff --git a/pkg/cni/state.go b/pkg/cni/state.go
new file mode 100644
index 00000000..169566d0
--- /dev/null
+++ b/pkg/cni/state.go
@@ -0,0 +1,99 @@
+// 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.
+
+package cni
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+type PodState struct {
+ ContainerID string `json:"containerID"`
+ Namespace string `json:"namespace"`
+ Name string `json:"name"`
+ IP string `json:"ip"`
+}
+
+type FileStateStore struct {
+ dir string
+}
+
+func NewFileStateStore(dir string) *FileStateStore {
+ return &FileStateStore{dir: dir}
+}
+
+func (s *FileStateStore) Write(state PodState) error {
+ if state.ContainerID == "" {
+ return fmt.Errorf("container ID is required")
+ }
+ if err := os.MkdirAll(s.dir, 0o700); err != nil {
+ return err
+ }
+ data, err := json.Marshal(state)
+ if err != nil {
+ return err
+ }
+ return os.WriteFile(s.path(state.ContainerID), data, 0o600)
+}
+
+func (s *FileStateStore) Read(containerID string) (PodState, error) {
+ data, err := os.ReadFile(s.path(containerID))
+ if err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ return PodState{}, notFoundError{err}
+ }
+ return PodState{}, err
+ }
+ state := PodState{}
+ if err := json.Unmarshal(data, &state); err != nil {
+ return PodState{}, err
+ }
+ return state, nil
+}
+
+func (s *FileStateStore) Delete(containerID string) error {
+ if err := os.Remove(s.path(containerID)); err != nil && !errors.Is(err,
os.ErrNotExist) {
+ return err
+ }
+ return nil
+}
+
+func (s *FileStateStore) path(containerID string) string {
+ sum := sha256.Sum256([]byte(containerID))
+ return filepath.Join(s.dir, hex.EncodeToString(sum[:])+".json")
+}
+
+type notFoundError struct {
+ err error
+}
+
+func (e notFoundError) Error() string {
+ return e.err.Error()
+}
+
+func (e notFoundError) Unwrap() error {
+ return e.err
+}
+
+func IsNotFound(err error) bool {
+ var nf notFoundError
+ return errors.As(err, &nf)
+}
diff --git a/pkg/kube/inject/proxyless.go b/pkg/kube/inject/proxyless.go
index c55cdb7a..3c53c77a 100644
--- a/pkg/kube/inject/proxyless.go
+++ b/pkg/kube/inject/proxyless.go
@@ -37,6 +37,8 @@ const (
ProxylessGRPCConfigPath = ProxylessXDSMountPath + "/" +
ProxylessGRPCConfigFileName
ProxylessXServerContainerName = "dubbo-xserver"
ProxylessXServerPort = 15080
+ ProxylessManagedLabel = "proxyless.dubbo.apache.org/managed"
+ ProxylessManagedLabelValue = "true"
)
var ProxylessInjectTemplatesAnnoName =
annotation.OrgApacheDubboInjectTemplates.Name
diff --git a/pkg/kube/inject/proxyless_test.go
b/pkg/kube/inject/proxyless_test.go
index 4fb61bc7..4cee4167 100644
--- a/pkg/kube/inject/proxyless_test.go
+++ b/pkg/kube/inject/proxyless_test.go
@@ -525,6 +525,14 @@ func TestEnsureProxylessGRPCTemplateAnnotation(t
*testing.T) {
}
}
+func TestEnsureProxylessManagedLabel(t *testing.T) {
+ pod := &corev1.Pod{}
+ ensureProxylessManagedLabel(pod)
+ if got := pod.Labels[ProxylessManagedLabel]; got !=
ProxylessManagedLabelValue {
+ t.Fatalf("managed label = %q, want %q", got,
ProxylessManagedLabelValue)
+ }
+}
+
func TestProxylessGRPCSecretNameFitsKubernetesLengthLimit(t *testing.T) {
name :=
ProxylessGRPCSecretName("grpc-provider-012345678901234567890123456789012345678901234567890123")
if len(name) > 63 {
diff --git a/pkg/kube/inject/webhook.go b/pkg/kube/inject/webhook.go
index cdf183dc..153ac4a0 100644
--- a/pkg/kube/inject/webhook.go
+++ b/pkg/kube/inject/webhook.go
@@ -442,6 +442,7 @@ func postProcessPod(pod *corev1.Pod, injectedPod
corev1.Pod, req InjectionParame
if shouldInjectProxylessGRPC(req) {
// Add proxyless gRPC env and shared bootstrap/cert volume to
application containers.
ensureProxylessGRPCTemplateAnnotation(pod)
+ ensureProxylessManagedLabel(pod)
if err := addApplicationContainerConfig(pod, req); err != nil {
return err
}
@@ -654,6 +655,13 @@ func ensureProxylessGRPCTemplateAnnotation(pod
*corev1.Pod) {
pod.Annotations[ProxylessInjectTemplatesAnnoName] = templates + "," +
ProxylessGRPCTemplateName
}
+func ensureProxylessManagedLabel(pod *corev1.Pod) {
+ if pod.Labels == nil {
+ pod.Labels = map[string]string{}
+ }
+ pod.Labels[ProxylessManagedLabel] = ProxylessManagedLabelValue
+}
+
func ensureEnvVar(envs []corev1.EnvVar, desired corev1.EnvVar) []corev1.EnvVar
{
for _, env := range envs {
if env.Name == desired.Name {
diff --git a/release/downloadDubboCandidate.sh
b/release/downloadDubboCandidate.sh
index 68cf9be8..40c75fa6 100644
--- a/release/downloadDubboCandidate.sh
+++ b/release/downloadDubboCandidate.sh
@@ -4,7 +4,7 @@ set -e
# Determines the operating system.
OS="${TARGET_OS:-$(uname)}"
if [ "${OS}" = "Darwin" ] ; then
- OSEXT="osx"
+ OSEXT="darwin"
else
OSEXT="linux"
fi
@@ -12,18 +12,34 @@ fi
# Package type, default to dubbo
PACKAGE_TYPE="${PACKAGE_TYPE:-dubbo}"
+latest_dubbo_version_from_api() {
+ curl -fsSL \
+ -H "Accept: application/vnd.github+json" \
+ https://api.github.com/repos/apache/dubbo-kubernetes/releases 2>/dev/null
| \
+ sed -n 's/.*"tag_name":[[:space:]]*"\([^"]*\)".*/\1/p' | \
+ grep -viE '(alpha|beta|rc)' | \
+ head -1
+}
+
+latest_dubbo_version_from_atom() {
+ curl -fsSL https://github.com/apache/dubbo-kubernetes/releases.atom
2>/dev/null | \
+ sed -n 's/.*<title>\([^<][^<]*\)<\/title>.*/\1/p' | \
+ grep -v '^Release notes from ' | \
+ grep -viE '(alpha|beta|rc)' | \
+ head -1
+}
+
# Determine the latest Dubbo version by version number ignoring alpha, beta,
and rc versions.
if [ "${DUBBO_VERSION}" = "" ] ; then
- DUBBO_VERSION="$(curl -s
https://api.github.com/repos/apache/dubbo-kubernetes/releases | \
- grep '"tag_name":' | \
- grep -vE '(alpha|beta|rc)' | \
- head -1 | \
- sed -E 's/.*"([^"]+)".*/\1/')"
+ DUBBO_VERSION="$(latest_dubbo_version_from_api)"
+ if [ "${DUBBO_VERSION}" = "" ] ; then
+ DUBBO_VERSION="$(latest_dubbo_version_from_atom)"
+ fi
DUBBO_VERSION="${DUBBO_VERSION##*/}"
fi
if [ "${DUBBO_VERSION}" = "" ] ; then
- printf "Unable to get latest Dubbo version.\n"
+ printf "Unable to get latest Dubbo version. Please specify DUBBO_VERSION.\n"
exit 1;
fi
@@ -91,4 +107,4 @@ printf "\nDubbo %s download complete!\n" "$DUBBO_VERSION"
printf "\n"
BINDIR="$(cd "$NAME/bin" && pwd)"
printf "add the %s directory to your environment path variable with:\n"
"$BINDIR"
-printf "\t export PATH=\"\$PATH:%s\"\n" "$BINDIR"
\ No newline at end of file
+printf "\t export PATH=\"\$PATH:%s\"\n" "$BINDIR"
diff --git a/samples/app/deployment.yaml b/samples/app/deployment.yaml
index 1c01a845..778f8e0e 100644
--- a/samples/app/deployment.yaml
+++ b/samples/app/deployment.yaml
@@ -37,22 +37,6 @@ spec:
targetPort: 80
protocol: TCP
---
-apiVersion: networking.k8s.io/v1
-kind: NetworkPolicy
-metadata:
- name: nginx-proxyless-only
- namespace: app
-spec:
- podSelector:
- matchLabels:
- app: nginx
- policyTypes:
- - Ingress
- ingress:
- - ports:
- - protocol: TCP
- port: 15080
----
apiVersion: v1
kind: ConfigMap
metadata: