diff --git a/deploy/skoopbundle.yaml b/deploy/skoopbundle.yaml index 5f2a282f..f1ac0373 100644 --- a/deploy/skoopbundle.yaml +++ b/deploy/skoopbundle.yaml @@ -31,7 +31,7 @@ spec: dnsPolicy: ClusterFirstWithHostNet initContainers: - name: inspector-prepare - image: "kubeskoop/kubeskoop:latest" + image: kubeskoop/kubeskoop:v1.0.0 volumeMounts: - name: btf-rawdata mountPath: /etc/net-exporter/btf @@ -39,7 +39,7 @@ spec: name: boot command: [btfhack, discover, -p, /etc/net-exporter/btf/] containers: - - image: "kubeskoop/kubeskoop:latest" + - image: kubeskoop/kubeskoop:v1.0.0 name: inspector env: - name: INSPECTOR_NODENAME @@ -383,7 +383,7 @@ spec: name: grafana-datasources readOnly: false - name: register-dashboard - image: kubeskoop/kubeskoop:latest + image: kubeskoop/kubeskoop:v1.0.0 env: - name: GRAFANA_PASSWORD value: "kubeskoop" @@ -579,7 +579,7 @@ spec: spec: containers: - name: controller - image: registry.aliyuncs.com/wangbs/kubeskoop:latest + image: kubeskoop/kubeskoop:v1.0.0 command: ["/bin/controller"] env: - name: PROMETHEUS_ENDPOINT @@ -627,7 +627,7 @@ spec: spec: containers: - name: controller - image: registry.aliyuncs.com/wangbs/kubeskoop:latest + image: kubeskoop/kubeskoop:v1.0.0 command: ["/bin/webconsole"] env: - name: CONTROLLER_ENDPOINT diff --git a/go.mod b/go.mod index b121eb2c..1d140853 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/alibaba/kubeskoop go 1.19 require ( - github.com/afiskon/promtail-client v0.0.0-20190305142237-506f3f921e9c github.com/alibabacloud-go/darabonba-openapi v0.2.1 github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2 github.com/alibabacloud-go/ecs-20140526/v2 v2.1.3 @@ -22,6 +21,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/hashicorp/golang-lru/v2 v2.0.6 github.com/jmoiron/sqlx v1.3.5 + github.com/json-iterator/go v1.1.12 github.com/mattn/go-sqlite3 v1.14.6 github.com/mdlayher/netlink v1.7.1 github.com/mitchellh/mapstructure v1.5.0 @@ -32,6 +32,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/projectcalico/api v0.0.0-20220722155641-439a754a988b github.com/prometheus/client_golang v1.15.1 + github.com/prometheus/common v0.42.0 github.com/prometheus/procfs v0.9.0 github.com/samber/lo v1.37.0 github.com/sirupsen/logrus v1.9.0 @@ -48,6 +49,7 @@ require ( golang.org/x/sys v0.8.0 google.golang.org/grpc v1.56.2 google.golang.org/protobuf v1.31.0 + gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.26.0 k8s.io/apimachinery v0.26.0 k8s.io/client-go v0.25.2 @@ -133,7 +135,6 @@ require ( github.com/intel/goresctrl v0.2.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/josharian/native v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.11.13 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect @@ -164,7 +165,6 @@ require ( github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.8.0 // indirect github.com/spf13/afero v1.9.3 // indirect @@ -200,7 +200,6 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiserver v0.22.5 // indirect k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a // indirect oss.terrastruct.com/util-go v0.0.0-20230604222829-11c3c60fec14 // indirect diff --git a/go.sum b/go.sum index 34002d7d..076a375c 100644 --- a/go.sum +++ b/go.sum @@ -107,8 +107,6 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/afiskon/promtail-client v0.0.0-20190305142237-506f3f921e9c h1:AMDVOKGaiqse4qiRXSzRgpC9DCNTHCx6zpzdtXXrKM4= -github.com/afiskon/promtail-client v0.0.0-20190305142237-506f3f921e9c/go.mod h1:p/7Wos+jcfrnwLqqzJMZ0s323kfVtJPW+HUvAANklVQ= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= @@ -730,6 +728,7 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= @@ -871,6 +870,7 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= diff --git a/pkg/controller/cmd/root.go b/pkg/controller/cmd/root.go index dc6b67bb..2f3af5ef 100644 --- a/pkg/controller/cmd/root.go +++ b/pkg/controller/cmd/root.go @@ -1,9 +1,10 @@ package cmd import ( + "os" + log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "os" ) // rootCmd represents the base command when called without any subcommands @@ -40,5 +41,5 @@ func Execute() { func init() { rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "Enable debug log information") rootCmd.PersistentFlags().IntVarP(&agentPort, "agent-port", "a", defaultAgentPort, "Controller Port For Agent Registration") - rootCmd.PersistentFlags().IntVarP(&httpPort, "http-port", "p", defaultHttpPort, "Controller Port For Agent Registration") + rootCmd.PersistentFlags().IntVarP(&httpPort, "http-port", "p", defaultHTTPPort, "Controller Port For Agent Registration") } diff --git a/pkg/controller/cmd/server.go b/pkg/controller/cmd/server.go index cc1515fd..0a644c18 100644 --- a/pkg/controller/cmd/server.go +++ b/pkg/controller/cmd/server.go @@ -2,14 +2,6 @@ package cmd import ( "fmt" - "github.com/alibaba/kubeskoop/pkg/controller/graph" - "github.com/alibaba/kubeskoop/pkg/controller/rpc" - "github.com/alibaba/kubeskoop/pkg/controller/service" - exporter "github.com/alibaba/kubeskoop/pkg/exporter/cmd" - skoopContext "github.com/alibaba/kubeskoop/pkg/skoop/context" - "github.com/gin-gonic/gin" - "github.com/prometheus/common/model" - "google.golang.org/grpc" "io" "log" "net" @@ -21,11 +13,20 @@ import ( "strings" "syscall" "time" + + "github.com/alibaba/kubeskoop/pkg/controller/graph" + "github.com/alibaba/kubeskoop/pkg/controller/rpc" + "github.com/alibaba/kubeskoop/pkg/controller/service" + exporter "github.com/alibaba/kubeskoop/pkg/exporter/cmd" + skoopContext "github.com/alibaba/kubeskoop/pkg/skoop/context" + "github.com/gin-gonic/gin" + "github.com/prometheus/common/model" + "google.golang.org/grpc" ) const ( defaultAgentPort = 10263 - defaultHttpPort = 10264 + defaultHTTPPort = 10264 ) type Server struct { @@ -75,7 +76,7 @@ func (s *Server) RunAgentServer(port int, done <-chan struct{}) { func (s *Server) RunHTTPServer(port int, done <-chan struct{}) { if port == 0 { - port = defaultHttpPort + port = defaultHTTPPort } r := gin.New() r.Use(gin.Logger()) diff --git a/pkg/controller/db/db.go b/pkg/controller/db/db.go index 121a2ac4..133131b6 100644 --- a/pkg/controller/db/db.go +++ b/pkg/controller/db/db.go @@ -3,13 +3,16 @@ package db import ( "bytes" "database/sql" - _ "database/sql" + + // import for go:embed _ "embed" "fmt" - "github.com/jmoiron/sqlx" - _ "github.com/mattn/go-sqlite3" "text/template" "time" + + "github.com/jmoiron/sqlx" + // import for sqlite + _ "github.com/mattn/go-sqlite3" ) //go:embed db_schema_v1.sql.tpl diff --git a/pkg/controller/diagnose/diagnose.go b/pkg/controller/diagnose/diagnose.go index 1f748ce6..22348c26 100644 --- a/pkg/controller/diagnose/diagnose.go +++ b/pkg/controller/diagnose/diagnose.go @@ -3,17 +3,18 @@ package diagnose import ( "context" "fmt" - skoopContext "github.com/alibaba/kubeskoop/pkg/skoop/context" "os" "os/exec" "strconv" + + skoopContext "github.com/alibaba/kubeskoop/pkg/skoop/context" ) -type DiagnoseController interface { +type Controller interface { Diagnose(ctx context.Context, taskConfig *skoopContext.TaskConfig) (string, error) } -func NewDiagnoseController() DiagnoseController { +func NewDiagnoseController() Controller { // 1. build skoop global context return &diagnoser{} } @@ -29,7 +30,7 @@ func (d *diagnoser) Diagnose(ctx context.Context, taskConfig *skoopContext.TaskC defer os.RemoveAll(tempDir) resultStorage := fmt.Sprintf("%v/result.json", tempDir) - cmd := exec.Command("skoop", "--output", resultStorage, "--format", "json", + cmd := exec.CommandContext(ctx, "skoop", "--output", resultStorage, "--format", "json", "-s", taskConfig.Source, "-d", taskConfig.Destination.Address, "--dport", strconv.FormatUint(uint64(taskConfig.Destination.Port), 10)) diff --git a/pkg/controller/graph/graph.go b/pkg/controller/graph/graph.go index fead454e..1873c9f0 100644 --- a/pkg/controller/graph/graph.go +++ b/pkg/controller/graph/graph.go @@ -2,10 +2,11 @@ package graph import ( "fmt" + "strconv" + jsoniter "github.com/json-iterator/go" "github.com/prometheus/common/model" "github.com/samber/lo" - "strconv" ) type Node struct { diff --git a/pkg/controller/rpc/controller.pb.go b/pkg/controller/rpc/controller.pb.go index 7069e16e..d4319f69 100644 --- a/pkg/controller/rpc/controller.pb.go +++ b/pkg/controller/rpc/controller.pb.go @@ -7,10 +7,11 @@ package rpc import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/pkg/controller/rpc/controller_grpc.pb.go b/pkg/controller/rpc/controller_grpc.pb.go index ab068368..ea5817f1 100644 --- a/pkg/controller/rpc/controller_grpc.pb.go +++ b/pkg/controller/rpc/controller_grpc.pb.go @@ -8,6 +8,7 @@ package rpc import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/controller/service/agent.go b/pkg/controller/service/agent.go index 612ed3f1..37eff386 100644 --- a/pkg/controller/service/agent.go +++ b/pkg/controller/service/agent.go @@ -3,10 +3,11 @@ package service import ( "context" "fmt" + "sync/atomic" + "github.com/alibaba/kubeskoop/pkg/controller/rpc" "github.com/samber/lo" log "k8s.io/klog/v2" - "sync/atomic" ) type taskWatcher struct { @@ -14,11 +15,11 @@ type taskWatcher struct { filter *rpc.TaskFilter } -func (c *controller) RegisterAgent(ctx context.Context, info *rpc.AgentInfo) (*rpc.ControllerInfo, error) { +func (c *controller) RegisterAgent(_ context.Context, _ *rpc.AgentInfo) (*rpc.ControllerInfo, error) { return nil, nil } -func (c *controller) ReportEvents(server rpc.ControllerRegisterService_ReportEventsServer) error { +func (c *controller) ReportEvents(_ rpc.ControllerRegisterService_ReportEventsServer) error { return nil } @@ -71,7 +72,7 @@ func (c *controller) GetAgentList() []*rpc.AgentInfo { } var ( - taskIdx int64 = 0 + taskIdx int64 ) func getTaskIdx() int64 { @@ -97,9 +98,9 @@ func (c *controller) commitTask(node string, task *rpc.Task) ([]string, error) { }) if len(commitedNode) > 0 { return commitedNode, nil - } else { - return nil, fmt.Errorf("there is no client to process task: %v", task) } + + return nil, fmt.Errorf("there is no client to process task: %v", task) } func (c *controller) waitTaskResult(ctx context.Context, id string) (*rpc.TaskResult, error) { diff --git a/pkg/controller/service/capture.go b/pkg/controller/service/capture.go index d2341003..fd4d6b5d 100644 --- a/pkg/controller/service/capture.go +++ b/pkg/controller/service/capture.go @@ -3,17 +3,26 @@ package service import ( "context" "fmt" - "github.com/alibaba/kubeskoop/pkg/controller/rpc" - "github.com/samber/lo" "io" - corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - log "k8s.io/klog/v2" "os" "os/exec" "path" "strconv" "sync" + + "github.com/alibaba/kubeskoop/pkg/controller/rpc" + "github.com/samber/lo" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + log "k8s.io/klog/v2" +) + +const ( + typePod = "Pod" + typeNode = "Node" + + statusSuccess = "success" + statusFailed = "failed" ) type CaptureArgs struct { @@ -106,18 +115,18 @@ func (c *controller) Capture(ctx context.Context, capture *CaptureArgs) (int, er Filter: capture.Filter, } switch captureItem.Type { - case "Pod": + case typePod: var err error task.Pod, task.Node, _, err = c.getPodInfo(ctx, captureItem.Namespace, captureItem.Name) if err != nil { return 0, err } - task.CaptureType = "Pod" - case "Node": + task.CaptureType = typePod + case typeNode: task.Node = &rpc.NodeInfo{ Name: captureItem.Name, } - task.CaptureType = "Node" + task.CaptureType = typeNode default: return 0, fmt.Errorf("invalid capture type: %v", captureItem.Type) } @@ -137,7 +146,7 @@ func (c *controller) Capture(ctx context.Context, capture *CaptureArgs) (int, er return 0, err } var spec *TaskSpec - if captureInfo.GetCaptureType() == "Pod" { + if captureInfo.GetCaptureType() == typePod { spec = &TaskSpec{ TaskType: captureInfo.CaptureType, Name: captureInfo.GetPod().Name, @@ -163,7 +172,7 @@ func (c *controller) Capture(ctx context.Context, capture *CaptureArgs) (int, er return taskID, nil } -func (c *controller) CaptureList(ctx context.Context) (map[int][]*CaptureTaskResult, error) { +func (c *controller) CaptureList(_ context.Context) (map[int][]*CaptureTaskResult, error) { results := map[int][]*CaptureTaskResult{} captureTasks.Range(func(key, value interface{}) bool { id := key.(int) @@ -174,14 +183,14 @@ func (c *controller) CaptureList(ctx context.Context) (map[int][]*CaptureTaskRes return results, nil } -func (c *controller) storeCaptureFile(ctx context.Context, spec *TaskSpec, id int, result *rpc.CaptureResult) (string, error) { +func (c *controller) storeCaptureFile(_ context.Context, spec *TaskSpec, id int, result *rpc.CaptureResult) (string, error) { taskPath := fmt.Sprintf("/tmp/task_%d/", id) err := os.MkdirAll(taskPath, 0755) if err != nil { return "", err } captureFileName := "" - if spec.TaskType == "Pod" { + if spec.TaskType == typePod { captureFileName = fmt.Sprintf("capture_task_%d_%s_%s", id, spec.Namespace, spec.Name) } else { captureFileName = fmt.Sprintf("capture_task_%d_%s_%s", id, "node", spec.Name) @@ -196,7 +205,7 @@ func (c *controller) storeCaptureFile(ctx context.Context, spec *TaskSpec, id in func (c *controller) DownloadCaptureFile(ctx context.Context, id int) (string, int64, io.ReadCloser, error) { filename := fmt.Sprintf("/tmp/capture_task_%d.tar.gz", id) - compressResults := exec.Command("tar", "-czf", filename, fmt.Sprintf("/tmp/task_%d/", id)) + compressResults := exec.CommandContext(ctx, "tar", "-czf", filename, fmt.Sprintf("/tmp/task_%d/", id)) output, err := compressResults.CombinedOutput() if err != nil { return "", 0, nil, fmt.Errorf("error compress capture file: %v, output: %s", err, string(output)) @@ -224,14 +233,14 @@ func (c *controller) storeCaptureResult(ctx context.Context, result *rpc.TaskRes (result.GetTask().GetPod() == nil && result.GetTask().GetNode().GetName() == captureResult.Spec.Name) { captureResult.Message = result.GetMessage() if result.GetSuccess() { - captureResult.Status = "success" + captureResult.Status = statusSuccess captureFile, err := c.storeCaptureFile(ctx, captureResult.Spec, id, result.GetCapture()) if err != nil { return nil, fmt.Errorf("store capture file failed: %v", err) } captureResult.Result = captureFile } else { - captureResult.Status = "failed" + captureResult.Status = statusFailed } } } diff --git a/pkg/controller/service/config.go b/pkg/controller/service/config.go index 409af9c7..3e2528b2 100644 --- a/pkg/controller/service/config.go +++ b/pkg/controller/service/config.go @@ -2,6 +2,7 @@ package service import ( "context" + exporter "github.com/alibaba/kubeskoop/pkg/exporter/cmd" "gopkg.in/yaml.v3" ) diff --git a/pkg/controller/service/controller.go b/pkg/controller/service/controller.go index 92f0fa58..b4234111 100644 --- a/pkg/controller/service/controller.go +++ b/pkg/controller/service/controller.go @@ -3,14 +3,15 @@ package service import ( "context" "fmt" - exporter "github.com/alibaba/kubeskoop/pkg/exporter/cmd" - "github.com/alibaba/kubeskoop/pkg/exporter/loki" "io" "os" "strings" "sync" "time" + exporter "github.com/alibaba/kubeskoop/pkg/exporter/cmd" + lokiwrapper "github.com/alibaba/kubeskoop/pkg/exporter/loki" + "github.com/alibaba/kubeskoop/pkg/controller/diagnose" "github.com/alibaba/kubeskoop/pkg/controller/rpc" skoopContext "github.com/alibaba/kubeskoop/pkg/skoop/context" @@ -99,7 +100,7 @@ func NewControllerService() (ControllerService, error) { type controller struct { rpc.UnimplementedControllerRegisterServiceServer - diagnosor diagnose.DiagnoseController + diagnosor diagnose.Controller k8sClient *kubernetes.Clientset taskWatcher sync.Map resultWatchers sync.Map diff --git a/pkg/controller/service/diagnose.go b/pkg/controller/service/diagnose.go index 81350e76..12a5235c 100644 --- a/pkg/controller/service/diagnose.go +++ b/pkg/controller/service/diagnose.go @@ -3,11 +3,12 @@ package service import ( "context" "encoding/json" + "time" + "github.com/alibaba/kubeskoop/pkg/controller/db" skoopContext "github.com/alibaba/kubeskoop/pkg/skoop/context" log "github.com/sirupsen/logrus" "golang.org/x/exp/slices" - "time" ) // todo reflect to generic task definition @@ -16,12 +17,12 @@ type DiagnoseTaskResult struct { TaskConfig string `json:"task_config" db:"config"` StartTime string `json:"start_time" db:"start_time"` FinishTime string `json:"finish_time" db:"finish_time"` - Status string `json:"status" db:"status""` + Status string `json:"status" db:"status"` Result string `json:"result" db:"result"` Message string `json:"message" db:"message"` } -func (c *controller) Diagnose(ctx context.Context, args *skoopContext.TaskConfig) (int64, error) { +func (c *controller) Diagnose(_ context.Context, args *skoopContext.TaskConfig) (int64, error) { startTime := time.Now().Format("2006-01-02 15:04:05") data, _ := json.Marshal(args) task := DiagnoseTaskResult{TaskConfig: string(data), StartTime: startTime, Status: "running"} @@ -48,7 +49,7 @@ func (c *controller) Diagnose(ctx context.Context, args *skoopContext.TaskConfig return task.TaskID, nil } -func (c *controller) DiagnoseList(ctx context.Context) ([]DiagnoseTaskResult, error) { +func (c *controller) DiagnoseList(_ context.Context) ([]DiagnoseTaskResult, error) { //TODO paging, do not list all at once taskSlice, err := listTasks() if err != nil { @@ -82,7 +83,10 @@ func listTasks() ([]DiagnoseTaskResult, error) { var ret []DiagnoseTaskResult for rows.Next() { result := DiagnoseTaskResult{} - rows.StructScan(&result) + err = rows.StructScan(&result) + if err != nil { + return nil, err + } ret = append(ret, result) } return ret, nil diff --git a/pkg/controller/service/event.go b/pkg/controller/service/event.go index 70b9b5f3..78d570ee 100644 --- a/pkg/controller/service/event.go +++ b/pkg/controller/service/event.go @@ -3,11 +3,12 @@ package service import ( "context" "fmt" - "github.com/alibaba/kubeskoop/pkg/exporter/loki" - "github.com/alibaba/kubeskoop/pkg/exporter/probe" - jsoniter "github.com/json-iterator/go" "strings" "time" + + lokiwrapper "github.com/alibaba/kubeskoop/pkg/exporter/loki" + "github.com/alibaba/kubeskoop/pkg/exporter/probe" + jsoniter "github.com/json-iterator/go" ) type Event struct { diff --git a/pkg/controller/service/pingmesh.go b/pkg/controller/service/pingmesh.go index 279a0759..506f926c 100644 --- a/pkg/controller/service/pingmesh.go +++ b/pkg/controller/service/pingmesh.go @@ -3,11 +3,12 @@ package service import ( "context" "fmt" - "github.com/alibaba/kubeskoop/pkg/controller/rpc" - log "github.com/sirupsen/logrus" "strconv" "sync" "time" + + "github.com/alibaba/kubeskoop/pkg/controller/rpc" + log "github.com/sirupsen/logrus" ) type NodeInfo struct { @@ -36,7 +37,7 @@ type PingMeshResult struct { } func (c *controller) dispatchPingTask(ctx context.Context, src, dst NodeInfo, taskGroup *sync.WaitGroup, latencyResult chan<- *Latency) error { - taskId := strconv.Itoa(int(getTaskIdx())) + taskID := strconv.Itoa(int(getTaskIdx())) pingInfo := &rpc.PingInfo{} var err error switch src.Type { @@ -67,7 +68,7 @@ func (c *controller) dispatchPingTask(ctx context.Context, src, dst NodeInfo, ta _, err = c.commitTask(src.Nodename, &rpc.Task{ Type: rpc.TaskType_Ping, - Id: taskId, + Id: taskID, TaskInfo: &rpc.Task_Ping{ Ping: pingInfo, }, @@ -78,8 +79,8 @@ func (c *controller) dispatchPingTask(ctx context.Context, src, dst NodeInfo, ta taskGroup.Add(1) go func() { defer taskGroup.Done() - result, err := c.waitTaskResult(ctx, taskId) - if err != nil || result.Success == false { + result, err := c.waitTaskResult(ctx, taskID) + if err != nil || !result.Success { if err != nil { log.Errorf("wait task result error: %v", err) } else { diff --git a/pkg/controller/service/prometheus.go b/pkg/controller/service/prometheus.go index 16b3ebc5..509f1eb4 100644 --- a/pkg/controller/service/prometheus.go +++ b/pkg/controller/service/prometheus.go @@ -3,9 +3,10 @@ package service import ( "context" "errors" + "time" + promv1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/prometheus/common/model" - "time" ) func (c *controller) QueryPrometheus(ctx context.Context, query string, ts time.Time) (model.Value, promv1.Warnings, error) { diff --git a/pkg/controller/service/utils.go b/pkg/controller/service/utils.go index 6bb2b945..058137c5 100644 --- a/pkg/controller/service/utils.go +++ b/pkg/controller/service/utils.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "github.com/alibaba/kubeskoop/pkg/controller/rpc" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/exporter/cmd/server.go b/pkg/exporter/cmd/server.go index 1cf90437..4e087109 100644 --- a/pkg/exporter/cmd/server.go +++ b/pkg/exporter/cmd/server.go @@ -7,7 +7,6 @@ import ( "context" "encoding/json" "fmt" - task_agent "github.com/alibaba/kubeskoop/pkg/exporter/task-agent" "net/http" "os" "os/signal" @@ -15,6 +14,8 @@ import ( "sync" "syscall" + task_agent "github.com/alibaba/kubeskoop/pkg/exporter/task-agent" + "github.com/alibaba/kubeskoop/pkg/exporter/sink" "github.com/fsnotify/fsnotify" diff --git a/pkg/exporter/loki/client.go b/pkg/exporter/loki/client.go index 4b074841..f3263591 100644 --- a/pkg/exporter/loki/client.go +++ b/pkg/exporter/loki/client.go @@ -3,13 +3,14 @@ package lokiwrapper import ( "bytes" "fmt" - log "github.com/sirupsen/logrus" "io" "net" "net/http" "sync" "time" + log "github.com/sirupsen/logrus" + inspproto "github.com/alibaba/kubeskoop/pkg/exporter/probe" "github.com/alibaba/kubeskoop/pkg/exporter/loki/logproto" @@ -178,36 +179,36 @@ func (i *Ingester) send(entries []*logproto.Entry) { buf = snappy.Encode(nil, buf) - resp, body, err := i.client.sendJSONReq("POST", i.PushURL, "application/x-protobuf", buf) + status, body, err := i.client.sendJSONReq("POST", i.PushURL, "application/x-protobuf", buf) if err != nil { log.Warn("loki ingester request error", "err", err) return } - if resp.StatusCode != 204 { - log.Warn("loki ingester response error", "status", resp.StatusCode, "body", body) + if status != 204 { + log.Warn("loki ingester response error", "status", status, "body", body) return } } -func (client *httpClient) sendJSONReq(method, url string, ctype string, reqBody []byte) (resp *http.Response, resBody []byte, err error) { +func (client *httpClient) sendJSONReq(method, url string, ctype string, reqBody []byte) (int, []byte, error) { req, err := http.NewRequest(method, url, bytes.NewBuffer(reqBody)) if err != nil { - return nil, nil, err + return 0, nil, err } req.Header.Set("Content-Type", ctype) - resp, err = client.parent.Do(req) + resp, err := client.parent.Do(req) if err != nil { - return nil, nil, err + return 0, nil, err } defer resp.Body.Close() - resBody, err = io.ReadAll(resp.Body) + resBody, err := io.ReadAll(resp.Body) if err != nil { - return nil, nil, err + return 0, nil, err } - return resp, resBody, nil + return resp.StatusCode, resBody, nil } diff --git a/pkg/exporter/loki/query.go b/pkg/exporter/loki/query.go index 1b791cbb..c7c65f1c 100644 --- a/pkg/exporter/loki/query.go +++ b/pkg/exporter/loki/query.go @@ -13,7 +13,6 @@ import ( const ( queryPath = "/loki/api/v1/query" queryRangePath = "/loki/api/v1/query_range" - tailPath = "/loki/api/v1/tail" ) type Client struct { @@ -99,7 +98,7 @@ func (i *Client) doQuery(ctx context.Context, path string, values url.Values) (* return nil, err } - req, err := http.NewRequest(http.MethodGet, u.String(), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) if err != nil { return nil, err } diff --git a/pkg/exporter/nettop/interface.go b/pkg/exporter/nettop/interface.go index 6ff2437a..147498bd 100644 --- a/pkg/exporter/nettop/interface.go +++ b/pkg/exporter/nettop/interface.go @@ -2,9 +2,10 @@ package nettop import ( "fmt" + "os" + "github.com/vishvananda/netlink" "golang.org/x/exp/slices" - "os" ) var ( diff --git a/pkg/exporter/probe/info/metrics.go b/pkg/exporter/probe/info/metrics.go index 1240e1c3..5428e741 100644 --- a/pkg/exporter/probe/info/metrics.go +++ b/pkg/exporter/probe/info/metrics.go @@ -2,6 +2,7 @@ package info import ( "context" + "github.com/alibaba/kubeskoop/pkg/exporter/nettop" "github.com/alibaba/kubeskoop/pkg/exporter/probe" "github.com/prometheus/client_golang/prometheus" @@ -63,11 +64,11 @@ func (m *metricsProbe) collectOnce(emit probe.Emit) error { return nil } -func (m *metricsProbe) Start(ctx context.Context) error { +func (m *metricsProbe) Start(_ context.Context) error { return nil } -func (m *metricsProbe) Stop(ctx context.Context) error { +func (m *metricsProbe) Stop(_ context.Context) error { return nil } diff --git a/pkg/exporter/sink/loki.go b/pkg/exporter/sink/loki.go index 9a795139..12a6a3d0 100644 --- a/pkg/exporter/sink/loki.go +++ b/pkg/exporter/sink/loki.go @@ -3,9 +3,8 @@ package sink import ( "encoding/json" "fmt" + lokiwrapper "github.com/alibaba/kubeskoop/pkg/exporter/loki" - "net/url" - "strings" "github.com/alibaba/kubeskoop/pkg/exporter/probe" ) @@ -20,26 +19,6 @@ func NewLokiSink(addr string, node string) (*LokiSink, error) { }, nil } -func buildURL(addr string) (string, error) { - if !strings.HasPrefix(addr, "http://") || !strings.HasPrefix(addr, "https://") { - addr = "http://" + addr - } - u, err := url.Parse(addr) - if err != nil { - return "", err - } - - if u.Path == "" { - u.Path = "/api/prom/push" - } - - if u.Port() == "" { - u.Host = fmt.Sprintf("%s:%s", u.Hostname(), "3100") - } - - return u.String(), nil -} - type LokiSink struct { client *lokiwrapper.Ingester } diff --git a/pkg/exporter/task-agent/agent.go b/pkg/exporter/task-agent/agent.go index a1c76208..24f0753e 100644 --- a/pkg/exporter/task-agent/agent.go +++ b/pkg/exporter/task-agent/agent.go @@ -1,14 +1,17 @@ -package task_agent +package taskagent import ( "context" "fmt" + "os" + "time" + + "google.golang.org/grpc/credentials/insecure" + "github.com/alibaba/kubeskoop/pkg/controller/rpc" "github.com/alibaba/kubeskoop/pkg/exporter/nettop" log "github.com/sirupsen/logrus" "google.golang.org/grpc" - "os" - "time" ) var ( @@ -29,7 +32,8 @@ type Agent struct { func (a *Agent) Run() error { var opts []grpc.CallOption opts = append(opts, grpc.MaxCallSendMsgSize(102*1024*1024)) - conn, err := grpc.Dial(controllerAddr, grpc.WithDefaultCallOptions(opts...), grpc.WithInsecure()) + conn, err := grpc.Dial(controllerAddr, grpc.WithDefaultCallOptions(opts...), + grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return fmt.Errorf("failed to connect: %v", err) } @@ -43,7 +47,8 @@ func (a *Agent) Run() error { } reconn := func() { time.Sleep(1 * time.Second) - conn, err = grpc.Dial(controllerAddr, grpc.WithDefaultCallOptions(opts...), grpc.WithInsecure()) + conn, err = grpc.Dial(controllerAddr, grpc.WithDefaultCallOptions(opts...), + grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Errorf("failed to connect: %v", err) return @@ -73,7 +78,11 @@ func (a *Agent) Run() error { reconn() continue } - a.ProcessTasks(task) + err = a.ProcessTasks(task) + if err != nil { + log.Errorf("failed to process task: %v", err) + continue + } } } }() @@ -84,10 +93,20 @@ func (a *Agent) ProcessTasks(task *rpc.ServerTask) error { log.Infof("process task: %v", task) switch task.GetTask().GetType() { case rpc.TaskType_Capture: - go a.ProcessCapture(task) + go func() { + err := a.ProcessCapture(task) + if err != nil { + log.Errorf("failed to process capture: %v", err) + } + }() return nil case rpc.TaskType_Ping: - go a.ProcessPing(task) + go func() { + err := a.ProcessPing(task) + if err != nil { + log.Errorf("failed to process ping: %v", err) + } + }() return nil } return nil diff --git a/pkg/exporter/task-agent/capture.go b/pkg/exporter/task-agent/capture.go index 0aa09093..e805cfc0 100644 --- a/pkg/exporter/task-agent/capture.go +++ b/pkg/exporter/task-agent/capture.go @@ -1,18 +1,19 @@ -package task_agent +package taskagent import ( "context" "fmt" - "github.com/alibaba/kubeskoop/pkg/controller/rpc" - "github.com/alibaba/kubeskoop/pkg/exporter/nettop" - "github.com/samber/lo" - log "github.com/sirupsen/logrus" - "golang.org/x/sync/errgroup" "os" "os/exec" "strings" "syscall" "time" + + "github.com/alibaba/kubeskoop/pkg/controller/rpc" + "github.com/alibaba/kubeskoop/pkg/exporter/nettop" + "github.com/samber/lo" + log "github.com/sirupsen/logrus" + "golang.org/x/sync/errgroup" ) const ( @@ -21,7 +22,6 @@ const ( ) type capture struct { - netns string captureCommand string captureFile string timeout time.Duration @@ -48,16 +48,17 @@ func (a *Agent) generateCaptures(id string, task *rpc.CaptureInfo) ([]capture, e }, } return files, nil - } else { - file := fmt.Sprintf("/tmp/%s_%s_host.pcap", id, task.Node.Name) - return []capture{ - { - captureCommand: fmt.Sprintf(dumpCommand, "", file, task.GetFilter()), - captureFile: file, - timeout: time.Duration(task.CaptureDurationSeconds) * time.Second, - }, - }, nil } + + file := fmt.Sprintf("/tmp/%s_%s_host.pcap", id, task.Node.Name) + return []capture{ + { + captureCommand: fmt.Sprintf(dumpCommand, "", file, task.GetFilter()), + captureFile: file, + timeout: time.Duration(task.CaptureDurationSeconds) * time.Second, + }, + }, nil + } func (a *Agent) execute(captures []capture) (string, []byte, error) { @@ -75,7 +76,7 @@ func (a *Agent) execute(captures []capture) (string, []byte, error) { output, err = cmd.CombinedOutput() }() time.Sleep(task.timeout) - cmd.Process.Signal(syscall.SIGTERM) + _ = cmd.Process.Signal(syscall.SIGTERM) time.Sleep(1 * time.Second) if err != nil { if strings.Contains(err.Error(), "no child processes") { diff --git a/pkg/exporter/task-agent/ping.go b/pkg/exporter/task-agent/ping.go index 6f764688..889bb381 100644 --- a/pkg/exporter/task-agent/ping.go +++ b/pkg/exporter/task-agent/ping.go @@ -1,14 +1,15 @@ -package task_agent +package taskagent import ( "context" "fmt" - "github.com/alibaba/kubeskoop/pkg/controller/rpc" - "github.com/alibaba/kubeskoop/pkg/exporter/nettop" - log "github.com/sirupsen/logrus" "os/exec" "regexp" "strconv" + + "github.com/alibaba/kubeskoop/pkg/controller/rpc" + "github.com/alibaba/kubeskoop/pkg/exporter/nettop" + log "github.com/sirupsen/logrus" ) var ( diff --git a/pkg/exporter/task-agent/ping_test.go b/pkg/exporter/task-agent/ping_test.go index 33803e36..8253dd5a 100644 --- a/pkg/exporter/task-agent/ping_test.go +++ b/pkg/exporter/task-agent/ping_test.go @@ -1,4 +1,4 @@ -package task_agent +package taskagent import "testing" diff --git a/webui/README.md b/webui/README.md deleted file mode 100644 index a3a01f61..00000000 --- a/webui/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# ice.js 3 Pro Scaffold - -## Usage - -```bash -$ npm install - -$ npm start -``` - -## Directories - -```md -. -├── README.md -├── ice.config.mts # The project config -├── package.json -├── .browserslistrc # Browsers that we support -├── public -│   ├── favicon.ico -├── src -| ├── app.ts # App entry -| ├── assets -| ├── components # Common component -| ├── document.tsx -| ├── global.css # Global style -| ├── interfaces -| ├── menuConfig.tsx # Layout menus -| ├── models -| ├── pages # Pages directory -| ├── services -| ├── store.ts # App store -| └── typings.d.ts -└── tsconfig.json -``` - -For more detail, please visit [docs](https://v3.ice.work/). diff --git a/webui/internal/config/config.go b/webui/internal/config/config.go index a6daf735..56c0d05f 100644 --- a/webui/internal/config/config.go +++ b/webui/internal/config/config.go @@ -1,9 +1,10 @@ package config import ( - "github.com/samber/lo" "log" "os" + + "github.com/samber/lo" ) var ( diff --git a/webui/internal/handler/auth.go b/webui/internal/handler/auth.go index 2e1b0300..acdf697f 100644 --- a/webui/internal/handler/auth.go +++ b/webui/internal/handler/auth.go @@ -1,10 +1,11 @@ package handler import ( + "time" + jwt "github.com/appleboy/gin-jwt/v2" "github.com/gin-gonic/gin" "github.com/kubeskoop/webconsole/internal/config" - "time" ) type loginParams struct { diff --git a/webui/internal/handler/config.go b/webui/internal/handler/config.go index b85222eb..45d512d9 100644 --- a/webui/internal/handler/config.go +++ b/webui/internal/handler/config.go @@ -1,11 +1,12 @@ package handler import ( + "net/http" + "strings" + jwt "github.com/appleboy/gin-jwt/v2" "github.com/gin-gonic/gin" "github.com/kubeskoop/webconsole/internal/service/config" - "net/http" - "strings" ) func RegisterConfigHandler(g *gin.RouterGroup, auth *jwt.GinJWTMiddleware) { diff --git a/webui/internal/handler/diagnosis.go b/webui/internal/handler/diagnosis.go index 831e4d2d..ee492da7 100644 --- a/webui/internal/handler/diagnosis.go +++ b/webui/internal/handler/diagnosis.go @@ -1,11 +1,12 @@ package handler import ( + "net/http" + "strconv" + jwt "github.com/appleboy/gin-jwt/v2" "github.com/gin-gonic/gin" "github.com/kubeskoop/webconsole/internal/service/controller" - "net/http" - "strconv" ) func RegisterDiagnosisHandler(g *gin.RouterGroup, auth *jwt.GinJWTMiddleware) { diff --git a/webui/internal/handler/proxy.go b/webui/internal/handler/proxy.go index fb7d517b..d4431cbe 100644 --- a/webui/internal/handler/proxy.go +++ b/webui/internal/handler/proxy.go @@ -1,12 +1,13 @@ package handler import ( - jwt "github.com/appleboy/gin-jwt/v2" - "github.com/gin-gonic/gin" - "github.com/kubeskoop/webconsole/internal/config" "net/http" "net/http/httputil" "net/url" + + jwt "github.com/appleboy/gin-jwt/v2" + "github.com/gin-gonic/gin" + "github.com/kubeskoop/webconsole/internal/config" ) func RegisterGrafanaProxyHandler(g *gin.RouterGroup, auth *jwt.GinJWTMiddleware) { diff --git a/webui/internal/service/config/config.go b/webui/internal/service/config/config.go index 1fad58c3..0fb47bc7 100644 --- a/webui/internal/service/config/config.go +++ b/webui/internal/service/config/config.go @@ -2,8 +2,9 @@ package config import ( "fmt" - "github.com/kubeskoop/webconsole/internal/config" "net/url" + + "github.com/kubeskoop/webconsole/internal/config" ) const ( diff --git a/webui/internal/service/controller/controller.go b/webui/internal/service/controller/controller.go index fc0269e3..8ae79f0b 100644 --- a/webui/internal/service/controller/controller.go +++ b/webui/internal/service/controller/controller.go @@ -2,9 +2,10 @@ package controller import ( "fmt" + "net/http" + "github.com/imroc/req/v3" "github.com/kubeskoop/webconsole/internal/config" - "net/http" ) const ( diff --git a/webui/package.json b/webui/package.json index ad837002..bd79cc6f 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,7 +1,8 @@ { "name": "@ice/fusion-pro-scaffold", - "version": "1.2.0", - "description": "ice.js 3 Pro 模板(基于 Fusion Design)", + "version": "1.0.0", + "license": "Apache-2.0", + "description": "KubeSkoop Web Console", "dependencies": { "@alifd/next": "^1.26.8", "@alifd/theme-design-pro": "^0.8.0", @@ -9,6 +10,7 @@ "@antv/g6-react-node": "^1.4.5", "@ice/runtime": "^1.2.7", "bizcharts": "^3.5.10", + "build-plugin-ice-i18n": "^0.2.2", "d3": "^7.8.5", "moment": "^2.28.0", "react": "^18.2.0", @@ -41,6 +43,5 @@ }, "publishConfig": { "access": "public" - }, - "repository": "git@github.com:ice-lab/react-materials.git" + } } diff --git a/webui/src/components/HeaderAvatar/index.module.css b/webui/src/components/HeaderAvatar/index.module.css index 5ddae63b..2d988e55 100644 --- a/webui/src/components/HeaderAvatar/index.module.css +++ b/webui/src/components/HeaderAvatar/index.module.css @@ -26,7 +26,7 @@ flex: 1 1 auto; align-items: flex-start; min-width: 250px; - padding: 8px 16px 4px 16px; + padding: 8px 16px 4px; font-size: 0; } diff --git a/webui/src/components/Logo/index.tsx b/webui/src/components/Logo/index.tsx index df0238c0..b6b59c4c 100644 --- a/webui/src/components/Logo/index.tsx +++ b/webui/src/components/Logo/index.tsx @@ -12,11 +12,9 @@ export interface ILogoProps { export default function Logo({ image, text, url, imageStyle, textStyle }: ILogoProps) { return ( -
- +
{image && logo} {text} -
); } diff --git a/webui/src/components/WebFrameCard/index.module.css b/webui/src/components/WebFrameCard/index.module.css index 3d42da11..0943e70e 100644 --- a/webui/src/components/WebFrameCard/index.module.css +++ b/webui/src/components/WebFrameCard/index.module.css @@ -1,17 +1,17 @@ .webFrame { - border: none; - width: 100%; - height: 80vh; - min-height: 860px; + border: none; + width: 100%; + height: 80vh; + min-height: 860px; } .cardAction { - display: flex; - justify-content: flex-end; - padding: 0; + display: flex; + justify-content: flex-end; + padding: 0; } .cardContent { - padding: 0; - margin-top: 0; + padding: 0; + margin-top: 0; } diff --git a/webui/src/components/WebFrameCard/index.tsx b/webui/src/components/WebFrameCard/index.tsx index a6887c27..dae84230 100644 --- a/webui/src/components/WebFrameCard/index.tsx +++ b/webui/src/components/WebFrameCard/index.tsx @@ -12,11 +12,6 @@ const WebFrameCard: React.FC = (props: WebFrameProps): JSX.Elemen - - - ) } diff --git a/webui/src/menuConfig.tsx b/webui/src/menuConfig.tsx index 2055ae4b..58e6d9ca 100644 --- a/webui/src/menuConfig.tsx +++ b/webui/src/menuConfig.tsx @@ -1,51 +1,50 @@ const asideMenuConfig = [ { - name: "主页", + name: "Network Graph", path: "/", }, { - name: '监控', + name: 'Monitoring', children: [ { - name: "大盘", + name: "Dashboard", path: "/monitoring/dashboard" }, { - name: "事件", + name: "Events", path: "/monitoring/events" }, { - name: "链路图", - path: "/flow" + name: "Network Graph", + path: "/monitoring/flow" } ] }, { - name: '诊断', + name: 'Diagnosis', children: [ { - name: "连通性诊断", + name: "Connectivity Diagnosis", path: "/diagnosis", }, { - name: "抓包", + name: "Packet Capturing", path: "/capture" }, { - name: "延迟探测(PingMesh)", + name: "Latency Detection", path: "/pingmesh" } ] }, { - name: '配置', + name: 'Configuration', children: [ { - name: '节点配置', + name: 'Node Configuration', path: '/config', } ], }, ]; - export { asideMenuConfig }; diff --git a/webui/src/pages/$.tsx b/webui/src/pages/$.tsx index 305bb88b..3030bba2 100644 --- a/webui/src/pages/$.tsx +++ b/webui/src/pages/$.tsx @@ -9,23 +9,11 @@ const { Cell } = ResponsiveGrid; const FeedbackNotFound = () => { return ( - - - - diff --git a/webui/src/pages/capture/components/captureForm/index.module.css b/webui/src/pages/capture/components/captureForm/index.module.css index 311da97f..d65d270c 100644 --- a/webui/src/pages/capture/components/captureForm/index.module.css +++ b/webui/src/pages/capture/components/captureForm/index.module.css @@ -1,8 +1,8 @@ .btn { - margin-left: 5px; + margin-left: 5px; } .custom { - border: 1px dashed; - padding: 4px; - display: inline-block; + border: 1px dashed; + padding: 4px; + display: inline-block; } diff --git a/webui/src/pages/capture/components/captureForm/index.tsx b/webui/src/pages/capture/components/captureForm/index.tsx index 79466ca3..19832bfd 100644 --- a/webui/src/pages/capture/components/captureForm/index.tsx +++ b/webui/src/pages/capture/components/captureForm/index.tsx @@ -1,5 +1,5 @@ -import {Form, Input, Select, Radio, Checkbox, TimePicker, Button, Message} from '@alifd/next'; -import {useEffect, useState} from "react"; +import { Form, Input, Select, Radio, Checkbox, TimePicker, Button, Message } from '@alifd/next'; +import { useEffect, useState } from "react"; import styles from "./index.module.css" import moment from 'moment'; import k8sService from "@/services/k8s"; @@ -17,17 +17,15 @@ interface CaptureFormData { const CaptureForm: React.FunctionComponent = (props: CaptureFormProps) => { const { onSubmit } = props; - const [formCaptureType, setformCaptureType] = useState("Pod") - const [formNamespace, setformNamespace] = useState("") - const [showSelectorDialog, setshowSelectorDialog] = useState(false) + const [showSelectorDialog, setShowSelectorDialog] = useState(false) const [capturelist, setCapturelist] = useState([]) const handleSubmit = (values: CaptureFormData, errors: any) => { if (errors) { return } - if(capturelist.length == 0) { - Message.error("未选择抓包对象") + if (capturelist.length == 0) { + Message.error("Please select at least one target.") return } values["capture_list"] = capturelist @@ -38,49 +36,49 @@ const CaptureForm: React.FunctionComponent = (props: CaptureFo return (
- +
{capturelist.map((v, i) => { - if(v.type == "Node") { + if (v.type == "Node") { return ; } else { - return ; + return ; } })} - - { - let toAdd = [] - skip: for(const v of value.values()) { - for(const c of capturelist.values()) { - if(v.name == c.name) { - continue skip - } - } - toAdd = [...toAdd, v] - } - setCapturelist([...capturelist, ...toAdd]) - setshowSelectorDialog(!showSelectorDialog) - }} - onClose={()=>{setshowSelectorDialog(!showSelectorDialog)}}> + submitSelector={(value) => { + let toAdd = [] + skip: for (const v of value.values()) { + for (const c of capturelist.values()) { + if (v.name == c.name) { + continue skip + } + } + toAdd = [...toAdd, v] + } + setCapturelist([...capturelist, ...toAdd]) + setShowSelectorDialog(!showSelectorDialog) + }} + onClose={() => { setShowSelectorDialog(!showSelectorDialog) }}>
-
- - +
+ + -
- +
+ - 发起抓包任务 + Submit Task diff --git a/webui/src/pages/capture/components/captureForm/selectorDialog.tsx b/webui/src/pages/capture/components/captureForm/selectorDialog.tsx index 359645ab..d647182d 100644 --- a/webui/src/pages/capture/components/captureForm/selectorDialog.tsx +++ b/webui/src/pages/capture/components/captureForm/selectorDialog.tsx @@ -141,14 +141,14 @@ const SelectorDialog: React.FunctionComponent = (props: SelectorP return ( props.submitSelector(selectedResult())} >
- + = (props: SelectorP
- + {setcaptureSelectorType(value); setformNamespace(""); setformName(""); filterCaptureObject(formCaptureType)}} > - 指定对象 - LabelSelector + Namespace & Name + Label Selector {formCaptureType == "Pod" && - `${item.name}`} valueRender={(item) => `${item.name}`} @@ -196,7 +196,7 @@ const SelectorDialog: React.FunctionComponent = (props: SelectorP } {formCaptureType == "Pod" && - + {setcapturePodsNodes(!capturePodsNodes); }} /> } diff --git a/webui/src/pages/capture/components/captureResult/index.tsx b/webui/src/pages/capture/components/captureResult/index.tsx index 1b7a08da..f5c68618 100644 --- a/webui/src/pages/capture/components/captureResult/index.tsx +++ b/webui/src/pages/capture/components/captureResult/index.tsx @@ -1,8 +1,5 @@ -import {Button, Table, Icon, Message} from '@alifd/next'; -import {useEffect, useState} from "react"; -import moment from 'moment'; +import {Table} from '@alifd/next'; import {CaptureResult} from "@/services/capture"; -import captureService from "@/services/capture"; import {requestConfig} from "@/app"; diff --git a/webui/src/pages/capture/index.tsx b/webui/src/pages/capture/index.tsx index 6422fc17..40f4687a 100644 --- a/webui/src/pages/capture/index.tsx +++ b/webui/src/pages/capture/index.tsx @@ -17,11 +17,11 @@ const submitCapture = (props, callback) => { captureService.createCapture(task) .then(res => { - Message.success('诊断提交成功') + Message.success('Capture task submitted.') callback() }) .catch(err => { - Message.error(`Error when submitting diagnosis: ${getErrorMessage(err)}`) + Message.error(`Error when submitting capture task: ${getErrorMessage(err)}`) }) } @@ -60,15 +60,15 @@ export default function Capture() { return (
- + submitCapture(props, refreshCaptureList)} /> - + diff --git a/webui/src/pages/config/components/AddDialog/index.module.css b/webui/src/pages/config/components/AddDialog/index.module.css index 3282e137..e4f64dd8 100644 --- a/webui/src/pages/config/components/AddDialog/index.module.css +++ b/webui/src/pages/config/components/AddDialog/index.module.css @@ -1,9 +1,9 @@ .box { - display: flex; - align-items: center; - margin-bottom: 20px; + display: flex; + align-items: center; + margin-bottom: 20px; - span { - margin-right: 10px; - } + span { + margin-right: 10px; + } } diff --git a/webui/src/pages/config/components/AddDialog/index.tsx b/webui/src/pages/config/components/AddDialog/index.tsx index af5940bb..a3263c29 100644 --- a/webui/src/pages/config/components/AddDialog/index.tsx +++ b/webui/src/pages/config/components/AddDialog/index.tsx @@ -37,7 +37,7 @@ const LokiArgs: React.FC = (props: LokiArgsProps): JSX.Element => return (
- 地址 + Address
@@ -50,11 +50,11 @@ const AddDialog: React.FC = (props: AddDialogProps): JSX.Element const [args, setArgs] = useState(undefined); const verifyInput = (): boolean => { if (selection === '') { - Message.error('请输入名称'); + Message.error('Please enter name.'); return false; } if (props.type === 'event_sink' && selection === 'loki' && _.isEmpty(args?.addr)) { - Message.error('请输入地址'); + Message.error('Please enter address.'); return false; } return true; @@ -72,14 +72,14 @@ const AddDialog: React.FC = (props: AddDialogProps): JSX.Element return props.onCancel()} onClose={() => props.onCancel()} > - 名称 + Name { props.autoComplete ? deleteItem(type, index)} > - 删除 + Delete
) @@ -66,13 +66,16 @@ export default function Config() { const showAddItemDialog = (type: string) => { switch (type) { case METRIC_PROBE: - setSelectableItems(probeTypes.metric_probe); + const enabledMetricProbes = extractMetricProbes(exporterConfig)?.map(p => p.name); + setSelectableItems(probeTypes.metric_probe.filter(i => !enabledMetricProbes.includes(i.name))); break; case EVENT_PROBE: - setSelectableItems(probeTypes.event_probe); + const enabledEventProbes = extractEventProbes(exporterConfig)?.map(p => p.name); + setSelectableItems(probeTypes.event_probe.filter(i => !enabledEventProbes.includes(i.name))); break; case EVENT_SINK: - setSelectableItems(probeTypes.event_sink); + const enabledEventSinks = extractEventSinks(exporterConfig)?.map(p => p.name); + setSelectableItems(probeTypes.event_sink.filter(i => !enabledEventSinks.includes(i.name))); break; } setDialogType(type); @@ -88,7 +91,7 @@ export default function Config() { newConfig.metrics.probes = []; } if (newConfig.metrics?.probes.find(p => p.name === selection.name)) { - Message.error(`指标探针 ${selection} 已存在!`) + Message.error(`Metric probe \"${selection.name}\" has already existed!`) return } newConfig.metrics?.probes?.push({ ...selection }); @@ -98,7 +101,7 @@ export default function Config() { newConfig.event.probes = []; } if (newConfig.event?.probes.find(p => p.name === selection.name)) { - Message.error(`事件探针 ${selection} 已存在!`) + Message.error(`Event probe \"${selection.name}\" has already existed!`) return } newConfig.event?.probes?.push({ ...selection }); @@ -108,7 +111,7 @@ export default function Config() { newConfig.event.sinks = []; } if (newConfig.event?.sinks.find(p => p.name === selection.name)) { - Message.error(`事件投递 ${selection.name} 已存在!`) + Message.error(`Event sink \"${selection.name}\" has already existed!`) return } newConfig.event?.sinks?.push({ ...selection }); @@ -125,53 +128,53 @@ export default function Config() { const saveConfig = () => { console.log(exporterConfig) configService.updateExporterConfig(exporterConfig!).then(() => { - Message.success('配置保存成功') + Message.success('Configuration saved.') setConfigChanged(false); }).catch(e => { - Message.error(`配置保存失败: ${getErrorMessage(e)}`) + Message.error(`Error when saving configuration: ${getErrorMessage(e)}`) }) } return (
- +
- +
- - _.isEmpty(v) ? '-' : JSON.stringify(v)} /> - generateActions('metric_probe', i)} /> + + _.isEmpty(v) ? '-' : JSON.stringify(v)} /> + generateActions(METRIC_PROBE, i)} />
- +
- +
- - _.isEmpty(v) ? '-' : JSON.stringify(v)} /> - generateActions('event_probe', i)} /> + + _.isEmpty(v) ? '-' : JSON.stringify(v)} /> + generateActions(EVENT_PROBE, i)} />
- +
- +
- - _.isEmpty(v) ? '-' : JSON.stringify(v)} /> - generateActions('event_sink', i)} /> + + _.isEmpty(v) ? '-' : JSON.stringify(v)} /> + generateActions(EVENT_SINK, i)} />
- +
diff --git a/webui/src/pages/diagnosis/components/DiagnosisForm/index.tsx b/webui/src/pages/diagnosis/components/DiagnosisForm/index.tsx index 3023eef0..8a722312 100644 --- a/webui/src/pages/diagnosis/components/DiagnosisForm/index.tsx +++ b/webui/src/pages/diagnosis/components/DiagnosisForm/index.tsx @@ -20,16 +20,16 @@ const DiagnosisForm: React.FunctionComponent = (props: Diagn }; return ( - - + + - - + + - + - + + + - - + + @@ -113,7 +113,7 @@ const LoginBlock: FunctionComponent = ( className={styles.submitBtn} validate > - 登录 + Login diff --git a/webui/src/pages/login/index.tsx b/webui/src/pages/login/index.tsx index acac3c7c..9619efd7 100644 --- a/webui/src/pages/login/index.tsx +++ b/webui/src/pages/login/index.tsx @@ -21,7 +21,7 @@ const Login: React.FC = () => { export const pageConfig = definePageConfig(() => { return { - title: '登录', + title: 'Login', }; }); diff --git a/webui/src/pages/monitoring/dashboard/index.tsx b/webui/src/pages/monitoring/dashboard/index.tsx index 117107c7..23b9d44c 100644 --- a/webui/src/pages/monitoring/dashboard/index.tsx +++ b/webui/src/pages/monitoring/dashboard/index.tsx @@ -2,11 +2,10 @@ import PageHeader from '@/components/PageHeader'; import WebFrameCard from '@/components/WebFrameCard'; import { useEffect, useState } from 'react'; import Exception from '@/components/Exception'; -import { Button, Loading, Message } from '@alifd/next'; +import { Loading, Message } from '@alifd/next'; import store from '@/store' export default function Dashboard() { - const [visible, setVisible] = useState(false); const [loading, setLoading] = useState(true) const [dashboardConfig, dashboardConfigDispatcher] = store.useModel('dashboard'); @@ -36,16 +35,16 @@ export default function Dashboard() { return (
{dashboardConfig.metrics_url ? (
- setVisible(true)} /> +
) : ( - setVisible(true)}>配置}/> + )}
diff --git a/webui/src/pages/monitoring/events/components/EventList/index.module.css b/webui/src/pages/monitoring/events/components/EventList/index.module.css index d68884b9..3626a9d2 100644 --- a/webui/src/pages/monitoring/events/components/EventList/index.module.css +++ b/webui/src/pages/monitoring/events/components/EventList/index.module.css @@ -1,32 +1,32 @@ .eventItem { - background-color: rgb(235, 245, 255); - font-size: 15px; - display: flex; - align-items: center; - height: 4em; - margin-bottom: 10px; + background-color: rgb(235, 245, 255); + font-size: 15px; + display: flex; + align-items: center; + height: 4em; + margin-bottom: 10px; } .eventInfo { - margin-right: 20px; + margin-right: 20px; } .eventMessage { } .eventType { - color: orangered; + color: orangered; } .tag { - margin-right: 10px; + margin-right: 10px; } .bar { - height: 100%; - width: 3px; - margin-right: 10px; - background-color: #0070cc; + height: 100%; + width: 3px; + margin-right: 10px; + background-color: #0070cc; } diff --git a/webui/src/pages/monitoring/events/components/EventList/index.tsx b/webui/src/pages/monitoring/events/components/EventList/index.tsx index cb9a0afa..be74f423 100644 --- a/webui/src/pages/monitoring/events/components/EventList/index.tsx +++ b/webui/src/pages/monitoring/events/components/EventList/index.tsx @@ -6,11 +6,11 @@ interface EventListProps { data: EventData[] }; -const renderListItem = (ev: EventData): JSX.Element => { +const renderListItem = (ev: EventData, i: number): JSX.Element => { // convert nanosecond timestamp to date const date = new Date(ev.timestamp / 1000000); return ( -
+
{date.toISOString()}
@@ -18,7 +18,7 @@ const renderListItem = (ev: EventData): JSX.Element => {
- {ev.labels.map(i => {`${i.name}: ${i.value}`})} + {ev.labels.map(i => {`${i.name}: ${i.value}`})}
{ev.msg}
diff --git a/webui/src/pages/monitoring/events/index.module.css b/webui/src/pages/monitoring/events/index.module.css index 646ed091..3f3efb85 100644 --- a/webui/src/pages/monitoring/events/index.module.css +++ b/webui/src/pages/monitoring/events/index.module.css @@ -1,22 +1,22 @@ .title:first-child { - margin-left: 0; + margin-left: 0; } .title { - margin-right: 10px; - margin-left: 20px; + margin-right: 10px; + margin-left: 20px; } .box { - display: flex; - align-items: center; - margin: 20px 0; + display: flex; + align-items: center; + margin: 20px 0; } .btn { - margin: 0 5px; + margin: 0 5px; } .select { - min-width: 200px; + min-width: 200px; } diff --git a/webui/src/pages/monitoring/events/index.tsx b/webui/src/pages/monitoring/events/index.tsx index 4c605d23..399277c6 100644 --- a/webui/src/pages/monitoring/events/index.tsx +++ b/webui/src/pages/monitoring/events/index.tsx @@ -40,7 +40,7 @@ export default function Events() { setEventData(res || []) if (setLoading) setIsLoading(false); }).catch((res) => { - Message.error(`获取事件信息失败:${getErrorMessage(res)}`) + Message.error(`Error fetching events: ${getErrorMessage(res)}`) }); }; @@ -48,19 +48,19 @@ export default function Events() { k8sService.listNodes().then((res) => { setNodes(res) }).catch((res) => { - Message.error(`获取节点信息失败:${getErrorMessage(res)}`) + Message.error(`Error fetching node info: ${getErrorMessage(res)}`) } ); k8sService.listNamespace().then((res) => { setNamespaces(res) }).catch((res) => { - Message.error(`获取命名空间信息失败:${getErrorMessage(res)}`) + Message.error(`Error fetching namespace info: ${getErrorMessage(res)}`) } ); k8sService.listPods().then((res) => { setPods(res) }).catch((res) => { - Message.error(`获取Pod信息失败:${getErrorMessage(res)}`) + Message.error(`Error fetching pod info: ${getErrorMessage(res)}`) } ); } @@ -100,23 +100,23 @@ export default function Events() { return (
- + - 时间范围 + Time Range setTimeRange(v)} /> - 事件类型 + Event Type setFilteredNodes(v)} disabled={isLive} /> - 命名空间 + Namespaces setFilteredPods(v)} disabled={isLive} />
{ isLive ? - : - + : + }
- + diff --git a/webui/src/pages/flow/components/FlowGraph/index.tsx b/webui/src/pages/monitoring/flow/components/FlowGraph/index.tsx similarity index 100% rename from webui/src/pages/flow/components/FlowGraph/index.tsx rename to webui/src/pages/monitoring/flow/components/FlowGraph/index.tsx diff --git a/webui/src/pages/monitoring/flow/components/FlowTable/index.module.css b/webui/src/pages/monitoring/flow/components/FlowTable/index.module.css new file mode 100644 index 00000000..83c7f3a3 --- /dev/null +++ b/webui/src/pages/monitoring/flow/components/FlowTable/index.module.css @@ -0,0 +1,6 @@ +.tableCell { + td div { + padding-top: 8px !important; + padding-bottom: 8px !important; + } +} diff --git a/webui/src/pages/flow/components/FlowTable/index.tsx b/webui/src/pages/monitoring/flow/components/FlowTable/index.tsx similarity index 92% rename from webui/src/pages/flow/components/FlowTable/index.tsx rename to webui/src/pages/monitoring/flow/components/FlowTable/index.tsx index 44355755..d33cf0c2 100644 --- a/webui/src/pages/flow/components/FlowTable/index.tsx +++ b/webui/src/pages/monitoring/flow/components/FlowTable/index.tsx @@ -8,33 +8,33 @@ interface FlowTableProps { const columns = [ { - title: '源', + title: 'Source', dataIndex: 'srcName', }, { - title: '源地址', + title: 'Source Address', dataIndex: 'srcAddr', }, { - title: '目的', + title: 'Destination', dataIndex: 'dstName', }, { - title: '目的地址', + title: 'Destination Address', dataIndex: 'dstAddr', }, { - title: '协议', + title: 'Protocol', dataIndex: 'protocol', }, { - title: '字节数', + title: 'Bytes', dataIndex: 'bytes', sortable: true, sortDirections: ["desc", "asc"], }, { - title: '数据包数', + title: 'Packets', dataIndex: 'packets', sortable: true, sortDirections: ["desc", "asc"], @@ -119,7 +119,7 @@ const FlowTable: React.FC = (props: FlowTableProps): JSX.Element current={currentPage} pageSize={pageSize} total={data.length} - totalRender={total => `总数:${total}`} + totalRender={total => `Total:${total}`} style={{ marginTop: 16, textAlign: 'right' }} onChange={onPageChange} /> diff --git a/webui/src/pages/monitoring/flow/index.module.css b/webui/src/pages/monitoring/flow/index.module.css new file mode 100644 index 00000000..bc4840c1 --- /dev/null +++ b/webui/src/pages/monitoring/flow/index.module.css @@ -0,0 +1,10 @@ + +.contentBox { + margin-bottom: 10px; +} + +.optionLabel { + display: flex; + align-items: center; + margin-right: 10px; +} diff --git a/webui/src/pages/flow/index.tsx b/webui/src/pages/monitoring/flow/index.tsx similarity index 87% rename from webui/src/pages/flow/index.tsx rename to webui/src/pages/monitoring/flow/index.tsx index 79237d40..aa345384 100644 --- a/webui/src/pages/flow/index.tsx +++ b/webui/src/pages/monitoring/flow/index.tsx @@ -22,7 +22,7 @@ const filterFlowData = (data: FlowData, namespaces: string[], nodes: string[], s return !namespaces || node.type != 'pod' || namespaces.includes(node.namespace) }) .filter((node: any) => { - return !nodes || node.type == 'external' || nodes.includes(node.nodeName) + return !node.length || node.type == 'external' || nodes.includes(node.nodeName) }) .filter((node: any) => { return showExternal || node.type !== 'external' @@ -64,7 +64,7 @@ export default function FlowDashboard() { setData(res); setLoading(false); }).catch(err => { - Message.error(`数据获取失败:${getErrorMessage(err)}`) + Message.error(`Error fetching data: ${getErrorMessage(err)}`) }); }; useEffect(() => getFlowData(true), []); @@ -88,24 +88,24 @@ export default function FlowDashboard() { } const filtered = useMemo( - () => filterFlowData(data, selectedNamespaces, null, showExternal), + () => filterFlowData(data, selectedNamespaces, [], showExternal), [data, selectedNamespaces, showExternal] ) return (
- 时间范围 + Time setTime(v)} /> - 命名空间 + Namespaces