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 6c3e8a44 Update dubboctl commands (#985)
6c3e8a44 is described below

commit 6c3e8a446547f204920fc7c11b7a6f2ab4e4ec61
Author: mfordjody <[email protected]>
AuthorDate: Mon Aug 3 20:54:13 2026 +0800

    Update dubboctl commands (#985)
---
 .asf.yaml                         |  28 +++-
 .github/workflows/ci.yml          |   6 +-
 .github/workflows/commands.yml    |  12 +-
 .github/workflows/labels.yml      |  40 -----
 .github/workflows/review-gate.yml |  10 +-
 dubboctl/cmd/admin.go             | 152 -----------------
 dubboctl/cmd/admin_test.go        |  71 --------
 dubboctl/cmd/dashboard.go         | 333 --------------------------------------
 dubboctl/cmd/dashboard_test.go    | 143 ----------------
 dubboctl/cmd/root.go              |   2 -
 10 files changed, 46 insertions(+), 751 deletions(-)

diff --git a/.asf.yaml b/.asf.yaml
index 26b9a477..5f17302e 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -42,9 +42,29 @@ github:
       required_status_checks:
         strict: true
         checks:
-          # Pin both gates to the GitHub Actions App so a personal token cannot
-          # forge either required result.
-          - context: CI Required
+          # Require the concrete CI jobs directly. A separate fan-in job needs
+          # another scarce ASF runner after every real check has already 
passed.
+          - context: Lint
             app_id: 15368
+          - context: Check Repo Hygiene
+            app_id: 15368
+          - context: Unit Tests
+            app_id: 15368
+          - context: Performance Scale Smoke
+            app_id: 15368
+          - context: Build (linux/amd64)
+            app_id: 15368
+          - context: Build (linux/arm64)
+            app_id: 15368
+          - context: Build (darwin/amd64)
+            app_id: 15368
+          - context: Build (darwin/arm64)
+            app_id: 15368
+          - context: Helm Charts
+            app_id: 15368
+          - context: E2E Smoke (kind)
+            app_id: 15368
+          # Pin every gate to the GitHub Actions App so a personal token cannot
+          # forge a required result.
           - context: Maintainer Approval Gate
-            app_id: 15368
\ No newline at end of file
+            app_id: 15368
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c5539223..57d73e96 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -213,9 +213,11 @@ jobs:
 
   required:
     name: CI Required
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-slim
     timeout-minutes: 5
-    if: ${{ always() }}
+    # Evaluate after all dependencies settle, but do not keep a superseded
+    # workflow alive and blocking the next run in this PR's concurrency group.
+    if: ${{ always() && !cancelled() }}
     needs:
       - lint
       - check
diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml
index 19f092ba..5310e0a4 100644
--- a/.github/workflows/commands.yml
+++ b/.github/workflows/commands.yml
@@ -52,11 +52,19 @@ permissions:
 jobs:
   command:
     name: Handle Command
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-slim
     timeout-minutes: 10
     if: |
       github.event_name == 'issue_comment' &&
-      github.repository == 'apache/dubbo-kubernetes'
+      github.repository == 'apache/dubbo-kubernetes' &&
+      (
+        contains(github.event.comment.body, '/assign') ||
+        contains(github.event.comment.body, '/unassign') ||
+        contains(github.event.comment.body, '/lgtm') ||
+        contains(github.event.comment.body, '/close') ||
+        contains(github.event.comment.body, '/reopen') ||
+        contains(github.event.comment.body, '/retest')
+      )
     env:
       BOT_APP_ID: ${{ secrets.BOT_APP_ID }}
     steps:
diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml
deleted file mode 100644
index 9de471b0..00000000
--- a/.github/workflows/labels.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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.
-
-name: Labels
-
-on:
-  pull_request_target:
-    types:
-      - opened
-      - reopened
-      - synchronize
-      - ready_for_review
-
-permissions:
-  contents: read
-  pull-requests: write
-
-jobs:
-  changed-files:
-    name: Apply PR Labels
-    runs-on: ubuntu-latest
-    timeout-minutes: 5
-    if: github.repository == 'apache/dubbo-kubernetes'
-    steps:
-      - name: Apply labels from changed paths
-        uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
-        with:
-          repo-token: ${{ github.token }}
diff --git a/.github/workflows/review-gate.yml 
b/.github/workflows/review-gate.yml
index 9a0b5741..3407906c 100644
--- a/.github/workflows/review-gate.yml
+++ b/.github/workflows/review-gate.yml
@@ -35,16 +35,22 @@ on:
 permissions:
   contents: read
   issues: write
-  pull-requests: read
+  pull-requests: write
   statuses: write
 
 jobs:
   approval:
     name: Publish Maintainer Approval
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-slim
     timeout-minutes: 5
     if: github.repository == 'apache/dubbo-kubernetes'
     steps:
+      - name: Apply PR labels
+        if: github.event_name == 'pull_request_target'
+        uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0
+        with:
+          repo-token: ${{ github.token }}
+
       - name: Publish approval status
         uses: actions/github-script@v7
         with:
diff --git a/dubboctl/cmd/admin.go b/dubboctl/cmd/admin.go
deleted file mode 100644
index 04bf509f..00000000
--- a/dubboctl/cmd/admin.go
+++ /dev/null
@@ -1,152 +0,0 @@
-//
-// 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 cmd
-
-import (
-       "context"
-       "fmt"
-       "io"
-       "sort"
-
-       "github.com/apache/dubbo-kubernetes/dubboctl/pkg/cli"
-       "github.com/spf13/cobra"
-       corev1 "k8s.io/api/core/v1"
-       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-       klabels "k8s.io/apimachinery/pkg/labels"
-       "k8s.io/client-go/kubernetes"
-)
-
-type adminLogArgs struct {
-       namespace  string
-       deployment string
-       container  string
-       tail       int64
-}
-
-func AdminCmd(ctx cli.Context) *cobra.Command {
-       command := &cobra.Command{
-               Use:   "admin",
-               Short: "Access dubbod admin information",
-       }
-       command.AddCommand(adminLogCmd(ctx))
-       return command
-}
-
-func adminLogCmd(ctx cli.Context) *cobra.Command {
-       args := &adminLogArgs{
-               namespace:  ctx.Namespace(),
-               deployment: "dubbod",
-               container:  "execute",
-               tail:       200,
-       }
-
-       command := &cobra.Command{
-               Use:   "log",
-               Short: "Print dubbod logs",
-               Args:  cobra.NoArgs,
-               RunE: func(cmd *cobra.Command, _ []string) error {
-                       client, err := ctx.CLIClient()
-                       if err != nil {
-                               return err
-                       }
-                       return printDeploymentLogs(cmd.Context(), 
client.Kube(), *args, cmd.OutOrStdout())
-               },
-       }
-       flags := command.Flags()
-       flags.StringVarP(&args.namespace, "namespace", "n", args.namespace, 
"Namespace of the dubbod deployment")
-       flags.StringVar(&args.deployment, "deployment", args.deployment, 
"Dubbod deployment name")
-       flags.StringVar(&args.container, "container", args.container, 
"Preferred container name")
-       flags.Int64Var(&args.tail, "tail", args.tail, "Number of recent log 
lines to print")
-       return command
-}
-
-func printDeploymentLogs(ctx context.Context, client kubernetes.Interface, 
args adminLogArgs, writer io.Writer) error {
-       pods, err := deploymentPods(ctx, client, args.namespace, 
args.deployment)
-       if err != nil {
-               return err
-       }
-       if len(pods) == 0 {
-               return fmt.Errorf("no pods found for deployment %s/%s", 
args.namespace, args.deployment)
-       }
-
-       for _, pod := range pods {
-               for _, container := range logContainers(pod, args.container) {
-                       if _, err := fmt.Fprintf(writer, "==> %s/%s:%s <==\n", 
pod.Namespace, pod.Name, container); err != nil {
-                               return err
-                       }
-                       raw, err := 
client.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &corev1.PodLogOptions{
-                               Container:  container,
-                               TailLines:  &args.tail,
-                               Timestamps: true,
-                       }).DoRaw(ctx)
-                       if err != nil {
-                               return fmt.Errorf("get logs %s/%s container %s: 
%w", pod.Namespace, pod.Name, container, err)
-                       }
-                       if _, err := writer.Write(raw); err != nil {
-                               return err
-                       }
-                       if len(raw) == 0 || raw[len(raw)-1] != '\n' {
-                               if _, err := fmt.Fprintln(writer); err != nil {
-                                       return err
-                               }
-                       }
-               }
-       }
-       return nil
-}
-
-func deploymentPods(ctx context.Context, client kubernetes.Interface, 
namespace, name string) ([]corev1.Pod, error) {
-       deployment, err := client.AppsV1().Deployments(namespace).Get(ctx, 
name, metav1.GetOptions{})
-       if err != nil {
-               return nil, fmt.Errorf("get deployment %s/%s: %w", namespace, 
name, err)
-       }
-       if deployment.Spec.Selector == nil {
-               return nil, fmt.Errorf("deployment %s/%s has no selector", 
namespace, name)
-       }
-       selector, err := 
metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
-       if err != nil {
-               return nil, fmt.Errorf("build pod selector for deployment 
%s/%s: %w", namespace, name, err)
-       }
-       if selector.Empty() {
-               selector = 
klabels.SelectorFromSet(deployment.Spec.Template.Labels)
-       }
-       pods, err := client.CoreV1().Pods(namespace).List(ctx, 
metav1.ListOptions{
-               LabelSelector: selector.String(),
-       })
-       if err != nil {
-               return nil, fmt.Errorf("list pods for deployment %s/%s: %w", 
namespace, name, err)
-       }
-       sort.SliceStable(pods.Items, func(i, j int) bool {
-               return pods.Items[i].Name < pods.Items[j].Name
-       })
-       return pods.Items, nil
-}
-
-func logContainers(pod corev1.Pod, preferred string) []string {
-       if preferred != "" {
-               for _, container := range pod.Spec.Containers {
-                       if container.Name == preferred {
-                               return []string{preferred}
-                       }
-               }
-       }
-       out := make([]string, 0, len(pod.Spec.Containers))
-       for _, container := range pod.Spec.Containers {
-               out = append(out, container.Name)
-       }
-       return out
-}
diff --git a/dubboctl/cmd/admin_test.go b/dubboctl/cmd/admin_test.go
deleted file mode 100644
index 11307f04..00000000
--- a/dubboctl/cmd/admin_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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 cmd
-
-import (
-       "context"
-       "reflect"
-       "testing"
-
-       appsv1 "k8s.io/api/apps/v1"
-       corev1 "k8s.io/api/core/v1"
-       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-       "k8s.io/client-go/kubernetes/fake"
-)
-
-func TestDeploymentPodsUsesDeploymentSelector(t *testing.T) {
-       client := fake.NewSimpleClientset(
-               &appsv1.Deployment{
-                       ObjectMeta: metav1.ObjectMeta{Name: "dubbod", 
Namespace: "dubbo-system"},
-                       Spec: appsv1.DeploymentSpec{
-                               Selector: &metav1.LabelSelector{MatchLabels: 
map[string]string{"app": "dubbod"}},
-                               Template: corev1.PodTemplateSpec{
-                                       ObjectMeta: metav1.ObjectMeta{Labels: 
map[string]string{"app": "dubbod"}},
-                               },
-                       },
-               },
-               &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "dubbod-b", 
Namespace: "dubbo-system", Labels: map[string]string{"app": "dubbod"}}},
-               &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "dubbod-a", 
Namespace: "dubbo-system", Labels: map[string]string{"app": "dubbod"}}},
-               &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "other", 
Namespace: "dubbo-system", Labels: map[string]string{"app": "other"}}},
-       )
-
-       pods, err := deploymentPods(context.Background(), client, 
"dubbo-system", "dubbod")
-       if err != nil {
-               t.Fatalf("deploymentPods() returned error: %v", err)
-       }
-       got := []string{}
-       for _, pod := range pods {
-               got = append(got, pod.Name)
-       }
-       want := []string{"dubbod-a", "dubbod-b"}
-       if !reflect.DeepEqual(got, want) {
-               t.Fatalf("deploymentPods() = %v, want %v", got, want)
-       }
-}
-
-func TestLogContainersPrefersRequestedContainer(t *testing.T) {
-       pod := corev1.Pod{
-               Spec: corev1.PodSpec{
-                       Containers: []corev1.Container{{Name: "app"}, {Name: 
"execute"}},
-               },
-       }
-       if got := logContainers(pod, "execute"); !reflect.DeepEqual(got, 
[]string{"execute"}) {
-               t.Fatalf("logContainers() = %v, want [execute]", got)
-       }
-       if got := logContainers(pod, "missing"); !reflect.DeepEqual(got, 
[]string{"app", "execute"}) {
-               t.Fatalf("logContainers() fallback = %v, want all containers", 
got)
-       }
-}
diff --git a/dubboctl/cmd/dashboard.go b/dubboctl/cmd/dashboard.go
deleted file mode 100644
index d56e5205..00000000
--- a/dubboctl/cmd/dashboard.go
+++ /dev/null
@@ -1,333 +0,0 @@
-//
-// 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 cmd
-
-import (
-       "bufio"
-       "bytes"
-       "context"
-       "encoding/json"
-       "fmt"
-       "io"
-       "os"
-       "path/filepath"
-       "time"
-
-       "github.com/apache/dubbo-kubernetes/dubboctl/pkg/cli"
-       "github.com/apache/dubbo-kubernetes/pkg/kube"
-       "github.com/spf13/cobra"
-       appsv1 "k8s.io/api/apps/v1"
-       apierrors "k8s.io/apimachinery/pkg/api/errors"
-       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-       "k8s.io/apimachinery/pkg/types"
-       "k8s.io/apimachinery/pkg/util/wait"
-       utilyaml "k8s.io/apimachinery/pkg/util/yaml"
-       "k8s.io/client-go/kubernetes"
-       "sigs.k8s.io/yaml"
-)
-
-const dashboardNamespace = "dubbo-system"
-
-type dashboardArgs struct {
-       manifests string
-       wait      time.Duration
-}
-
-type appliedObject struct {
-       Kind      string
-       Name      string
-       Namespace string
-}
-
-func DashboardCmd(ctx cli.Context) *cobra.Command {
-       args := &dashboardArgs{
-               manifests: "samples/addons",
-               wait:      2 * time.Minute,
-       }
-
-       command := &cobra.Command{
-               Use:   "dashboard",
-               Short: "Start the sample Prometheus and Grafana dashboard",
-               Args:  cobra.NoArgs,
-               RunE: func(cmd *cobra.Command, _ []string) error {
-                       client, err := ctx.CLIClient()
-                       if err != nil {
-                               return err
-                       }
-
-                       files, err := dashboardManifestFiles(args.manifests)
-                       if err != nil {
-                               return err
-                       }
-
-                       var applied []appliedObject
-                       for _, file := range files {
-                               objects, err := 
applyManifestFile(cmd.Context(), client, file)
-                               if err != nil {
-                                       return err
-                               }
-                               applied = append(applied, objects...)
-                       }
-                       if err := printAppliedDashboard(cmd.OutOrStdout(), 
applied); err != nil {
-                               return err
-                       }
-
-                       if args.wait > 0 {
-                               if err := waitForDashboard(cmd.Context(), 
client.Kube(), dashboardNamespace, dashboardWaitDeploymentNames(files), 
args.wait); err != nil {
-                                       return err
-                               }
-                               if _, err := fmt.Fprintln(cmd.OutOrStdout(), 
"dashboard ready"); err != nil {
-                                       return err
-                               }
-                       }
-
-                       _, err = fmt.Fprintf(cmd.OutOrStdout(), "prometheus: 
kubectl -n %s port-forward svc/prometheus 9090:9090\ngrafana: kubectl -n %s 
port-forward svc/grafana 3000:3000\n", dashboardNamespace, dashboardNamespace)
-                       if err != nil {
-                               return err
-                       }
-                       if dashboardHasTracing(files) {
-                               _, err = fmt.Fprintf(cmd.OutOrStdout(), 
"tracing: kubectl -n %s port-forward svc/tracing 16686:16686\n", 
dashboardNamespace)
-                               if err != nil {
-                                       return err
-                               }
-                       }
-                       if dashboardHasOpenTelemetry(files) {
-                               _, err = fmt.Fprintf(cmd.OutOrStdout(), 
"opentelemetry: kubectl -n %s port-forward svc/opentelemetry-collector 
4317:4317\n", dashboardNamespace)
-                       }
-                       return err
-               },
-       }
-       command.Flags().StringVar(&args.manifests, "manifests", args.manifests, 
"Dashboard manifest file or samples/addons directory")
-       command.Flags().DurationVar(&args.wait, "wait", args.wait, "Maximum 
time to wait for observability deployments; 0 disables waiting")
-
-       command.AddCommand(dashboardTargetCmd(ctx, "grafana", "Open the Grafana 
dashboards", "grafana", 3000, 3000))
-       command.AddCommand(dashboardTargetCmd(ctx, "prometheus", "Open the 
Prometheus UI", "prometheus", 9090, 9090))
-       command.AddCommand(dashboardTargetCmd(ctx, "tracing", "Open the 
distributed tracing UI", "tracing", 16686, 16686))
-       command.AddCommand(dashboardTargetCmd(ctx, "otel", "Forward the 
OpenTelemetry collector OTLP gRPC port", "opentelemetry-collector", 4317, 4317))
-       return command
-}
-
-// dashboardTargetCmd builds a subcommand that port-forwards to one
-// observability addon. Installation is handled by the operator (for example
-// `dubboctl install --set profile=demo`); these subcommands only provide 
access.
-func dashboardTargetCmd(ctx cli.Context, name, short, serviceName string, 
localPort, podPort int) *cobra.Command {
-       port := localPort
-       cmd := &cobra.Command{
-               Use:   name,
-               Short: short,
-               Args:  cobra.NoArgs,
-               RunE: func(cmd *cobra.Command, _ []string) error {
-                       client, err := ctx.CLIClient()
-                       if err != nil {
-                               return err
-                       }
-                       return forwardToService(cmd.Context(), client, 
cmd.OutOrStdout(), dashboardNamespace, serviceName, port, podPort)
-               },
-       }
-       cmd.Flags().IntVarP(&port, "port", "p", localPort, "Local port to 
forward from")
-       return cmd
-}
-
-func dashboardManifestFiles(path string) ([]string, error) {
-       info, err := os.Stat(path)
-       if err != nil {
-               return nil, err
-       }
-       if !info.IsDir() {
-               return []string{path}, nil
-       }
-
-       prometheus := filepath.Join(path, "prometheus.yaml")
-       if _, err := os.Stat(prometheus); err != nil {
-               prometheus = filepath.Join(path, "metrics.yaml")
-               if _, err := os.Stat(prometheus); err != nil {
-                       return nil, fmt.Errorf("dashboard prometheus manifest 
not found in %s", path)
-               }
-       }
-
-       grafana := filepath.Join(path, "grafana.yaml")
-       if _, err := os.Stat(grafana); err != nil {
-               return nil, fmt.Errorf("dashboard grafana manifest not found in 
%s", path)
-       }
-       files := []string{prometheus, grafana}
-       tracing := filepath.Join(path, "tracing.yaml")
-       if _, err := os.Stat(tracing); err == nil {
-               files = append(files, tracing)
-       }
-       opentelemetry := filepath.Join(path, "opentelemetry.yaml")
-       if _, err := os.Stat(opentelemetry); err == nil {
-               files = append(files, opentelemetry)
-       }
-       return files, nil
-}
-
-func dashboardHasTracing(files []string) bool {
-       for _, file := range files {
-               if filepath.Base(file) == "tracing.yaml" {
-                       return true
-               }
-       }
-       return false
-}
-
-func dashboardHasOpenTelemetry(files []string) bool {
-       for _, file := range files {
-               if filepath.Base(file) == "opentelemetry.yaml" {
-                       return true
-               }
-       }
-       return false
-}
-
-func dashboardWaitDeploymentNames(files []string) []string {
-       names := []string{"prometheus", "grafana"}
-       if dashboardHasTracing(files) {
-               names = append(names, "tracing")
-       }
-       if dashboardHasOpenTelemetry(files) {
-               names = append(names, "opentelemetry-collector")
-       }
-       return names
-}
-
-func applyManifestFile(ctx context.Context, client kube.CLIClient, file 
string) ([]appliedObject, error) {
-       objects, err := readManifestObjects(file)
-       if err != nil {
-               return nil, err
-       }
-       applied := make([]appliedObject, 0, len(objects))
-       for _, object := range objects {
-               item, err := applyDashboardObject(ctx, client, object)
-               if err != nil {
-                       return nil, err
-               }
-               applied = append(applied, item)
-       }
-       return applied, nil
-}
-
-func readManifestObjects(path string) ([]*unstructured.Unstructured, error) {
-       file, err := os.Open(path)
-       if err != nil {
-               return nil, err
-       }
-       defer file.Close()
-
-       reader := utilyaml.NewYAMLReader(bufio.NewReader(file))
-       out := []*unstructured.Unstructured{}
-       for {
-               doc, err := reader.Read()
-               if err == io.EOF {
-                       return out, nil
-               }
-               if err != nil {
-                       return nil, fmt.Errorf("read manifest %s: %w", path, 
err)
-               }
-               doc = bytes.TrimSpace(doc)
-               if len(doc) == 0 {
-                       continue
-               }
-               jsonDoc, err := yaml.YAMLToJSON(doc)
-               if err != nil {
-                       return nil, fmt.Errorf("decode manifest %s: %w", path, 
err)
-               }
-               object := &unstructured.Unstructured{}
-               if err := json.Unmarshal(jsonDoc, object); err != nil {
-                       return nil, fmt.Errorf("decode manifest %s: %w", path, 
err)
-               }
-               if object.GetKind() == "" || object.GetAPIVersion() == "" || 
object.GetName() == "" {
-                       return nil, fmt.Errorf("manifest %s contains an object 
without apiVersion, kind, or metadata.name", path)
-               }
-               out = append(out, object)
-       }
-}
-
-func applyDashboardObject(ctx context.Context, client kube.CLIClient, object 
*unstructured.Unstructured) (appliedObject, error) {
-       data, err := json.Marshal(object.Object)
-       if err != nil {
-               return appliedObject{}, err
-       }
-       resource, err := client.DynamicClientFor(object.GroupVersionKind(), 
object, object.GetNamespace())
-       if err != nil {
-               return appliedObject{}, err
-       }
-       force := true
-       applied, err := resource.Patch(ctx, object.GetName(), 
types.ApplyPatchType, data, metav1.PatchOptions{
-               FieldManager: "dubboctl-dashboard",
-               Force:        &force,
-       })
-       if err != nil {
-               return appliedObject{}, fmt.Errorf("apply %s %s/%s: %w", 
object.GetKind(), object.GetNamespace(), object.GetName(), err)
-       }
-       kind := applied.GetKind()
-       if kind == "" {
-               kind = object.GetKind()
-       }
-       namespace := applied.GetNamespace()
-       if namespace == "" {
-               namespace = object.GetNamespace()
-       }
-       return appliedObject{
-               Kind:      kind,
-               Name:      applied.GetName(),
-               Namespace: namespace,
-       }, nil
-}
-
-func printAppliedDashboard(writer io.Writer, objects []appliedObject) error {
-       for _, object := range objects {
-               name := object.Name
-               if object.Namespace != "" {
-                       name = object.Namespace + "/" + name
-               }
-               if _, err := fmt.Fprintf(writer, "applied %s %s\n", 
object.Kind, name); err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-func waitForDashboard(ctx context.Context, client kubernetes.Interface, 
namespace string, names []string, timeout time.Duration) error {
-       for _, name := range names {
-               if err := waitForAvailableDeployment(ctx, client, namespace, 
name, timeout); err != nil {
-                       return err
-               }
-       }
-       return nil
-}
-
-func waitForAvailableDeployment(ctx context.Context, client 
kubernetes.Interface, namespace, name string, timeout time.Duration) error {
-       return wait.PollUntilContextTimeout(ctx, 2*time.Second, timeout, true, 
func(ctx context.Context) (bool, error) {
-               deployment, err := 
client.AppsV1().Deployments(namespace).Get(ctx, name, metav1.GetOptions{})
-               if apierrors.IsNotFound(err) {
-                       return false, nil
-               }
-               if err != nil {
-                       return false, err
-               }
-               return deploymentAvailable(deployment), nil
-       })
-}
-
-func deploymentAvailable(deployment *appsv1.Deployment) bool {
-       desired := int32(1)
-       if deployment.Spec.Replicas != nil {
-               desired = *deployment.Spec.Replicas
-       }
-       return deployment.Status.AvailableReplicas >= desired
-}
diff --git a/dubboctl/cmd/dashboard_test.go b/dubboctl/cmd/dashboard_test.go
deleted file mode 100644
index 00084d42..00000000
--- a/dubboctl/cmd/dashboard_test.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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 cmd
-
-import (
-       "os"
-       "path/filepath"
-       "reflect"
-       "strings"
-       "testing"
-
-       appsv1 "k8s.io/api/apps/v1"
-)
-
-func TestDashboardManifestFiles(t *testing.T) {
-       dir := t.TempDir()
-       for _, name := range []string{"prometheus.yaml", "grafana.yaml"} {
-               if err := os.WriteFile(filepath.Join(dir, name), 
[]byte("apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: "+name+"\n"), 
0o600); err != nil {
-                       t.Fatal(err)
-               }
-       }
-
-       got, err := dashboardManifestFiles(dir)
-       if err != nil {
-               t.Fatalf("dashboardManifestFiles() returned error: %v", err)
-       }
-       want := []string{filepath.Join(dir, "prometheus.yaml"), 
filepath.Join(dir, "grafana.yaml")}
-       if !reflect.DeepEqual(got, want) {
-               t.Fatalf("dashboardManifestFiles() = %v, want %v", got, want)
-       }
-       if dashboardHasTracing(got) {
-               t.Fatalf("dashboardHasTracing() = true, want false")
-       }
-       if names := dashboardWaitDeploymentNames(got); 
!reflect.DeepEqual(names, []string{"prometheus", "grafana"}) {
-               t.Fatalf("dashboardWaitDeploymentNames() = %v", names)
-       }
-}
-
-func TestDashboardManifestFilesIncludesTracingWhenPresent(t *testing.T) {
-       dir := t.TempDir()
-       for _, name := range []string{"prometheus.yaml", "grafana.yaml", 
"tracing.yaml"} {
-               if err := os.WriteFile(filepath.Join(dir, name), 
[]byte("apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: "+name+"\n"), 
0o600); err != nil {
-                       t.Fatal(err)
-               }
-       }
-
-       got, err := dashboardManifestFiles(dir)
-       if err != nil {
-               t.Fatalf("dashboardManifestFiles() returned error: %v", err)
-       }
-       want := []string{filepath.Join(dir, "prometheus.yaml"), 
filepath.Join(dir, "grafana.yaml"), filepath.Join(dir, "tracing.yaml")}
-       if !reflect.DeepEqual(got, want) {
-               t.Fatalf("dashboardManifestFiles() = %v, want %v", got, want)
-       }
-       if !dashboardHasTracing(got) {
-               t.Fatalf("dashboardHasTracing() = false, want true")
-       }
-       if names := dashboardWaitDeploymentNames(got); 
!reflect.DeepEqual(names, []string{"prometheus", "grafana", "tracing"}) {
-               t.Fatalf("dashboardWaitDeploymentNames() = %v", names)
-       }
-}
-
-func TestDashboardManifestFilesIncludesOpenTelemetryWhenPresent(t *testing.T) {
-       dir := t.TempDir()
-       for _, name := range []string{"prometheus.yaml", "grafana.yaml", 
"tracing.yaml", "opentelemetry.yaml"} {
-               if err := os.WriteFile(filepath.Join(dir, name), 
[]byte("apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: "+name+"\n"), 
0o600); err != nil {
-                       t.Fatal(err)
-               }
-       }
-
-       got, err := dashboardManifestFiles(dir)
-       if err != nil {
-               t.Fatalf("dashboardManifestFiles() returned error: %v", err)
-       }
-       want := []string{
-               filepath.Join(dir, "prometheus.yaml"),
-               filepath.Join(dir, "grafana.yaml"),
-               filepath.Join(dir, "tracing.yaml"),
-               filepath.Join(dir, "opentelemetry.yaml"),
-       }
-       if !reflect.DeepEqual(got, want) {
-               t.Fatalf("dashboardManifestFiles() = %v, want %v", got, want)
-       }
-       if !dashboardHasOpenTelemetry(got) {
-               t.Fatalf("dashboardHasOpenTelemetry() = false, want true")
-       }
-       if names := dashboardWaitDeploymentNames(got); 
!reflect.DeepEqual(names, []string{"prometheus", "grafana", "tracing", 
"opentelemetry-collector"}) {
-               t.Fatalf("dashboardWaitDeploymentNames() = %v", names)
-       }
-}
-
-func TestReadManifestObjects(t *testing.T) {
-       file := filepath.Join(t.TempDir(), "manifest.yaml")
-       manifest := strings.Join([]string{
-               "apiVersion: v1",
-               "kind: ConfigMap",
-               "metadata:",
-               "  name: first",
-               "---",
-               "apiVersion: v1",
-               "kind: Service",
-               "metadata:",
-               "  name: second",
-               "",
-       }, "\n")
-       if err := os.WriteFile(file, []byte(manifest), 0o600); err != nil {
-               t.Fatal(err)
-       }
-
-       objects, err := readManifestObjects(file)
-       if err != nil {
-               t.Fatalf("readManifestObjects() returned error: %v", err)
-       }
-       if len(objects) != 2 {
-               t.Fatalf("readManifestObjects() returned %d objects, want 2", 
len(objects))
-       }
-       if objects[0].GetKind() != "ConfigMap" || objects[1].GetKind() != 
"Service" {
-               t.Fatalf("unexpected objects: %s, %s", objects[0].GetKind(), 
objects[1].GetKind())
-       }
-}
-
-func TestDeploymentAvailable(t *testing.T) {
-       replicas := int32(2)
-       if deploymentAvailable(&appsv1.Deployment{Spec: 
appsv1.DeploymentSpec{Replicas: &replicas}, Status: 
appsv1.DeploymentStatus{AvailableReplicas: 1}}) {
-               t.Fatal("deploymentAvailable() = true, want false")
-       }
-       if !deploymentAvailable(&appsv1.Deployment{Spec: 
appsv1.DeploymentSpec{Replicas: &replicas}, Status: 
appsv1.DeploymentStatus{AvailableReplicas: 2}}) {
-               t.Fatal("deploymentAvailable() = false, want true")
-       }
-}
diff --git a/dubboctl/cmd/root.go b/dubboctl/cmd/root.go
index 5685ccc4..1321403f 100644
--- a/dubboctl/cmd/root.go
+++ b/dubboctl/cmd/root.go
@@ -145,10 +145,8 @@ func GetRootCmd(args []string) *cobra.Command {
        hideFlags(imageCmd, ChartFlag)
 
        rootCmd.AddCommand(GetCmd(ctx))
-       rootCmd.AddCommand(AdminCmd(ctx))
        rootCmd.AddCommand(ProxyStatusCmd(ctx))
        rootCmd.AddCommand(AnalyzeCmd(ctx))
-       rootCmd.AddCommand(DashboardCmd(ctx))
        rootCmd.AddCommand(MulticlusterCmd())
 
        rootCmd.AddCommand(GuiCmd())

Reply via email to