mirror of https://github.com/dapr/cli.git
194 lines
4.0 KiB
Go
194 lines
4.0 KiB
Go
package standalone
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v2"
|
|
|
|
"github.com/Pallinder/sillyname-go"
|
|
"github.com/phayes/freeport"
|
|
)
|
|
|
|
type RunConfig struct {
|
|
AppID string
|
|
AppPort int
|
|
Port int
|
|
Arguments []string
|
|
}
|
|
|
|
type RunOutput struct {
|
|
ActionsCMD *exec.Cmd
|
|
ActionsPort int
|
|
AppID string
|
|
AppCMD *exec.Cmd
|
|
}
|
|
|
|
type component struct {
|
|
APIVersion string `json:"apiVersion"`
|
|
Kind string `json:"kind"`
|
|
Metadata struct {
|
|
Name string `json:"name"`
|
|
} `json:"metadata"`
|
|
Spec struct {
|
|
Type string `json:"type"`
|
|
ConnectionInfo map[string]string `json:"connectionInfo"`
|
|
} `json:"spec"`
|
|
}
|
|
|
|
func getActionsCommand(appID string, actionsPort int, appPort int) (*exec.Cmd, int, error) {
|
|
if actionsPort < 0 {
|
|
port, err := freeport.GetFreePort()
|
|
if err != nil {
|
|
return nil, -1, err
|
|
}
|
|
|
|
actionsPort = port
|
|
}
|
|
|
|
actionsCMD := "actionsrt"
|
|
if runtime.GOOS == "windows" {
|
|
actionsCMD = fmt.Sprintf("%s.exe", actionsCMD)
|
|
}
|
|
|
|
args := []string{"--actions-id", appID, "--actions-http-port", fmt.Sprintf("%v", actionsPort)}
|
|
if appPort > -1 {
|
|
args = append(args, "--app-port")
|
|
args = append(args, fmt.Sprintf("%v", appPort))
|
|
}
|
|
|
|
args = append(args, "--placement-address")
|
|
|
|
if runtime.GOOS == "windows" {
|
|
args = append(args, "localhost:6050")
|
|
args = append(args, "--actions-grpc-port", "6051")
|
|
} else {
|
|
args = append(args, "localhost:50005")
|
|
}
|
|
|
|
cmd := exec.Command(actionsCMD, args...)
|
|
return cmd, actionsPort, nil
|
|
}
|
|
|
|
func getAppCommand(actionsPort int, command string, args []string) (*exec.Cmd, error) {
|
|
cmd := exec.Command(command, args...)
|
|
cmd.Env = os.Environ()
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("ACTIONS_PORT=%v", actionsPort))
|
|
|
|
return cmd, nil
|
|
}
|
|
|
|
func createRedisStateStore() error {
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
redisStore := component{
|
|
APIVersion: "actions.io/v1alpha1",
|
|
Kind: "Component",
|
|
}
|
|
|
|
redisStore.Metadata.Name = "statestore"
|
|
redisStore.Spec.Type = "state.redis"
|
|
redisStore.Spec.ConnectionInfo = map[string]string{}
|
|
redisStore.Spec.ConnectionInfo["redisHost"] = "localhost:6379"
|
|
redisStore.Spec.ConnectionInfo["redisPassword"] = ""
|
|
|
|
b, err := yaml.Marshal(&redisStore)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
os.Mkdir(path.Join(wd, "components"), 0777)
|
|
err = ioutil.WriteFile(path.Join(path.Join(wd, "components"), "redis.yaml"), b, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func createRedisPubSub() error {
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
redisMessageBus := component{
|
|
APIVersion: "actions.io/v1alpha1",
|
|
Kind: "Component",
|
|
}
|
|
|
|
redisMessageBus.Metadata.Name = "messagebus"
|
|
redisMessageBus.Spec.Type = "pubsub.redis"
|
|
redisMessageBus.Spec.ConnectionInfo = map[string]string{}
|
|
redisMessageBus.Spec.ConnectionInfo["redisHost"] = "localhost:6379"
|
|
redisMessageBus.Spec.ConnectionInfo["password"] = ""
|
|
|
|
b, err := yaml.Marshal(&redisMessageBus)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
os.Mkdir(path.Join(wd, "components"), 0777)
|
|
err = ioutil.WriteFile(path.Join(path.Join(wd, "components"), "redis_messagebus.yaml"), b, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func Run(config *RunConfig) (*RunOutput, error) {
|
|
appID := config.AppID
|
|
if appID == "" {
|
|
appID = strings.Replace(sillyname.GenerateStupidName(), " ", "-", -1)
|
|
}
|
|
|
|
err := createRedisStateStore()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = createRedisPubSub()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
actionsCMD, actionsPort, err := getActionsCommand(appID, config.Port, config.AppPort)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
runArgs := []string{}
|
|
argCount := len(config.Arguments)
|
|
|
|
if argCount == 0 {
|
|
return nil, errors.New("No app entrypoint given")
|
|
}
|
|
|
|
cmd := config.Arguments[0]
|
|
if len(config.Arguments) > 1 {
|
|
runArgs = config.Arguments[1:]
|
|
}
|
|
|
|
appCMD, err := getAppCommand(actionsPort, cmd, runArgs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &RunOutput{
|
|
ActionsCMD: actionsCMD,
|
|
AppCMD: appCMD,
|
|
AppID: appID,
|
|
ActionsPort: actionsPort,
|
|
}, nil
|
|
}
|