Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement dubboctl dashboard subcmd #1197

Merged
merged 63 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
35f09f1
dubboctl demo
DMwangnima Mar 8, 2023
dad3f8c
Merge branch 'refactor-with-go' into dubboctl-demo
DMwangnima Mar 8, 2023
09d58d1
dubboctl-zookeeper demo
DMwangnima Mar 10, 2023
e428265
add manifest cobra cmd
DMwangnima Mar 10, 2023
231c60b
Merge branch 'refactor-with-go' into dubboctl-demo
DMwangnima Mar 10, 2023
a5a7ce0
fix some bugs
DMwangnima Mar 10, 2023
7047c3b
move dubboctl dirs and add license
DMwangnima Mar 14, 2023
2ca4ad8
move dubboctl dirs and add license
DMwangnima Mar 14, 2023
6a3d964
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Mar 14, 2023
2ed7534
add remaining licenses
DMwangnima Mar 14, 2023
2f25e59
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Mar 14, 2023
a7cf673
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Mar 14, 2023
8f55cf5
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Mar 14, 2023
bc39dfc
modify .gitignore
DMwangnima Mar 14, 2023
60f7c5d
modify .gitignore
DMwangnima Mar 14, 2023
4481f2e
remove dubbogo-cli dependency
DMwangnima Mar 14, 2023
3b16f46
fix lint and test error
DMwangnima Mar 14, 2023
dc75bc5
gofumpt processing
DMwangnima Mar 14, 2023
3647fda
fix: <#1035> Lock Release issue
DMwangnima Mar 14, 2023
f40f338
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Mar 18, 2023
79ce90b
add install subcommand
DMwangnima Apr 3, 2023
88d9111
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Apr 3, 2023
069effe
resolve conflict
DMwangnima Apr 4, 2023
c460679
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Apr 4, 2023
b83901a
add some comments
DMwangnima Apr 4, 2023
21b2aa5
resolve conflict
DMwangnima Apr 4, 2023
65678cc
resolve conflict
DMwangnima Apr 4, 2023
fa1cbc5
modify some representation
DMwangnima Apr 4, 2023
22bf927
modify identifier to env
DMwangnima Apr 4, 2023
d987bd8
fix some tests
DMwangnima Apr 4, 2023
16613a5
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Apr 5, 2023
cb83a64
expose test flag and test cli
DMwangnima Apr 9, 2023
43acd19
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Apr 12, 2023
dd78011
add unit tests
DMwangnima Apr 12, 2023
781101b
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Apr 12, 2023
7e5ea5e
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Apr 12, 2023
5dc675e
modify golden test
DMwangnima Apr 12, 2023
291197a
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Apr 12, 2023
70bd0b6
add license to test yaml file
DMwangnima Apr 12, 2023
100eda4
move filter to util package
DMwangnima Apr 13, 2023
b50af5c
add cmd logger
DMwangnima Apr 13, 2023
c1b9d4c
add cmd logger
DMwangnima Apr 13, 2023
7e1a305
set namespace when apply manifest
DMwangnima Apr 13, 2023
f6ab159
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Apr 18, 2023
98b5cfc
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Apr 20, 2023
d1034ba
implement manifest diff and manifest uninstall
DMwangnima Apr 27, 2023
f095383
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Apr 27, 2023
1f530e6
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Apr 27, 2023
3c7ef10
update admin testdata
DMwangnima Apr 27, 2023
d445b40
delete dubboctl exe
DMwangnima Apr 27, 2023
25d602e
add license
DMwangnima Apr 27, 2023
dcfc6bb
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima May 3, 2023
4a3ae60
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima May 6, 2023
c873f12
implement profile related cmds and add some small fixs
DMwangnima May 9, 2023
4458b23
fix conflict
DMwangnima May 9, 2023
5fefdae
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima May 14, 2023
118da1f
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Jul 3, 2023
80479ef
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Jul 4, 2023
b913b1e
implement dashboard subcmd
DMwangnima Jul 12, 2023
0cc84da
Merge branch 'apache:refactor-with-go' into refactor-with-go
DMwangnima Jul 12, 2023
900c491
Merge branch 'refactor-with-go' of github.com:DMwangnima/dubbo-admin …
DMwangnima Jul 12, 2023
0c4fca6
fix RESTClient bug
DMwangnima Jul 13, 2023
3814324
update skywalking pod selector
DMwangnima Jul 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions pkg/dubboctl/cmd/dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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 (
"github.com/apache/dubbo-admin/pkg/dubboctl/cmd/subcmd"
"github.com/spf13/cobra"
)

