generated from TBD54566975/tbd-project-template
/
main.go
132 lines (111 loc) · 4.71 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"context"
"errors"
"net/url"
"os"
"os/signal"
"runtime"
"strconv"
"syscall"
"github.com/alecthomas/kong"
kongtoml "github.com/alecthomas/kong-toml"
"github.com/TBD54566975/ftl"
"github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/ftlv1connect"
cf "github.com/TBD54566975/ftl/common/configuration"
"github.com/TBD54566975/ftl/common/projectconfig"
_ "github.com/TBD54566975/ftl/internal/automaxprocs" // Set GOMAXPROCS to match Linux container CPU quota.
"github.com/TBD54566975/ftl/internal/log"
"github.com/TBD54566975/ftl/internal/rpc"
)
type CLI struct {
Version kong.VersionFlag `help:"Show version."`
LogConfig log.Config `embed:"" prefix:"log-" group:"Logging:"`
Endpoint *url.URL `default:"http://127.0.0.1:8892" help:"FTL endpoint to bind/connect to." env:"FTL_ENDPOINT"`
ConfigFlag []string `name:"config" short:"C" help:"Paths to FTL project configuration files." env:"FTL_CONFIG" placeholder:"FILE[,FILE,...]"`
Authenticators map[string]string `help:"Authenticators to use for FTL endpoints." mapsep:"," env:"FTL_AUTHENTICATORS" placeholder:"HOST=EXE,…"`
Ping pingCmd `cmd:"" help:"Ping the FTL cluster."`
Status statusCmd `cmd:"" help:"Show FTL status."`
Init initCmd `cmd:"" help:"Initialize a new FTL module."`
Dev devCmd `cmd:"" help:"Develop FTL modules. Will start the FTL cluster, build and deploy all modules found in the specified directories, and watch for changes."`
PS psCmd `cmd:"" help:"List deployments."`
Serve serveCmd `cmd:"" help:"Start the FTL server."`
Call callCmd `cmd:"" help:"Call an FTL function."`
Update updateCmd `cmd:"" help:"Update a deployment."`
Kill killCmd `cmd:"" help:"Kill a deployment."`
Schema schemaCmd `cmd:"" help:"FTL schema commands."`
Build buildCmd `cmd:"" help:"Build all modules found in the specified directories."`
Deploy deployCmd `cmd:"" help:"Build and deploy all modules found in the specified directories."`
Download downloadCmd `cmd:"" help:"Download a deployment."`
Secret secretCmd `cmd:"" help:"Manage secrets."`
Config configCmd `cmd:"" help:"Manage configuration."`
}
var cli CLI
func main() {
kctx := kong.Parse(&cli,
kong.Description(`FTL - Towards a 𝝺-calculus for large-scale systems`),
kong.Configuration(kongtoml.Loader, ".ftl.toml", "~/.ftl.toml"),
kong.ShortUsageOnError(),
kong.HelpOptions{Compact: true, WrapUpperBound: 80},
kong.AutoGroup(func(parent kong.Visitable, flag *kong.Flag) *kong.Group {
node, ok := parent.(*kong.Command)
if !ok {
return nil
}
return &kong.Group{Key: node.Name, Title: "Command flags:"}
}),
kong.Vars{
"version": ftl.Version,
"os": runtime.GOOS,
"arch": runtime.GOARCH,
"numcpu": strconv.Itoa(runtime.NumCPU()),
},
)
rpc.InitialiseClients(cli.Authenticators)
// Set some envars for child processes.
os.Setenv("LOG_LEVEL", cli.LogConfig.Level.String())
ctx, cancel := context.WithCancel(context.Background())
logger := log.Configure(os.Stderr, cli.LogConfig)
ctx = log.ContextWithLogger(ctx, logger)
config, err := projectconfig.LoadConfig(ctx, cli.ConfigFlag)
if err != nil && !errors.Is(err, os.ErrNotExist) {
kctx.Fatalf(err.Error())
}
kctx.Bind(config)
sr := cf.ProjectConfigResolver[cf.Secrets]{Config: cli.ConfigFlag}
cr := cf.ProjectConfigResolver[cf.Configuration]{Config: cli.ConfigFlag}
kctx.BindTo(sr, (*cf.Resolver[cf.Secrets])(nil))
kctx.BindTo(cr, (*cf.Resolver[cf.Configuration])(nil))
// Add config manager to context.
cm, err := cf.NewConfigurationManager(ctx, cr)
if err != nil {
kctx.Fatalf(err.Error())
}
ctx = cf.ContextWithConfig(ctx, cm)
// Add secrets manager to context.
sm, err := cf.NewSecretsManager(ctx, sr)
if err != nil {
kctx.Fatalf(err.Error())
}
ctx = cf.ContextWithSecrets(ctx, sm)
// Handle signals.
sigch := make(chan os.Signal, 1)
signal.Notify(sigch, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigch
logger.Debugf("FTL terminating with signal %s", sig)
cancel()
_ = syscall.Kill(-syscall.Getpid(), sig.(syscall.Signal)) //nolint:forcetypeassert
os.Exit(0)
}()
controllerServiceClient := rpc.Dial(ftlv1connect.NewControllerServiceClient, cli.Endpoint.String(), log.Error)
ctx = rpc.ContextWithClient(ctx, controllerServiceClient)
kctx.BindTo(controllerServiceClient, (*ftlv1connect.ControllerServiceClient)(nil))
verbServiceClient := rpc.Dial(ftlv1connect.NewVerbServiceClient, cli.Endpoint.String(), log.Error)
ctx = rpc.ContextWithClient(ctx, verbServiceClient)
kctx.BindTo(verbServiceClient, (*ftlv1connect.VerbServiceClient)(nil))
kctx.Bind(cli.Endpoint)
kctx.BindTo(ctx, (*context.Context)(nil))
err = kctx.Run(ctx)
kctx.FatalIfErrorf(err)
}