mirror of https://github.com/dapr/cli.git
250 lines
6.1 KiB
Go
250 lines
6.1 KiB
Go
// ------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation and Dapr Contributors.
|
|
// Licensed under the MIT License.
|
|
// ------------------------------------------------------------
|
|
|
|
package standalone
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/Pallinder/sillyname-go"
|
|
"github.com/dapr/dapr/pkg/components"
|
|
modes "github.com/dapr/dapr/pkg/config/modes"
|
|
"github.com/phayes/freeport"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
const sentryDefaultAddress = "localhost:50001"
|
|
|
|
// RunConfig represents the application configuration parameters.
|
|
type RunConfig struct {
|
|
AppID string
|
|
AppPort int
|
|
HTTPPort int
|
|
GRPCPort int
|
|
ConfigFile string
|
|
Protocol string
|
|
Arguments []string
|
|
EnableProfiling bool
|
|
ProfilePort int
|
|
LogLevel string
|
|
MaxConcurrency int
|
|
PlacementHostAddr string
|
|
ComponentsPath string
|
|
AppSSL bool
|
|
MetricsPort int
|
|
MaxRequestBodySize int
|
|
}
|
|
|
|
// RunOutput represents the run output.
|
|
type RunOutput struct {
|
|
DaprCMD *exec.Cmd
|
|
DaprHTTPPort int
|
|
DaprGRPCPort int
|
|
AppID string
|
|
AppCMD *exec.Cmd
|
|
}
|
|
|
|
func getDaprCommand(appID string, daprHTTPPort int, daprGRPCPort int, appPort int, configFile, protocol string, enableProfiling bool, profilePort int, logLevel string, maxConcurrency int, placementHostAddr string, componentsPath string, appSSL bool, metricsPort int, requestBodySize int) (*exec.Cmd, int, int, int, error) {
|
|
if daprHTTPPort < 0 {
|
|
port, err := freeport.GetFreePort()
|
|
if err != nil {
|
|
return nil, -1, -1, -1, err
|
|
}
|
|
|
|
daprHTTPPort = port
|
|
}
|
|
|
|
if daprGRPCPort < 0 {
|
|
grpcPort, err := freeport.GetFreePort()
|
|
if err != nil {
|
|
return nil, -1, -1, -1, err
|
|
}
|
|
|
|
daprGRPCPort = grpcPort
|
|
}
|
|
|
|
if metricsPort < 0 {
|
|
var err error
|
|
metricsPort, err = freeport.GetFreePort()
|
|
if err != nil {
|
|
return nil, -1, -1, -1, err
|
|
}
|
|
}
|
|
|
|
if maxConcurrency < 1 {
|
|
maxConcurrency = -1
|
|
}
|
|
|
|
if requestBodySize < 0 {
|
|
requestBodySize = -1
|
|
}
|
|
|
|
daprCMD := binaryFilePath(defaultDaprBinPath(), "daprd")
|
|
|
|
args := []string{
|
|
"--app-id", appID,
|
|
"--dapr-http-port", strconv.Itoa(daprHTTPPort),
|
|
"--dapr-grpc-port", strconv.Itoa(daprGRPCPort),
|
|
"--log-level", logLevel,
|
|
"--app-max-concurrency", strconv.Itoa(maxConcurrency),
|
|
"--app-protocol", protocol,
|
|
"--components-path", componentsPath,
|
|
"--metrics-port", strconv.Itoa(metricsPort),
|
|
"--dapr-http-max-request-size", strconv.Itoa(requestBodySize),
|
|
}
|
|
if appPort > -1 {
|
|
args = append(args, "--app-port", strconv.Itoa(appPort))
|
|
}
|
|
args = append(args, "--placement-host-address")
|
|
|
|
// if placementHostAddr does not contain port, add default port value
|
|
if indx := strings.Index(placementHostAddr, ":"); indx == -1 {
|
|
if runtime.GOOS == daprWindowsOS {
|
|
args = append(args, fmt.Sprintf("%s:6050", placementHostAddr))
|
|
} else {
|
|
args = append(args, fmt.Sprintf("%s:50005", placementHostAddr))
|
|
}
|
|
} else {
|
|
args = append(args, placementHostAddr)
|
|
}
|
|
|
|
if configFile != "" {
|
|
args = append(args, "--config", configFile)
|
|
sentryAddress := mtlsEndpoint(configFile)
|
|
if sentryAddress != "" {
|
|
// mTLS is enabled locally, set it up
|
|
args = append(args, "--enable-mtls", "--sentry-address", sentryAddress)
|
|
}
|
|
}
|
|
|
|
if enableProfiling {
|
|
if profilePort == -1 {
|
|
pp, err := freeport.GetFreePort()
|
|
if err != nil {
|
|
return nil, -1, -1, -1, err
|
|
}
|
|
profilePort = pp
|
|
}
|
|
|
|
args = append(
|
|
args,
|
|
"--enable-profiling",
|
|
"--profile-port", strconv.Itoa(profilePort))
|
|
}
|
|
|
|
if appSSL {
|
|
args = append(args, "--app-ssl")
|
|
}
|
|
|
|
cmd := exec.Command(daprCMD, args...)
|
|
return cmd, daprHTTPPort, daprGRPCPort, metricsPort, nil
|
|
}
|
|
|
|
func mtlsEndpoint(configFile string) string {
|
|
if configFile == "" {
|
|
return ""
|
|
}
|
|
|
|
b, err := ioutil.ReadFile(configFile)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
var config mtlsConfig
|
|
err = yaml.Unmarshal(b, &config)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
if config.Spec.MTLS.Enabled {
|
|
return sentryDefaultAddress
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func getAppCommand(httpPort, grpcPort, metricsPort int, command string, args []string) (*exec.Cmd, error) {
|
|
cmd := exec.Command(command, args...)
|
|
cmd.Env = os.Environ()
|
|
cmd.Env = append(
|
|
cmd.Env,
|
|
fmt.Sprintf("DAPR_HTTP_PORT=%v", httpPort),
|
|
fmt.Sprintf("DAPR_GRPC_PORT=%v", grpcPort),
|
|
fmt.Sprintf("DAPR_METRICS_PORT=%v", metricsPort))
|
|
|
|
return cmd, nil
|
|
}
|
|
|
|
func Run(config *RunConfig) (*RunOutput, error) {
|
|
appID := config.AppID
|
|
if appID == "" {
|
|
appID = strings.ReplaceAll(sillyname.GenerateStupidName(), " ", "-")
|
|
}
|
|
|
|
_, err := os.Stat(config.ComponentsPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dapr, err := List()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, a := range dapr {
|
|
if appID == a.AppID {
|
|
return nil, fmt.Errorf("dapr with ID %s is already running", appID)
|
|
}
|
|
}
|
|
|
|
componentsLoader := components.NewStandaloneComponents(modes.StandaloneConfig{ComponentsPath: config.ComponentsPath})
|
|
_, err = componentsLoader.LoadComponents()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
daprCMD, daprHTTPPort, daprGRPCPort, metricsPort, err := getDaprCommand(appID, config.HTTPPort, config.GRPCPort, config.AppPort, config.ConfigFile, config.Protocol, config.EnableProfiling, config.ProfilePort, config.LogLevel, config.MaxConcurrency, config.PlacementHostAddr, config.ComponentsPath, config.AppSSL, config.MetricsPort, config.MaxRequestBodySize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, a := range dapr {
|
|
if daprHTTPPort == a.HTTPPort {
|
|
return nil, fmt.Errorf("there's already a Dapr instance running with http port %v", daprHTTPPort)
|
|
} else if daprGRPCPort == a.GRPCPort {
|
|
return nil, fmt.Errorf("there's already a Dapr instance running with gRPC port %v", daprGRPCPort)
|
|
}
|
|
}
|
|
|
|
argCount := len(config.Arguments)
|
|
runArgs := []string{}
|
|
var appCMD *exec.Cmd
|
|
|
|
if argCount > 0 {
|
|
cmd := config.Arguments[0]
|
|
if len(config.Arguments) > 1 {
|
|
runArgs = config.Arguments[1:]
|
|
}
|
|
|
|
appCMD, err = getAppCommand(daprHTTPPort, daprGRPCPort, metricsPort, cmd, runArgs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &RunOutput{
|
|
DaprCMD: daprCMD,
|
|
AppCMD: appCMD,
|
|
AppID: appID,
|
|
DaprHTTPPort: daprHTTPPort,
|
|
DaprGRPCPort: daprGRPCPort,
|
|
}, nil
|
|
}
|