mirror of https://github.com/dapr/cli.git
Dapr stop and list changes for dapr run -f (#1169)
* dapr stop -f impl Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * add description Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * fix tests Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * fix windows failure Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * Update cmd/stop.go Co-authored-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com> Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * review comments Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * review comments Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * change cmd description Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * stop refactoring Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> * trigger pr checks Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> Signed-off-by: Pravin Pushkar <ppushkar@microsoft.com> Co-authored-by: Mukundan Sundararajan <65565396+mukundansundar@users.noreply.github.com>
This commit is contained in:
parent
61bf50cc4c
commit
14c04f9a87
|
|
@ -46,6 +46,12 @@ type daprVersion struct {
|
|||
RuntimeVersion string `json:"Runtime version"`
|
||||
}
|
||||
|
||||
type osType string
|
||||
|
||||
const (
|
||||
windowsOsType osType = "windows"
|
||||
)
|
||||
|
||||
var (
|
||||
daprVer daprVersion
|
||||
logAsJSON bool
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ dapr invoke --unix-domain-socket --app-id target --method sample --verb GET
|
|||
|
||||
// TODO(@daixiang0): add Windows support.
|
||||
if invokeSocket != "" {
|
||||
if runtime.GOOS == "windows" {
|
||||
if runtime.GOOS == string(windowsOsType) {
|
||||
print.FailureStatusEvent(os.Stderr, "The unix-domain-socket option is not supported on Windows")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ dapr publish --publish-app-id myapp --pubsub target --topic sample --data '{"key
|
|||
client := standalone.NewClient()
|
||||
// TODO(@daixiang0): add Windows support.
|
||||
if publishSocket != "" {
|
||||
if runtime.GOOS == "windows" {
|
||||
if runtime.GOOS == string(windowsOsType) {
|
||||
print.FailureStatusEvent(os.Stderr, "The unix-domain-socket option is not supported on Windows")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
|
|
|
|||
54
cmd/run.go
54
cmd/run.go
|
|
@ -18,6 +18,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -92,6 +93,12 @@ dapr run --app-id myapp --app-port 3000 --app-protocol grpc -- go run main.go
|
|||
|
||||
# Run sidecar only specifying dapr runtime installation directory
|
||||
dapr run --app-id myapp --dapr-path /usr/local/dapr
|
||||
|
||||
# Run multiple apps by providing path of a run config file
|
||||
dapr run --run-file dapr.yaml
|
||||
|
||||
# Run multiple apps by providing a directory path containing the run config file(dapr.yaml)
|
||||
dapr run --run-file /path/to/directory
|
||||
`,
|
||||
Args: cobra.MinimumNArgs(0),
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
|
|
@ -99,7 +106,7 @@ dapr run --app-id myapp --dapr-path /usr/local/dapr
|
|||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(runFilePath) > 0 {
|
||||
if runtime.GOOS == "windows" {
|
||||
if runtime.GOOS == string(windowsOsType) {
|
||||
print.FailureStatusEvent(os.Stderr, "The run command with run file is not supported on Windows")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
@ -133,7 +140,7 @@ dapr run --app-id myapp --dapr-path /usr/local/dapr
|
|||
|
||||
if unixDomainSocket != "" {
|
||||
// TODO(@daixiang0): add Windows support.
|
||||
if runtime.GOOS == "windows" {
|
||||
if runtime.GOOS == string(windowsOsType) {
|
||||
print.FailureStatusEvent(os.Stderr, "The unix-domain-socket option is not supported on Windows")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
|
|
@ -438,7 +445,7 @@ func init() {
|
|||
RunCmd.Flags().IntVar(&appHealthThreshold, "app-health-threshold", 0, "Number of consecutive failures for the app to be considered unhealthy")
|
||||
RunCmd.Flags().BoolVar(&enableAPILogging, "enable-api-logging", false, "Log API calls at INFO verbosity. Valid values are: true or false")
|
||||
RunCmd.Flags().StringVar(&apiListenAddresses, "dapr-listen-addresses", "", "Comma separated list of IP addresses that sidecar will listen to")
|
||||
RunCmd.Flags().StringVarP(&runFilePath, "run-file", "f", "", "Path to the configuration file for the apps to run")
|
||||
RunCmd.Flags().StringVarP(&runFilePath, "run-file", "f", "", "Path to the run template file for the list of apps to run")
|
||||
RootCmd.AddCommand(RunCmd)
|
||||
}
|
||||
|
||||
|
|
@ -503,11 +510,13 @@ func executeRun(runFilePath string, apps []runfileconfig.App) (bool, error) {
|
|||
runStates = append(runStates, runState)
|
||||
|
||||
// Metadata API is only available if app has started listening to port, so wait for app to start before calling metadata API.
|
||||
// The PID is put as 0, so as to not kill CLI process when any one of the apps is stopped.
|
||||
_ = putCLIProcessIDInMeta(runState, 0)
|
||||
putCLIProcessIDInMeta(runState, os.Getpid())
|
||||
|
||||
// Update extended metadata with run file path.
|
||||
putRunFilePathInMeta(runState, runFilePath)
|
||||
|
||||
if runState.AppCMD.Command != nil {
|
||||
_ = putAppCommandInMeta(runConfig, runState)
|
||||
putAppCommandInMeta(runConfig, runState)
|
||||
}
|
||||
print.StatusEvent(runState.DaprCMD.OutputWriter, print.LogSuccess, "You're up and running! Dapr logs will appear here.\n")
|
||||
logInformationalStatusToStdout(app)
|
||||
|
|
@ -885,28 +894,37 @@ func killAppProcess(runE *runExec.RunExec) error {
|
|||
}
|
||||
|
||||
// putCLIProcessIDInMeta puts the CLI process ID in metadata so that it can be used by the CLI to stop the CLI process.
|
||||
func putCLIProcessIDInMeta(runE *runExec.RunExec, pid int) error {
|
||||
// For now putting this as 0, since we do not want the dapr stop command for a single to kill the CLI process,
|
||||
// thereby killing all the apps that are running via dapr run -f.
|
||||
func putCLIProcessIDInMeta(runE *runExec.RunExec, pid int) {
|
||||
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogInfo, "Updating metadata for cliPID: %d", pid)
|
||||
err := metadata.Put(runE.DaprHTTPPort, "cliPID", strconv.Itoa(pid), runE.AppID, unixDomainSocket)
|
||||
if err != nil {
|
||||
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogWarning, "Could not update sidecar metadata for cliPID: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// putAppCommandInMeta puts the app command in metadata so that it can be used by the CLI to stop the app.
|
||||
func putAppCommandInMeta(runConfig standalone.RunConfig, runState *runExec.RunExec) error {
|
||||
func putAppCommandInMeta(runConfig standalone.RunConfig, runE *runExec.RunExec) {
|
||||
appCommand := strings.Join(runConfig.Command, " ")
|
||||
print.StatusEvent(runState.DaprCMD.OutputWriter, print.LogInfo, "Updating metadata for app command: %s", appCommand)
|
||||
err := metadata.Put(runState.DaprHTTPPort, "appCommand", appCommand, runState.AppID, runConfig.UnixDomainSocket)
|
||||
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogInfo, "Updating metadata for app command: %s", appCommand)
|
||||
err := metadata.Put(runE.DaprHTTPPort, "appCommand", appCommand, runE.AppID, runConfig.UnixDomainSocket)
|
||||
if err != nil {
|
||||
print.StatusEvent(runState.DaprCMD.OutputWriter, print.LogWarning, "Could not update sidecar metadata for appCommand: %s", err.Error())
|
||||
return err
|
||||
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogWarning, "Could not update sidecar metadata for appCommand: %s", err.Error())
|
||||
return
|
||||
}
|
||||
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogSuccess, "You're up and running! Dapr logs will appear here.\n")
|
||||
}
|
||||
|
||||
// putRunFilePathInMeta puts the absolute path of run file in metadata so that it can be used by the CLI to stop all apps started by this run file.
|
||||
func putRunFilePathInMeta(runE *runExec.RunExec, runFilePath string) {
|
||||
runFilePath, err := filepath.Abs(runFilePath)
|
||||
if err != nil {
|
||||
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogWarning, "Could not get absolute path for run file: %s", err.Error())
|
||||
return
|
||||
}
|
||||
err = metadata.Put(runE.DaprHTTPPort, "runTemplatePath", runFilePath, runE.AppID, unixDomainSocket)
|
||||
if err != nil {
|
||||
print.StatusEvent(runE.DaprCMD.OutputWriter, print.LogWarning, "Could not update sidecar metadata for runFile: %s", err.Error())
|
||||
}
|
||||
print.StatusEvent(runState.DaprCMD.OutputWriter, print.LogSuccess, "You're up and running! Dapr logs will appear here.\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// getRunFilePath returns the path to the run file.
|
||||
|
|
|
|||
45
cmd/stop.go
45
cmd/stop.go
|
|
@ -14,7 +14,10 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
|
@ -30,13 +33,44 @@ var StopCmd = &cobra.Command{
|
|||
Example: `
|
||||
# Stop Dapr application
|
||||
dapr stop --app-id <ID>
|
||||
|
||||
# Stop multiple apps by providing a run config file
|
||||
dapr stop --run-file dapr.yaml
|
||||
|
||||
# Stop multiple apps by providing a directory path containing the run config file(dapr.yaml)
|
||||
dapr stop --run-file /path/to/directory
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
if len(runFilePath) > 0 {
|
||||
if runtime.GOOS == string(windowsOsType) {
|
||||
print.FailureStatusEvent(os.Stderr, "Stop command with run file is not supported on Windows")
|
||||
os.Exit(1)
|
||||
}
|
||||
runFilePath, err = getRunFilePath(runFilePath)
|
||||
if err != nil {
|
||||
print.FailureStatusEvent(os.Stderr, "Failed to get run file path: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = executeStopWithRunFile(runFilePath)
|
||||
if err != nil {
|
||||
print.FailureStatusEvent(os.Stderr, "Failed to stop Dapr and app processes: %s", err)
|
||||
} else {
|
||||
print.SuccessStatusEvent(os.Stdout, "Dapr and app processes stopped successfully")
|
||||
}
|
||||
return
|
||||
}
|
||||
if stopAppID != "" {
|
||||
args = append(args, stopAppID)
|
||||
}
|
||||
apps, err := standalone.List()
|
||||
if err != nil {
|
||||
print.FailureStatusEvent(os.Stderr, "failed to get list of apps started by dapr : %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
cliPIDToNoOfApps := standalone.GetCLIPIDCountMap(apps)
|
||||
for _, appID := range args {
|
||||
err := standalone.Stop(appID)
|
||||
err = standalone.Stop(appID, cliPIDToNoOfApps, apps)
|
||||
if err != nil {
|
||||
print.FailureStatusEvent(os.Stderr, "failed to stop app id %s: %s", appID, err)
|
||||
} else {
|
||||
|
|
@ -48,6 +82,15 @@ dapr stop --app-id <ID>
|
|||
|
||||
func init() {
|
||||
StopCmd.Flags().StringVarP(&stopAppID, "app-id", "a", "", "The application id to be stopped")
|
||||
StopCmd.Flags().StringVarP(&runFilePath, "run-file", "f", "", "Path to the run template file for the list of apps to stop")
|
||||
StopCmd.Flags().BoolP("help", "h", false, "Print this help message")
|
||||
RootCmd.AddCommand(StopCmd)
|
||||
}
|
||||
|
||||
func executeStopWithRunFile(runFilePath string) error {
|
||||
absFilePath, err := filepath.Abs(runFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get absolute file path for %s: %w", runFilePath, err)
|
||||
}
|
||||
return standalone.StopAppsWithRunFile(absFilePath)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ type ListOutput struct {
|
|||
CliPID int `csv:"CLI PID" json:"cliPid" yaml:"cliPid"`
|
||||
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"`
|
||||
}
|
||||
|
||||
func (d *daprProcess) List() ([]ListOutput, error) {
|
||||
|
|
@ -99,11 +100,13 @@ func List() ([]ListOutput, error) {
|
|||
appID := argumentsMap["--app-id"]
|
||||
appCmd := ""
|
||||
cliPIDString := ""
|
||||
runTemplatePath := ""
|
||||
socket := argumentsMap["--unix-domain-socket"]
|
||||
appMetadata, err := metadata.Get(httpPort, appID, socket)
|
||||
if err == nil {
|
||||
appCmd = appMetadata.Extended["appCommand"]
|
||||
cliPIDString = appMetadata.Extended["cliPID"]
|
||||
runTemplatePath = appMetadata.Extended["runTemplatePath"]
|
||||
}
|
||||
|
||||
// Parse functions return an error on bad input.
|
||||
|
|
@ -134,6 +137,7 @@ func List() ([]ListOutput, error) {
|
|||
Command: utils.TruncateString(appCmd, 20),
|
||||
MaxRequestBodySize: maxRequestBodySize,
|
||||
HTTPReadBufferSize: httpReadBufferSize,
|
||||
RunTemplatePath: runTemplatePath,
|
||||
}
|
||||
|
||||
// filter only dashboard instance.
|
||||
|
|
@ -156,3 +160,12 @@ func getIntArg(argMap map[string]string, argKey string, argDef int) int {
|
|||
}
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,19 +23,15 @@ import (
|
|||
)
|
||||
|
||||
// Stop terminates the application process.
|
||||
func Stop(appID string) error {
|
||||
apps, err := List()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func Stop(appID string, cliPIDToNoOfApps map[int]int, apps []ListOutput) error {
|
||||
for _, a := range apps {
|
||||
if a.AppID == appID {
|
||||
var pid string
|
||||
// Kill the Daprd process if Daprd was started without CLI, otherwise
|
||||
// kill the CLI process which also kills the associated Daprd process.
|
||||
if a.CliPID == 0 {
|
||||
if a.CliPID == 0 || cliPIDToNoOfApps[a.CliPID] > 1 {
|
||||
pid = fmt.Sprintf("%v", a.DaprdPID)
|
||||
cliPIDToNoOfApps[a.CliPID]--
|
||||
} else {
|
||||
pid = fmt.Sprintf("%v", a.CliPID)
|
||||
}
|
||||
|
|
@ -45,6 +41,20 @@ func Stop(appID string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("couldn't find app id %s", appID)
|
||||
}
|
||||
|
||||
// StopAppsWithRunFile terminates the daprd and application processes with the given run file.
|
||||
func StopAppsWithRunFile(runTemplatePath string) error {
|
||||
apps, err := List()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, a := range apps {
|
||||
if a.RunTemplatePath == runTemplatePath {
|
||||
_, err := utils.RunCmdAndWait("kill", fmt.Sprintf("%v", a.CliPID))
|
||||
return err
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("couldn't find apps with run file %q", runTemplatePath)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ limitations under the License.
|
|||
package standalone
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"syscall"
|
||||
|
||||
|
|
@ -21,12 +22,7 @@ import (
|
|||
)
|
||||
|
||||
// Stop terminates the application process.
|
||||
func Stop(appID string) error {
|
||||
apps, err := List()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func Stop(appID string, cliPIDToNoOfApps map[int]int, apps []ListOutput) error {
|
||||
for _, a := range apps {
|
||||
if a.AppID == appID {
|
||||
eventName, _ := syscall.UTF16FromString(fmt.Sprintf("dapr_cli_%v", a.CliPID))
|
||||
|
|
@ -39,6 +35,10 @@ func Stop(appID string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("couldn't find app id %s", appID)
|
||||
}
|
||||
|
||||
// StopAppsWithRunFile terminates the daprd and application processes with the given run file.
|
||||
func StopAppsWithRunFile(runFilePath string) error {
|
||||
return errors.New("stopping apps with run template file is not supported on windows")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ func TestStandaloneStop(t *testing.T) {
|
|||
output, err := cmdStop("dapr_e2e_stop", "-p", "test")
|
||||
require.Error(t, err, "expected error on stop with unknown flag")
|
||||
require.Contains(t, output, "Error: unknown shorthand flag: 'p' in -p\nUsage:", "expected usage to be printed")
|
||||
require.Contains(t, output, "-a, --app-id string The application id to be stopped", "expected usage to be printed")
|
||||
require.Contains(t, output, "-a, --app-id string", "expected usage to be printed")
|
||||
require.Contains(t, output, "-f, --run-file string", "expected usage to be printed")
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue