-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathcmd.go
142 lines (118 loc) · 4.35 KB
/
cmd.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
133
134
135
136
137
138
139
140
141
142
package cmd
import (
"context"
"errors"
"io"
"os"
"os/signal"
"syscall"
"github.com/jzelinskie/cobrautil/v2"
"github.com/jzelinskie/cobrautil/v2/cobrazerolog"
"github.com/mattn/go-isatty"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/authzed/zed/internal/commands"
)
var (
SyncFlagsCmdFunc = cobrautil.SyncViperPreRunE("ZED")
errParsing = errors.New("parsing error")
)
func init() {
// NOTE: this is mostly to set up logging in the case where
// the command doesn't exist or the construction of the command
// errors out before the PersistentPreRunE setup in the below function.
// It helps keep log output visually consistent for a user even in
// exceptional cases.
var output io.Writer
if isatty.IsTerminal(os.Stdout.Fd()) {
output = zerolog.ConsoleWriter{Out: os.Stderr}
} else {
output = os.Stderr
}
l := zerolog.New(output).With().Timestamp().Logger()
log.Logger = l
}
func Run() {
zl := cobrazerolog.New(cobrazerolog.WithPreRunLevel(zerolog.DebugLevel))
rootCmd := &cobra.Command{
Use: "zed",
Short: "SpiceDB client, by AuthZed",
Long: "A command-line client for managing SpiceDB clusters, built by AuthZed",
PersistentPreRunE: cobrautil.CommandStack(
zl.RunE(),
SyncFlagsCmdFunc,
commands.InjectRequestID,
),
SilenceErrors: true,
SilenceUsage: false,
}
rootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
cmd.Println(err)
cmd.Println(cmd.UsageString())
return errParsing
})
zl.RegisterFlags(rootCmd.PersistentFlags())
rootCmd.PersistentFlags().String("endpoint", "", "spicedb gRPC API endpoint")
rootCmd.PersistentFlags().String("permissions-system", "", "permissions system to query")
rootCmd.PersistentFlags().String("hostname-override", "", "override the hostname used in the connection to the endpoint")
rootCmd.PersistentFlags().String("token", "", "token used to authenticate to SpiceDB")
rootCmd.PersistentFlags().String("certificate-path", "", "path to certificate authority used to verify secure connections")
rootCmd.PersistentFlags().Bool("insecure", false, "connect over a plaintext connection")
rootCmd.PersistentFlags().Bool("skip-version-check", false, "if true, no version check is performed against the server")
rootCmd.PersistentFlags().Bool("no-verify-ca", false, "do not attempt to verify the server's certificate chain and host name")
rootCmd.PersistentFlags().Bool("debug", false, "enable debug logging")
rootCmd.PersistentFlags().String("request-id", "", "optional id to send along with SpiceDB requests for tracing")
rootCmd.PersistentFlags().Int("max-message-size", 0, "maximum size *in bytes* (defaults to 4_194_304 bytes ~= 4MB) of a gRPC message that can be sent or received by zed")
_ = rootCmd.PersistentFlags().MarkHidden("debug") // This cannot return its error.
versionCmd := &cobra.Command{
Use: "version",
Short: "Display zed and SpiceDB version information",
RunE: versionCmdFunc,
}
cobrautil.RegisterVersionFlags(versionCmd.Flags())
versionCmd.Flags().Bool("include-remote-version", true, "whether to display the version of Authzed or SpiceDB for the current context")
rootCmd.AddCommand(versionCmd)
// Register root-level aliases
rootCmd.AddCommand(&cobra.Command{
Use: "use <context>",
Short: "Alias for `zed context use`",
Args: cobra.MaximumNArgs(1),
RunE: contextUseCmdFunc,
ValidArgsFunction: ContextGet,
})
// Register CLI-only commands.
registerContextCmd(rootCmd)
registerImportCmd(rootCmd)
registerValidateCmd(rootCmd)
registerBackupCmd(rootCmd)
registerPreviewCmd(rootCmd)
// Register shared commands.
commands.RegisterPermissionCmd(rootCmd)
relCmd := commands.RegisterRelationshipCmd(rootCmd)
commands.RegisterWatchCmd(rootCmd)
commands.RegisterWatchRelationshipCmd(relCmd)
schemaCmd := commands.RegisterSchemaCmd(rootCmd)
registerAdditionalSchemaCmds(schemaCmd)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
signalChan := make(chan os.Signal, 2)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
defer func() {
signal.Stop(signalChan)
cancel()
}()
go func() {
select {
case <-signalChan:
cancel()
case <-ctx.Done():
}
}()
if err := rootCmd.ExecuteContext(ctx); err != nil {
if !errors.Is(err, errParsing) {
log.Err(err).Msg("terminated with errors")
}
os.Exit(1)
}
}