171 lines
4.3 KiB
Go
171 lines
4.3 KiB
Go
//go:build unix
|
|
|
|
package dev
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
|
|
"github.com/cirruslabs/orchard/internal/config"
|
|
"github.com/cirruslabs/orchard/internal/controller"
|
|
"github.com/cirruslabs/orchard/internal/netconstants"
|
|
"github.com/cirruslabs/orchard/internal/worker"
|
|
"github.com/cirruslabs/orchard/pkg/client"
|
|
v1 "github.com/cirruslabs/orchard/pkg/resource/v1"
|
|
"github.com/spf13/cobra"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
var ErrFailed = errors.New("failed to run development controller and worker")
|
|
|
|
var devDataDirPath string
|
|
var apiPrefix string
|
|
var stringToStringResources map[string]string
|
|
var experimentalRPCV2 bool
|
|
|
|
func NewCommand() *cobra.Command {
|
|
command := &cobra.Command{
|
|
Use: "dev",
|
|
Short: "Run a controller and a worker for development purposes",
|
|
RunE: runDev,
|
|
}
|
|
|
|
command.Flags().StringVarP(&devDataDirPath, "data-dir", "d", ".dev-data",
|
|
"path to persist data between runs")
|
|
command.Flags().StringVar(&apiPrefix, "api-prefix", "",
|
|
"prefix to prepend to all Orchard Controller API endpoints; useful when exposing Orchard Controller "+
|
|
"behind an HTTP proxy together with other services")
|
|
command.Flags().StringToStringVar(&stringToStringResources, "resources", map[string]string{},
|
|
"resources that the development worker will provide")
|
|
command.Flags().BoolVar(&experimentalRPCV2, "experimental-rpc-v2", false,
|
|
"enable experimental RPC v2 (https://github.com/cirruslabs/orchard/issues/235)")
|
|
|
|
return command
|
|
}
|
|
|
|
func runDev(cmd *cobra.Command, args []string) error {
|
|
if !filepath.IsAbs(devDataDirPath) {
|
|
pwd, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
devDataDirPath = path.Join(pwd, devDataDirPath)
|
|
}
|
|
|
|
// Convert resources
|
|
resources, err := v1.NewResourcesFromStringToString(stringToStringResources)
|
|
if err != nil {
|
|
return fmt.Errorf("%w: %v", ErrFailed, err)
|
|
}
|
|
|
|
var additionalControllerOpts []controller.Option
|
|
|
|
if apiPrefix != "" {
|
|
additionalControllerOpts = append(additionalControllerOpts, controller.WithAPIPrefix(apiPrefix))
|
|
}
|
|
|
|
if experimentalRPCV2 {
|
|
additionalControllerOpts = append(additionalControllerOpts, controller.WithExperimentalRPCV2())
|
|
}
|
|
|
|
devController, devWorker, err := CreateDevControllerAndWorker(devDataDirPath,
|
|
fmt.Sprintf(":%d", netconstants.DefaultControllerPort), resources,
|
|
additionalControllerOpts, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer devWorker.Close()
|
|
|
|
errChan := make(chan error, 2)
|
|
|
|
go func() {
|
|
if err := devController.Run(cmd.Context()); err != nil {
|
|
errChan <- err
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
if err := devWorker.Run(cmd.Context()); err != nil {
|
|
errChan <- err
|
|
}
|
|
}()
|
|
|
|
return <-errChan
|
|
}
|
|
|
|
func CreateDevControllerAndWorker(
|
|
devDataDirPath string,
|
|
controllerListenAddr string,
|
|
resources v1.Resources,
|
|
additionalControllerOpts []controller.Option,
|
|
additionalWorkerOpts []worker.Option,
|
|
) (*controller.Controller, *worker.Worker, error) {
|
|
// Initialize the logger
|
|
logger, err := zap.NewDevelopment()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
defer func() {
|
|
if syncErr := logger.Sync(); syncErr != nil && err == nil {
|
|
err = syncErr
|
|
}
|
|
}()
|
|
|
|
dataDir, err := controller.NewDataDir(devDataDirPath)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
controllerOpts := []controller.Option{
|
|
controller.WithDataDir(dataDir),
|
|
controller.WithListenAddr(controllerListenAddr),
|
|
controller.WithInsecureAuthDisabled(),
|
|
controller.WithSwaggerDocs(),
|
|
controller.WithLogger(logger),
|
|
}
|
|
|
|
controllerOpts = append(controllerOpts, additionalControllerOpts...)
|
|
|
|
devController, err := controller.New(controllerOpts...)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
defaultClient, err := client.New(client.WithAddress(devController.Address()))
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
workerOpts := []worker.Option{
|
|
worker.WithResources(resources),
|
|
worker.WithLogger(logger),
|
|
}
|
|
|
|
workerOpts = append(workerOpts, additionalWorkerOpts...)
|
|
|
|
devWorker, err := worker.New(defaultClient, workerOpts...)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// set local-dev context as active
|
|
configHandle, err := config.NewHandle()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
localContext := config.Context{URL: devController.Address()}
|
|
err = configHandle.CreateContext("local-dev", localContext, true)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
err = configHandle.SetDefaultContext("local-dev")
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return devController, devWorker, nil
|
|
}
|