mirror of https://github.com/dapr/cli.git
201 lines
6.8 KiB
Go
201 lines
6.8 KiB
Go
/*
|
|
Copyright 2021 The Dapr Authors
|
|
Licensed 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 standalone
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
ps "github.com/mitchellh/go-ps"
|
|
process "github.com/shirou/gopsutil/process"
|
|
|
|
"github.com/dapr/dapr/pkg/runtime"
|
|
|
|
"github.com/dapr/cli/pkg/age"
|
|
"github.com/dapr/cli/pkg/metadata"
|
|
"github.com/dapr/cli/utils"
|
|
)
|
|
|
|
// ListOutput represents the application ID, application port and creation time.
|
|
type ListOutput struct {
|
|
AppID string `csv:"APP ID" json:"appId" yaml:"appId"`
|
|
HTTPPort int `csv:"HTTP PORT" json:"httpPort" yaml:"httpPort"`
|
|
GRPCPort int `csv:"GRPC PORT" json:"grpcPort" yaml:"grpcPort"`
|
|
AppPort int `csv:"APP PORT" json:"appPort" yaml:"appPort"`
|
|
MetricsEnabled bool `csv:"-" json:"metricsEnabled" yaml:"metricsEnabled"` // Not displayed in table, consumed by dashboard.
|
|
Command string `csv:"COMMAND" json:"command" yaml:"command"`
|
|
Age string `csv:"AGE" json:"age" yaml:"age"`
|
|
Created string `csv:"CREATED" json:"created" yaml:"created"`
|
|
DaprdPID int `csv:"DAPRD PID" json:"daprdPid" yaml:"daprdPid"`
|
|
CliPID int `csv:"CLI PID" json:"cliPid" yaml:"cliPid"`
|
|
AppPID int `csv:"APP PID" json:"appPid" yaml:"appPid"`
|
|
MaxRequestBodySize int `csv:"-" json:"maxRequestBodySize" yaml:"maxRequestBodySize"` // Additional field, not displayed in table.
|
|
HTTPReadBufferSize int `csv:"-" json:"httpReadBufferSize" yaml:"httpReadBufferSize"` // Additional field, not displayed in table.
|
|
RunTemplatePath string `csv:"RUN_TEMPLATE_PATH" json:"runTemplatePath" yaml:"runTemplatePath"`
|
|
AppLogPath string `csv:"APP_LOG_PATH" json:"appLogPath" yaml:"appLogPath"`
|
|
DaprDLogPath string `csv:"DAPRD_LOG_PATH" json:"daprdLogPath" yaml:"daprdLogPath"`
|
|
RunTemplateName string `json:"runTemplateName" yaml:"runTemplateName"` // specifically omitted in csv output.
|
|
}
|
|
|
|
func (d *daprProcess) List() ([]ListOutput, error) {
|
|
return List()
|
|
}
|
|
|
|
// List outputs all the applications.
|
|
func List() ([]ListOutput, error) {
|
|
list := []ListOutput{}
|
|
|
|
processes, err := ps.Processes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Populates the map if all data is available for the sidecar.
|
|
for _, proc := range processes {
|
|
executable := strings.ToLower(proc.Executable())
|
|
if (executable == "daprd") || (executable == "daprd.exe") {
|
|
procDetails, err := process.NewProcess(int32(proc.Pid())) //nolint:gosec
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
cmdLine, err := procDetails.Cmdline()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
cmdLineItems := strings.Fields(cmdLine)
|
|
if len(cmdLineItems) <= 1 {
|
|
continue
|
|
}
|
|
|
|
// Parse command line arguments, example format for cmdLine `daprd --flag1 value1 --enable-flag2 --flag3 value3`.
|
|
argumentsMap := make(map[string]string)
|
|
for i := 1; i < len(cmdLineItems)-1; {
|
|
if !strings.HasPrefix(cmdLineItems[i+1], "--") {
|
|
argumentsMap[cmdLineItems[i]] = cmdLineItems[i+1]
|
|
i += 2
|
|
} else {
|
|
argumentsMap[cmdLineItems[i]] = ""
|
|
i++
|
|
}
|
|
}
|
|
|
|
httpPort := getIntArg(argumentsMap, "--dapr-http-port", runtime.DefaultDaprHTTPPort)
|
|
|
|
grpcPort := getIntArg(argumentsMap, "--dapr-grpc-port", runtime.DefaultDaprAPIGRPCPort)
|
|
|
|
appPort := getIntArg(argumentsMap, "--app-port", 0)
|
|
|
|
enableMetrics, err := strconv.ParseBool(argumentsMap["--enable-metrics"])
|
|
if err != nil {
|
|
// Default is true for metrics.
|
|
enableMetrics = true
|
|
}
|
|
|
|
maxRequestBodySize := getIntArg(argumentsMap, "max-body-size", runtime.DefaultMaxRequestBodySize)
|
|
|
|
httpReadBufferSize := getIntArg(argumentsMap, "read-buffer-size", runtime.DefaultReadBufferSize)
|
|
|
|
appID := argumentsMap["--app-id"]
|
|
appCmd := ""
|
|
appPIDString := ""
|
|
cliPIDString := ""
|
|
runTemplatePath := ""
|
|
appLogPath := ""
|
|
daprdLogPath := ""
|
|
runTemplateName := ""
|
|
socket := argumentsMap["--unix-domain-socket"]
|
|
appMetadata, err := metadata.Get(httpPort, appID, socket)
|
|
if err == nil {
|
|
appCmd = appMetadata.Extended["appCommand"]
|
|
appPIDString = appMetadata.Extended["appPID"]
|
|
cliPIDString = appMetadata.Extended["cliPID"]
|
|
runTemplatePath = appMetadata.Extended["runTemplatePath"]
|
|
runTemplateName = appMetadata.Extended["runTemplateName"]
|
|
appLogPath = appMetadata.Extended["appLogPath"]
|
|
daprdLogPath = appMetadata.Extended["daprdLogPath"]
|
|
}
|
|
|
|
appPID, err := strconv.Atoi(appPIDString)
|
|
if err != nil {
|
|
appPID = 0
|
|
}
|
|
|
|
// Parse functions return an error on bad input.
|
|
cliPID, err := strconv.Atoi(cliPIDString)
|
|
if err != nil {
|
|
cliPID = 0
|
|
}
|
|
|
|
daprPID := proc.Pid()
|
|
|
|
createUnixTimeMilliseconds, err := procDetails.CreateTime()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
createTime := time.Unix(createUnixTimeMilliseconds/1000, 0)
|
|
|
|
listRow := ListOutput{
|
|
Created: createTime.Format("2006-01-02 15:04.05"),
|
|
Age: age.GetAge(createTime),
|
|
DaprdPID: daprPID,
|
|
CliPID: cliPID,
|
|
AppID: appID,
|
|
AppPID: appPID,
|
|
HTTPPort: httpPort,
|
|
GRPCPort: grpcPort,
|
|
AppPort: appPort,
|
|
MetricsEnabled: enableMetrics,
|
|
Command: utils.TruncateString(appCmd, 20),
|
|
MaxRequestBodySize: maxRequestBodySize,
|
|
HTTPReadBufferSize: httpReadBufferSize,
|
|
RunTemplatePath: runTemplatePath,
|
|
RunTemplateName: runTemplateName,
|
|
AppLogPath: appLogPath,
|
|
DaprDLogPath: daprdLogPath,
|
|
}
|
|
|
|
// filter only dashboard instance.
|
|
if listRow.AppID != "" {
|
|
list = append(list, listRow)
|
|
}
|
|
}
|
|
}
|
|
|
|
return list, nil
|
|
}
|
|
|
|
// getIntArg returns the value of the argument as an integer.
|
|
// If the argument is not set, or is not an integer, it returns the default value.
|
|
func getIntArg(argMap map[string]string, argKey string, argDef int) int {
|
|
if arg, ok := argMap[argKey]; ok {
|
|
if argInt, err := strconv.Atoi(arg); err == nil {
|
|
return argInt
|
|
}
|
|
}
|
|
return argDef
|
|
}
|
|
|
|
// GetCLIPIDCountMap returns a map of CLI PIDs to number of apps started with it.
|
|
func GetCLIPIDCountMap(apps []ListOutput) map[int]int {
|
|
cliPIDCountMap := make(map[int]int, len(apps))
|
|
for _, app := range apps {
|
|
cliPIDCountMap[app.CliPID]++
|
|
}
|
|
return cliPIDCountMap
|
|
}
|