mirror of https://github.com/dapr/cli.git
262 lines
9.0 KiB
Go
262 lines
9.0 KiB
Go
// ------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
// ------------------------------------------------------------
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/dapr/cli/pkg/kubernetes"
|
|
"github.com/dapr/cli/pkg/metadata"
|
|
"github.com/dapr/cli/pkg/print"
|
|
"github.com/dapr/cli/pkg/standalone"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var appPort int
|
|
var profilePort int
|
|
var appID string
|
|
var configFile string
|
|
var port int
|
|
var grpcPort int
|
|
var maxConcurrency int
|
|
var image string
|
|
var enableProfiling bool
|
|
var logLevel string
|
|
var protocol string
|
|
var componentsPath string
|
|
|
|
var RunCmd = &cobra.Command{
|
|
Use: "run",
|
|
Short: "Launches Dapr and (optionally) your app side by side",
|
|
Long: `Runs Dapr's sidecar and (optionally) an application.
|
|
|
|
Run a Java application:
|
|
dapr run --app-id myapp -- java -jar myapp.jar
|
|
Run a NodeJs application that listens to port 3000:
|
|
dapr run --app-id myapp --app-port 3000 -- node myapp.js
|
|
Run a Python application:
|
|
dapr run --app-id myapp -- python myapp.py
|
|
Run sidecar only:
|
|
dapr run --app-id myapp
|
|
`,
|
|
Args: cobra.MinimumNArgs(0),
|
|
PreRun: func(cmd *cobra.Command, args []string) {
|
|
viper.BindPFlag("placement-host", cmd.Flags().Lookup("placement-host"))
|
|
},
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
if len(args) == 0 {
|
|
fmt.Println(print.WhiteBold("WARNING: no application command found."))
|
|
}
|
|
|
|
if kubernetesMode {
|
|
output, err := kubernetes.Run(&kubernetes.RunConfig{
|
|
AppID: appID,
|
|
AppPort: appPort,
|
|
GRPCPort: grpcPort,
|
|
HTTPPort: port,
|
|
Arguments: args,
|
|
Image: image,
|
|
CodeDirectory: args[0],
|
|
})
|
|
if err != nil {
|
|
print.FailureStatusEvent(os.Stdout, err.Error())
|
|
return
|
|
}
|
|
|
|
print.InfoStatusEvent(os.Stdout, output.Message)
|
|
} else {
|
|
output, err := standalone.Run(&standalone.RunConfig{
|
|
AppID: appID,
|
|
AppPort: appPort,
|
|
HTTPPort: port,
|
|
GRPCPort: grpcPort,
|
|
ConfigFile: configFile,
|
|
Arguments: args,
|
|
EnableProfiling: enableProfiling,
|
|
ProfilePort: profilePort,
|
|
LogLevel: logLevel,
|
|
MaxConcurrency: maxConcurrency,
|
|
Protocol: protocol,
|
|
PlacementHost: viper.GetString("placement-host"),
|
|
ComponentsPath: componentsPath,
|
|
})
|
|
if err != nil {
|
|
print.FailureStatusEvent(os.Stdout, err.Error())
|
|
return
|
|
}
|
|
|
|
var sigCh = make(chan os.Signal, 1)
|
|
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
daprRunning := make(chan bool, 1)
|
|
appRunning := make(chan bool, 1)
|
|
|
|
go func() {
|
|
print.InfoStatusEvent(
|
|
os.Stdout,
|
|
fmt.Sprintf(
|
|
"Starting Dapr with id %s. HTTP Port: %v. gRPC Port: %v",
|
|
output.AppID,
|
|
output.DaprHTTPPort,
|
|
output.DaprGRPCPort))
|
|
|
|
stdErrPipe, pipeErr := output.DaprCMD.StderrPipe()
|
|
if pipeErr != nil {
|
|
print.FailureStatusEvent(os.Stdout, fmt.Sprintf("Error creating stderr for Dapr: %s", err.Error()))
|
|
os.Exit(1)
|
|
}
|
|
|
|
stdOutPipe, pipeErr := output.DaprCMD.StdoutPipe()
|
|
if pipeErr != nil {
|
|
print.FailureStatusEvent(os.Stdout, fmt.Sprintf("Error creating stdout for Dapr: %s", err.Error()))
|
|
os.Exit(1)
|
|
}
|
|
|
|
errScanner := bufio.NewScanner(stdErrPipe)
|
|
outScanner := bufio.NewScanner(stdOutPipe)
|
|
go func() {
|
|
for errScanner.Scan() {
|
|
fmt.Println(print.Yellow(fmt.Sprintf("== DAPR == %s\n", errScanner.Text())))
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
for outScanner.Scan() {
|
|
fmt.Println(print.Yellow(fmt.Sprintf("== DAPR == %s\n", outScanner.Text())))
|
|
}
|
|
}()
|
|
|
|
err = output.DaprCMD.Start()
|
|
if err != nil {
|
|
print.FailureStatusEvent(os.Stdout, err.Error())
|
|
os.Exit(1)
|
|
}
|
|
|
|
daprRunning <- true
|
|
}()
|
|
|
|
<-daprRunning
|
|
|
|
go func() {
|
|
if output.AppCMD == nil {
|
|
appRunning <- true
|
|
return
|
|
}
|
|
|
|
stdErrPipe, pipeErr := output.AppCMD.StderrPipe()
|
|
if pipeErr != nil {
|
|
print.FailureStatusEvent(os.Stdout, fmt.Sprintf("Error creating stderr for App: %s", err.Error()))
|
|
os.Exit(1)
|
|
}
|
|
|
|
stdOutPipe, pipeErr := output.AppCMD.StdoutPipe()
|
|
if pipeErr != nil {
|
|
print.FailureStatusEvent(os.Stdout, fmt.Sprintf("Error creating stdout for App: %s", err.Error()))
|
|
os.Exit(1)
|
|
}
|
|
|
|
errScanner := bufio.NewScanner(stdErrPipe)
|
|
outScanner := bufio.NewScanner(stdOutPipe)
|
|
go func() {
|
|
for errScanner.Scan() {
|
|
fmt.Println(print.Blue(fmt.Sprintf("== APP == %s\n", errScanner.Text())))
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
for outScanner.Scan() {
|
|
fmt.Println(print.Blue(fmt.Sprintf("== APP == %s\n", outScanner.Text())))
|
|
}
|
|
}()
|
|
|
|
err = output.AppCMD.Start()
|
|
if err != nil {
|
|
print.FailureStatusEvent(os.Stdout, err.Error())
|
|
os.Exit(1)
|
|
}
|
|
|
|
appRunning <- true
|
|
}()
|
|
|
|
<-appRunning
|
|
|
|
// Metadata API is only available if app has started listening to port, so wait for app to start before calling metadata API.
|
|
err = metadata.Put(output.DaprHTTPPort, "cliPID", strconv.Itoa(os.Getpid()))
|
|
if err != nil {
|
|
print.WarningStatusEvent(os.Stdout, "Could not update sidecar metadata for cliPID: %s", err.Error())
|
|
}
|
|
|
|
if output.AppCMD != nil {
|
|
appCommand := strings.Join(args, " ")
|
|
print.InfoStatusEvent(os.Stdout, fmt.Sprintf("Updating metadata for app command: %s", appCommand))
|
|
err = metadata.Put(output.DaprHTTPPort, "appCommand", appCommand)
|
|
if err != nil {
|
|
print.WarningStatusEvent(os.Stdout, "Could not update sidecar metadata for appCommand: %s", err.Error())
|
|
}
|
|
|
|
print.SuccessStatusEvent(os.Stdout, "You're up and running! Both Dapr and your app logs will appear here.\n")
|
|
} else {
|
|
print.SuccessStatusEvent(os.Stdout, "You're up and running! Dapr logs will appear here.\n")
|
|
}
|
|
|
|
<-sigCh
|
|
print.InfoStatusEvent(os.Stdout, "\nterminated signal received: shutting down")
|
|
|
|
err = output.DaprCMD.Process.Kill()
|
|
if err != nil {
|
|
print.FailureStatusEvent(os.Stdout, fmt.Sprintf("Error exiting Dapr: %s", err))
|
|
} else {
|
|
print.SuccessStatusEvent(os.Stdout, "Exited Dapr successfully")
|
|
}
|
|
|
|
if output.AppCMD != nil {
|
|
err = output.AppCMD.Process.Kill()
|
|
if err != nil {
|
|
print.FailureStatusEvent(os.Stdout, fmt.Sprintf("Error exiting App: %s", err))
|
|
} else {
|
|
print.SuccessStatusEvent(os.Stdout, "Exited App successfully")
|
|
}
|
|
}
|
|
}
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
RunCmd.Flags().IntVarP(&appPort, "app-port", "p", -1, "the port your application is listening on")
|
|
RunCmd.Flags().StringVarP(&appID, "app-id", "i", "", "an id for your application, used for service discovery")
|
|
RunCmd.Flags().StringVarP(&configFile, "config", "c", standalone.DefaultConfigFilePath(), "Dapr configuration file. Default is $HOME/.dapr/config.yaml or %USERPROFILE%\\.dapr\\config.yaml")
|
|
RunCmd.Flags().IntVarP(&port, "dapr-http-port", "H", -1, "the HTTP port for Dapr to listen on")
|
|
RunCmd.Flags().IntVarP(&grpcPort, "dapr-grpc-port", "G", -1, "the gRPC port for Dapr to listen on")
|
|
RunCmd.Flags().StringVarP(&image, "image", "", "", "the image to build the code in. input is repository/image")
|
|
RunCmd.Flags().BoolVar(&enableProfiling, "enable-profiling", false, "Enable pprof profiling via an HTTP endpoint")
|
|
RunCmd.Flags().IntVarP(&profilePort, "profile-port", "", -1, "the port for the profile server to listen on")
|
|
RunCmd.Flags().StringVarP(&logLevel, "log-level", "", "info", "Sets the log verbosity. Valid values are: debug, info, warn, error, fatal, or panic. Default is info")
|
|
RunCmd.Flags().IntVarP(&maxConcurrency, "max-concurrency", "", -1, "controls the concurrency level of the app. Default is unlimited")
|
|
RunCmd.Flags().StringVarP(&protocol, "app-protocol", "P", "http", "tells Dapr to use HTTP or gRPC to talk to the app. Default is http")
|
|
RunCmd.Flags().StringVarP(&componentsPath, "components-path", "d", standalone.DefaultComponentsDirPath(), "Path for components directory. Default is $HOME/.dapr/components or %USERPROFILE%\\.dapr\\components")
|
|
RunCmd.Flags().String("placement-host-address", "localhost", "the host on which the placement service resides")
|
|
|
|
// deprecated flags
|
|
RunCmd.Flags().IntVarP(&port, "port", "", -1, "the HTTP port for Dapr to listen on")
|
|
RunCmd.Flags().IntVarP(&grpcPort, "grpc-port", "", -1, "the gRPC port for Dapr to listen on")
|
|
RunCmd.Flags().String("placement-host", "localhost", "the host on which the placement service resides")
|
|
RunCmd.Flags().StringVarP(&protocol, "protocol", "", "http", "tells Dapr to use HTTP or gRPC to talk to the app. Default is http")
|
|
|
|
RunCmd.Flags().MarkDeprecated("port", "this flag is deprecated and will be removed in v1.0. Use dapr-http-port instead")
|
|
RunCmd.Flags().MarkDeprecated("grpc-port", "this flag is deprecated and will be removed in v1.0. Use dapr-grpc-port instead")
|
|
RunCmd.Flags().MarkDeprecated("placement-host", "this flag is deprecated and will be removed in v1.0. Use placement-host-address instead")
|
|
RunCmd.Flags().MarkDeprecated("protocol", "this flag is deprecated and will be removed in v1.0. Use app-protocol instead")
|
|
|
|
RootCmd.AddCommand(RunCmd)
|
|
}
|