func addDashboard(rootCmd *cobra.Command) {
dashboardCmd := &cobra.Command{
Use: "dashboard",
Short: "Commands related to control plane components dashboards",
Long: "Commands help user to open control plane components dashboards directly. Now support Admin, Grafana, Nacos, Prometheus, Skywalking and Zipkin",
}
subcmd.ConfigDashboardAdminCmd(dashboardCmd)
subcmd.ConfigDashboardGrafanaCmd(dashboardCmd)
subcmd.ConfigDashboardNacosCmd(dashboardCmd)
subcmd.ConfigDashboardPrometheusCmd(dashboardCmd)
subcmd.ConfigDashboardSkywalkingCmd(dashboardCmd)
subcmd.ConfigDashboardZipkinCmd(dashboardCmd)

rootCmd.AddCommand(dashboardCmd)
}
4 changes: 2 additions & 2 deletions pkg/dubboctl/cmd/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func addProfile(rootCmd *cobra.Command) {
Short: "Commands related to profiles",
Long: "Commands help user to list and describe profiles",
}
subcmd.ConfigProfileListArgs(profileCmd)
subcmd.ConfigProfileDiffArgs(profileCmd)
subcmd.ConfigProfileListCmd(profileCmd)
subcmd.ConfigProfileDiffCmd(profileCmd)

