-
Notifications
You must be signed in to change notification settings - Fork 223
/
run.go
125 lines (99 loc) · 2.53 KB
/
run.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
package agent
import (
"context"
"fmt"
"io"
"log"
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/superfly/flyctl/agent/server"
"github.com/superfly/flyctl/client"
"github.com/superfly/flyctl/internal/command"
"github.com/superfly/flyctl/internal/filemu"
"github.com/superfly/flyctl/internal/flag"
"github.com/superfly/flyctl/internal/state"
)
func newRun() (cmd *cobra.Command) {
const (
short = "Run the Fly agent in the foreground"
long = short + "\n"
)
cmd = command.New("run", short, long, run)
cmd.Args = cobra.MaximumNArgs(1)
cmd.Aliases = []string{"daemon-start"}
return
}
func run(ctx context.Context) error {
logPath := flag.FirstArg(ctx)
logger, closeLogger, err := setupLogger(logPath)
if err != nil {
err = fmt.Errorf("failed setting up logger: %w", err)
fmt.Fprintln(os.Stderr, err)
return err
}
defer closeLogger()
apiClient := client.FromContext(ctx)
if !apiClient.Authenticated() {
logger.Println(client.ErrNoAuthToken)
return client.ErrNoAuthToken
}
unlock, err := lock(ctx, logger)
if err != nil {
return err
}
defer unlock()
opt := server.Options{
Socket: socketPath(ctx),
Logger: logger,
Client: apiClient.API(),
Background: logPath != "",
ConfigFile: state.ConfigFile(ctx),
}
return server.Run(ctx, opt)
}
func setupLogger(path string) (logger *log.Logger, close func(), err error) {
var out io.Writer
if path != "" {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0o600)
if err != nil {
return nil, nil, err
}
out = io.MultiWriter(os.Stdout, f)
close = func() {
_ = f.Sync()
_ = f.Close()
}
} else {
out = os.Stdout
close = func() {}
}
logger = log.Default()
logger.SetFlags(log.Ldate | log.Lmicroseconds | log.Lmsgprefix)
logger.SetPrefix("srv ")
logger.SetOutput(out)
return
}
type dupInstanceError struct{}
func (*dupInstanceError) Error() string {
return "another instance of the agent is already running"
}
func (*dupInstanceError) Description() string {
return "It looks like another instance of the agent is already running. Please stop it before starting a new one."
}
var (
lockPath = filepath.Join(os.TempDir(), "flyctl.agent.lock")
errDupInstance = new(dupInstanceError)
)
func lock(ctx context.Context, logger *log.Logger) (unlock filemu.UnlockFunc, err error) {
switch unlock, err = filemu.Lock(ctx, lockPath); {
case err == nil:
break // all done
case ctx.Err() != nil:
err = ctx.Err() // parent canceled or deadlined
default:
err = errDupInstance
logger.Print(err)
}
return
}