rootCmd.AddCommand(profileCmd)
}
1 change: 1 addition & 0 deletions pkg/dubboctl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@ func getRootCmd(args []string) *cobra.Command {
func addSubCommands(rootCmd *cobra.Command) {
addManifest(rootCmd)
addProfile(rootCmd)
addDashboard(rootCmd)
}
229 changes: 229 additions & 0 deletions pkg/dubboctl/cmd/subcmd/dashboard_all_cmds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// 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 subcmd

import (
"context"
"fmt"
"github.com/apache/dubbo-admin/pkg/dubboctl/identifier"
"github.com/apache/dubbo-admin/pkg/dubboctl/internal/kube"
"github.com/apache/dubbo-admin/pkg/dubboctl/internal/operator"
"github.com/apache/dubbo-admin/pkg/logger"
"github.com/spf13/cobra"
"go.uber.org/zap/zapcore"
"io"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"net"
"os"
"os/exec"
"os/signal"
"runtime"
"strconv"
"strings"
)

var (
// todo: think about a efficient way to change selectors and ports when yaml files change
// ports are coming from /deploy/charts and /deploy/kubernetes
ComponentPortMap = map[operator.ComponentName]int{
operator.Admin: 8080,
operator.Grafana: 3000,
operator.Nacos: 8848,
operator.Prometheus: 9090,
operator.Skywalking: 8080,
operator.Zipkin: 9411,
}
// selectors are coming from /deploy/charts and /deploy/kubernetes
ComponentSelectorMap = map[operator.ComponentName]string{
operator.Admin: "app.kubernetes.io/name=dubbo-admin",
operator.Grafana: "app.kubernetes.io/name=grafana",
operator.Nacos: "app.kubernetes.io/name=nacos",
operator.Prometheus: "app=prometheus",
operator.Skywalking: "app=skywalking, component=ui",
operator.Zipkin: "app.kubernetes.io/name=zipkin",
}
)

type DashboardCommonArgs struct {
port int
host string
openBrowser bool
namespace string
KubeConfigPath string
// selected cluster info of kubeconfig
Context string
}

func (dca *DashboardCommonArgs) setDefault() {
if dca == nil {
return
}
if dca.host == "" {
dca.host = "127.0.0.1"
}
if dca.namespace == "" {
dca.namespace = identifier.DubboSystemNamespace
}
}

func commonDashboardCmd(baseCmd *cobra.Command, compName operator.ComponentName) {
nameStr := string(compName)
lowerNameStr := strings.ToLower(nameStr)
dcArgs := &DashboardCommonArgs{}
cmd := &cobra.Command{
Use: lowerNameStr,
Short: fmt.Sprintf("create PortForward between local address and target component %s pod. open browser by default", nameStr),
Example: fmt.Sprintf(` # create PortForward in 127.0.0.1:%d and open browser directly
dubboctl dashboard %s
# specify port
dubboctl dashboard %s --port 8888
# do not open browser
dubboctl dashboard %s --openBrowser false
# specify namespace of Admin
dubboctl dashboard %s --namespace user_specified
`, ComponentPortMap[compName], lowerNameStr, lowerNameStr, lowerNameStr, lowerNameStr),
RunE: func(cmd *cobra.Command, args []string) error {
logger.InitCmdSugar(zapcore.AddSync(cmd.OutOrStdout()))
dcArgs.setDefault()
if err := portForward(dcArgs, compName, cmd.OutOrStdout()); err != nil {
return err
}
return nil
},
}
cmd.PersistentFlags().IntVarP(&dcArgs.port, "port", "p", 0,
fmt.Sprintf("local port to listen on. If not set, it would be same as the default port of component %s", nameStr))
cmd.PersistentFlags().StringVarP(&dcArgs.host, "host", "", "",
"local host to bind. If not set, it would be 127.0.0.1")
// openBrowser is default behaviour
cmd.PersistentFlags().BoolVarP(&dcArgs.openBrowser, "openBrowser", "", true,
"whether to open browser automatically")
cmd.PersistentFlags().StringVarP(&dcArgs.namespace, "namespace", "n", "",
fmt.Sprintf("namespace in which component %s is located", nameStr))
cmd.PersistentFlags().StringVarP(&dcArgs.KubeConfigPath, "kubeConfig", "", "",
"Path to kubeConfig")
cmd.PersistentFlags().StringVarP(&dcArgs.Context, "context", "", "",
"Context in kubeConfig to use")

baseCmd.AddCommand(cmd)
}

func ConfigDashboardAdminCmd(baseCmd *cobra.Command) {
commonDashboardCmd(baseCmd, operator.Admin)
}

func ConfigDashboardGrafanaCmd(baseCmd *cobra.Command) {
commonDashboardCmd(baseCmd, operator.Grafana)
}

func ConfigDashboardNacosCmd(baseCmd *cobra.Command) {
commonDashboardCmd(baseCmd, operator.Nacos)
}

func ConfigDashboardPrometheusCmd(baseCmd *cobra.Command) {
commonDashboardCmd(baseCmd, operator.Prometheus)
}

func ConfigDashboardSkywalkingCmd(baseCmd *cobra.Command) {
commonDashboardCmd(baseCmd, operator.Skywalking)
}

func ConfigDashboardZipkinCmd(baseCmd *cobra.Command) {
commonDashboardCmd(baseCmd, operator.Zipkin)
}

func portForward(args *DashboardCommonArgs, compName operator.ComponentName, writer io.Writer) error {
// process args
var podPort int
podPort = ComponentPortMap[compName]
if args.port == 0 {
args.port = podPort
}

// prepare PortForward args
labelSelector := ComponentSelectorMap[compName]
cfg, err := kube.BuildConfig(args.KubeConfigPath, args.Context)
if err != nil {
return fmt.Errorf("build kube config failed, err: %s", err)
}
// todo: unify kube client
cli, err := kubernetes.NewForConfig(cfg)
if err != nil {
return fmt.Errorf("create kube RESTClient failed, err: %s", err)
}
pods, err := cli.CoreV1().Pods(args.namespace).List(context.Background(), metav1.ListOptions{

Check failure on line 168 in pkg/dubboctl/cmd/subcmd/dashboard_all_cmds.go

View workflow job for this annotation

GitHub Actions / lint

ineffectual assignment to err (ineffassign)
LabelSelector: labelSelector,
})
if len(pods.Items) < 1 {
return fmt.Errorf("no %s pods found", string(compName))
}
// use name of the first pod
podName := pods.Items[0].Name

pf, err := kube.NewPortForward(podName, args.namespace, args.host, args.port, podPort, cfg)
if err != nil {
return fmt.Errorf("create PortForward failed, err: %s", err)
}
if err := pf.Run(); err != nil {
pf.Stop()
return fmt.Errorf("PortForward running failed, err: %s", err)
}

logger.CmdSugar().Infof("PortForward to %s pod is running", podName)

// wait for interrupt
go func() {
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt)
defer signal.Stop(signals)
<-signals
logger.CmdSugar().Info("PortForward stops")
pf.Stop()
}()

if args.openBrowser {
address := net.JoinHostPort(args.host, strconv.Itoa(args.port))
url := "http://" + address
openBrowser(url, writer)
}

pf.Wait()

return nil
}

// openBrowser uses syscall from different runtime
func openBrowser(url string, writer io.Writer) {
var err error

fmt.Fprintf(writer, "open browser in %s\n", url)

switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", url).Start()
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
err = exec.Command("open", url).Start()
default:
fmt.Fprintf(writer, "unsupported platform %q. pls open %s in your browser.\n", runtime.GOOS, url)
}

if err != nil {
fmt.Fprintf(writer, "open browser failed; open %s in your browser.\n", url)
}
}
6 changes: 3 additions & 3 deletions pkg/dubboctl/cmd/subcmd/manifest_install.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ func ConfigManifestInstallCmd(baseCmd *cobra.Command) {
},
}
addManifestGenerateFlags(miCmd, mgArgs)
miCmd.PersistentFlags().StringVarP(&miArgs.KubeConfigPath, "kubeconfig", "", "",
"Path to kubeconfig")
miCmd.PersistentFlags().StringVarP(&miArgs.KubeConfigPath, "kubeConfig", "", "",
"Path to kubeConfig")
miCmd.PersistentFlags().StringVarP(&miArgs.Context, "context", "", "",
"Context in kubeconfig to use")
"Context in kubeConfig to use")

baseCmd.AddCommand(miCmd)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/dubboctl/cmd/subcmd/profile_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (pda *ProfileDiffArgs) setDefault() {
}
}

func ConfigProfileDiffArgs(baseCmd *cobra.Command) {
func ConfigProfileDiffCmd(baseCmd *cobra.Command) {
pdArgs := &ProfileDiffArgs{}
pdCmd := &cobra.Command{
Use: "diff",
Expand Down
2 changes: 1 addition & 1 deletion pkg/dubboctl/cmd/subcmd/profile_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (pla *ProfileListArgs) setDefault() {
}
}

func ConfigProfileListArgs(baseCmd *cobra.Command) {
func ConfigProfileListCmd(baseCmd *cobra.Command) {
plArgs := &ProfileListArgs{}
plCmd := &cobra.Command{
Use: "list",
Expand Down
2 changes: 1 addition & 1 deletion pkg/dubboctl/internal/kube/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ import (

// CtlClient wraps controller-runtime client and is used by dubboctl
type CtlClient struct {
client.Client
opts *CtlClientOptions
client.Client
}

type CtlClientOptions struct {
Expand Down
33 changes: 30 additions & 3 deletions pkg/dubboctl/internal/kube/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ package kube

import (
"fmt"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"os"
"strconv"
"strings"

jsonpatch "github.com/evanphx/json-patch/v5"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
kubescheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubectl/pkg/scheme"
Expand Down Expand Up @@ -135,10 +139,33 @@ func BuildConfig(kubecfgPath string, ctx string) (*rest.Config, error) {
if err != nil {
return nil, err
}
// setDefaults(cfg)
setDefaults(cfg)
return cfg, nil
}

func setDefaults(cfg *rest.Config) {
// todo:// add schema
func setDefaults(config *rest.Config) *rest.Config {
if config.GroupVersion == nil || config.GroupVersion.Empty() {
config.GroupVersion = &corev1.SchemeGroupVersion
}
if len(config.APIPath) == 0 {
if len(config.GroupVersion.Group) == 0 {
config.APIPath = "/api"
} else {
config.APIPath = "/apis"
}
}
if len(config.ContentType) == 0 {
config.ContentType = runtime.ContentTypeJSON
}
if config.NegotiatedSerializer == nil {
config.NegotiatedSerializer = serializer.NewCodecFactory(dubboScheme()).WithoutConversion()
}

return config
}

func dubboScheme() *runtime.Scheme {
newScheme := runtime.NewScheme()
utilruntime.Must(kubescheme.AddToScheme(newScheme))
return newScheme
}
Loading
Loading