-
Notifications
You must be signed in to change notification settings - Fork 469
/
flags.go
221 lines (193 loc) · 13.6 KB
/
flags.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package cli
import (
"flag"
"path/filepath"
"strings"
"time"
"github.com/tus/tusd/v2/internal/grouped_flags"
"github.com/tus/tusd/v2/pkg/hooks"
"golang.org/x/exp/slices"
)
var Flags struct {
HttpHost string
HttpPort string
HttpSock string
MaxSize int64
UploadDir string
Basepath string
ShowGreeting bool
DisableDownload bool
DisableTermination bool
DisableCors bool
CorsAllowOrigin string
CorsAllowCredentials bool
CorsAllowMethods string
CorsAllowHeaders string
CorsMaxAge string
CorsExposeHeaders string
NetworkTimeout time.Duration
S3Bucket string
S3ObjectPrefix string
S3Endpoint string
S3PartSize int64
S3MaxBufferedParts int64
S3DisableContentHashes bool
S3DisableSSL bool
S3ConcurrentPartUploads int
GCSBucket string
GCSObjectPrefix string
AzStorage string
AzContainerAccessType string
AzBlobAccessTier string
AzObjectPrefix string
AzEndpoint string
EnabledHooksString string
PluginHookPath string
FileHooksDir string
HttpHooksEndpoint string
HttpHooksForwardHeaders string
HttpHooksRetry int
HttpHooksBackoff time.Duration
GrpcHooksEndpoint string
GrpcHooksRetry int
GrpcHooksBackoff time.Duration
EnabledHooks []hooks.HookType
ProgressHooksInterval time.Duration
ShowVersion bool
ExposeMetrics bool
MetricsPath string
ExposePprof bool
PprofPath string
PprofBlockProfileRate int
PprofMutexProfileRate int
BehindProxy bool
VerboseOutput bool
LogFormat string
S3TransferAcceleration bool
TLSCertFile string
TLSKeyFile string
TLSMode string
ShutdownTimeout time.Duration
AcquireLockTimeout time.Duration
FilelockHolderPollInterval time.Duration
FilelockAcquirerPollInterval time.Duration
GracefulRequestCompletionTimeout time.Duration
ExperimentalProtocol bool
}
func ParseFlags() {
fs := grouped_flags.NewFlagGroupSet(flag.ExitOnError)
fs.AddGroup("Listening options", func(f *flag.FlagSet) {
f.StringVar(&Flags.HttpHost, "host", "0.0.0.0", "Host to bind HTTP server to")
f.StringVar(&Flags.HttpPort, "port", "8080", "Port to bind HTTP server to")
f.StringVar(&Flags.HttpSock, "unix-sock", "", "If set, will listen to a UNIX socket at this location instead of a TCP socket")
f.StringVar(&Flags.Basepath, "base-path", "/files/", "Basepath of the HTTP server")
f.BoolVar(&Flags.BehindProxy, "behind-proxy", false, "Respect X-Forwarded-* and similar headers which may be set by proxies")
})
fs.AddGroup("TLS options", func(f *flag.FlagSet) {
f.StringVar(&Flags.TLSCertFile, "tls-certificate", "", "Path to the file containing the x509 TLS certificate to be used. The file should also contain any intermediate certificates and the CA certificate.")
f.StringVar(&Flags.TLSKeyFile, "tls-key", "", "Path to the file containing the key for the TLS certificate.")
f.StringVar(&Flags.TLSMode, "tls-mode", "tls12", "Specify which TLS mode to use; valid modes are tls13, tls12, and tls12-strong.")
})
fs.AddGroup("Upload protocol options", func(f *flag.FlagSet) {
f.BoolVar(&Flags.ExperimentalProtocol, "enable-experimental-protocol", false, "Enable support for the new resumable upload protocol draft from the IETF's HTTP working group, next to the current tus v1 protocol. (experimental and may be removed/changed in the future)")
f.BoolVar(&Flags.DisableDownload, "disable-download", false, "Disable the download endpoint")
f.BoolVar(&Flags.DisableTermination, "disable-termination", false, "Disable the termination endpoint")
f.Int64Var(&Flags.MaxSize, "max-size", 0, "Maximum size of a single upload in bytes")
})
fs.AddGroup("CORS options", func(f *flag.FlagSet) {
f.BoolVar(&Flags.DisableCors, "disable-cors", false, "Disable CORS headers")
f.StringVar(&Flags.CorsAllowOrigin, "cors-allow-origin", ".*", "Regular expression used to determine if the Origin header is allowed. If not, no CORS headers will be sent. By default, all origins are allowed.")
f.BoolVar(&Flags.CorsAllowCredentials, "cors-allow-credentials", false, "Allow credentials by setting Access-Control-Allow-Credentials: true")
f.StringVar(&Flags.CorsAllowMethods, "cors-allow-methods", "", "Comma-separated list of request methods that are included in Access-Control-Allow-Methods in addition to the ones required by tusd")
f.StringVar(&Flags.CorsAllowHeaders, "cors-allow-headers", "", "Comma-separated list of headers that are included in Access-Control-Allow-Headers in addition to the ones required by tusd")
f.StringVar(&Flags.CorsMaxAge, "cors-max-age", "86400", "Value of the Access-Control-Max-Age header to control the cache duration of CORS responses.")
f.StringVar(&Flags.CorsExposeHeaders, "cors-expose-headers", "", "Comma-separated list of headers that are included in Access-Control-Expose-Headers in addition to the ones required by tusd")
})
fs.AddGroup("File storage option", func(f *flag.FlagSet) {
f.StringVar(&Flags.UploadDir, "upload-dir", "./data", "Directory to store uploads in")
f.DurationVar(&Flags.FilelockHolderPollInterval, "filelock-holder-poll-interval", 5*time.Second, "The holder of a lock polls regularly to see if another request handler needs the lock. This flag specifies the poll interval.")
f.DurationVar(&Flags.FilelockAcquirerPollInterval, "filelock-acquirer-poll-interval", 2*time.Second, "The acquirer of a lock polls regularly to see if the lock has been released. This flag specifies the poll interval.")
})
fs.AddGroup("AWS S3 storage options", func(f *flag.FlagSet) {
f.StringVar(&Flags.S3Bucket, "s3-bucket", "", "Use AWS S3 with this bucket as storage backend (requires the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION environment variables to be set)")
f.StringVar(&Flags.S3ObjectPrefix, "s3-object-prefix", "", "Prefix for S3 object names")
f.StringVar(&Flags.S3Endpoint, "s3-endpoint", "", "Endpoint to use S3 compatible implementations like minio (requires s3-bucket to be pass)")
f.Int64Var(&Flags.S3PartSize, "s3-part-size", 50*1024*1024, "Size in bytes of the individual upload requests made to the S3 API. Defaults to 50MiB (experimental and may be removed in the future)")
f.Int64Var(&Flags.S3MaxBufferedParts, "s3-max-buffered-parts", 20, "Size in bytes of the individual upload requests made to the S3 API. Defaults to 50MiB (experimental and may be removed in the future)")
f.BoolVar(&Flags.S3DisableContentHashes, "s3-disable-content-hashes", false, "Disable the calculation of MD5 and SHA256 hashes for the content that gets uploaded to S3 for minimized CPU usage (experimental and may be removed in the future)")
f.BoolVar(&Flags.S3DisableSSL, "s3-disable-ssl", false, "Disable SSL and only use HTTP for communication with S3 (experimental and may be removed in the future)")
f.IntVar(&Flags.S3ConcurrentPartUploads, "s3-concurrent-part-uploads", 10, "Number of concurrent part uploads to S3 (experimental and may be removed in the future)")
f.BoolVar(&Flags.S3TransferAcceleration, "s3-transfer-acceleration", false, "Use AWS S3 transfer acceleration endpoint (requires -s3-bucket option and Transfer Acceleration property on S3 bucket to be set)")
})
fs.AddGroup("Google Cloud Storage options", func(f *flag.FlagSet) {
f.StringVar(&Flags.GCSBucket, "gcs-bucket", "", "Use Google Cloud Storage with this bucket as storage backend (requires the GCS_SERVICE_ACCOUNT_FILE environment variable to be set)")
f.StringVar(&Flags.GCSObjectPrefix, "gcs-object-prefix", "", "Prefix for GCS object names")
})
fs.AddGroup("Azure Storage options", func(f *flag.FlagSet) {
f.StringVar(&Flags.AzStorage, "azure-storage", "", "Use Azure BlockBlob Storage with this container name as a storage backend (requires the AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_KEY environment variable to be set)")
f.StringVar(&Flags.AzContainerAccessType, "azure-container-access-type", "", "Access type when creating a new container if it does not exist (possible values: blob, container, '')")
f.StringVar(&Flags.AzBlobAccessTier, "azure-blob-access-tier", "", "Blob access tier when uploading new files (possible values: archive, cool, hot, '')")
f.StringVar(&Flags.AzObjectPrefix, "azure-object-prefix", "", "Prefix for Azure object names")
f.StringVar(&Flags.AzEndpoint, "azure-endpoint", "", "Custom Endpoint to use for Azure BlockBlob Storage (requires azure-storage to be pass)")
})
fs.AddGroup("General hook options", func(f *flag.FlagSet) {
f.StringVar(&Flags.EnabledHooksString, "hooks-enabled-events", "pre-create,post-create,post-receive,post-terminate,post-finish", "Comma separated list of enabled hook events (e.g. post-create,post-finish). Leave empty to enable default events")
f.DurationVar(&Flags.ProgressHooksInterval, "progress-hooks-interval", 1*time.Second, "Interval at which the post-receive progress hooks are emitted for each active upload")
})
fs.AddGroup("File hook options", func(f *flag.FlagSet) {
f.StringVar(&Flags.FileHooksDir, "hooks-dir", "", "Directory to search for available hooks scripts")
})
fs.AddGroup("HTTP hook options", func(f *flag.FlagSet) {
f.StringVar(&Flags.HttpHooksEndpoint, "hooks-http", "", "An HTTP endpoint to which hook events will be sent to")
f.StringVar(&Flags.HttpHooksForwardHeaders, "hooks-http-forward-headers", "", "List of HTTP request headers to be forwarded from the client request to the hook endpoint")
f.IntVar(&Flags.HttpHooksRetry, "hooks-http-retry", 3, "Number of times to retry on a 500 or network timeout")
f.DurationVar(&Flags.HttpHooksBackoff, "hooks-http-backoff", 1*time.Second, "Wait period before retrying each retry")
})
fs.AddGroup("gRPC hook options", func(f *flag.FlagSet) {
f.StringVar(&Flags.GrpcHooksEndpoint, "hooks-grpc", "", "An gRPC endpoint to which hook events will be sent to")
f.IntVar(&Flags.GrpcHooksRetry, "hooks-grpc-retry", 3, "Number of times to retry on a server error or network timeout")
f.DurationVar(&Flags.GrpcHooksBackoff, "hooks-grpc-backoff", 1*time.Second, "Wait period before retrying each retry")
})
fs.AddGroup("Plugin hook options", func(f *flag.FlagSet) {
f.StringVar(&Flags.PluginHookPath, "hooks-plugin", "", "Path to a Go plugin for loading hook functions")
})
fs.AddGroup("Monitoring, profiling, logging options", func(f *flag.FlagSet) {
f.BoolVar(&Flags.ExposeMetrics, "expose-metrics", true, "Expose metrics about tusd usage")
f.StringVar(&Flags.MetricsPath, "metrics-path", "/metrics", "Path under which the metrics endpoint will be accessible")
f.BoolVar(&Flags.ExposePprof, "expose-pprof", false, "Expose the pprof interface over HTTP for profiling tusd")
f.StringVar(&Flags.PprofPath, "pprof-path", "/debug/pprof/", "Path under which the pprof endpoint will be accessible")
f.IntVar(&Flags.PprofBlockProfileRate, "pprof-block-profile-rate", 0, "Fraction of goroutine blocking events that are reported in the blocking profile")
f.IntVar(&Flags.PprofMutexProfileRate, "pprof-mutex-profile-rate", 0, "Fraction of mutex contention events that are reported in the mutex profile")
f.BoolVar(&Flags.ShowGreeting, "show-greeting", true, "Show the greeting message")
f.BoolVar(&Flags.ShowVersion, "version", false, "Print tusd version information")
f.BoolVar(&Flags.VerboseOutput, "verbose", true, "Enable verbose logging output")
f.StringVar(&Flags.LogFormat, "log-format", "text", "Logging format (text or json)")
})
fs.AddGroup("Timeout options", func(f *flag.FlagSet) {
f.DurationVar(&Flags.NetworkTimeout, "network-timeout", 60*time.Second, "Timeout for reading the request and writing the response. If the tusd does not receive data for this duration, it will consider the connection dead.")
f.DurationVar(&Flags.ShutdownTimeout, "shutdown-timeout", 10*time.Second, "Timeout for closing connections gracefully during shutdown. After the timeout, tusd will exit regardless of any open connection.")
f.DurationVar(&Flags.AcquireLockTimeout, "acquire-lock-timeout", 20*time.Second, "Timeout for a request handler to wait for acquiring the upload lock.")
f.DurationVar(&Flags.GracefulRequestCompletionTimeout, "request-completion-timeout", 10*time.Second, "Period after which all request operations are cancelled when the request is stopped by the client.")
})
fs.Parse()
SetEnabledHooks()
if Flags.FileHooksDir != "" {
Flags.FileHooksDir, _ = filepath.Abs(Flags.FileHooksDir)
}
SetupStructuredLogger()
}
func SetEnabledHooks() {
if Flags.EnabledHooksString != "" {
slc := strings.Split(Flags.EnabledHooksString, ",")
for i, h := range slc {
slc[i] = strings.TrimSpace(h)
if !slices.Contains(hooks.AvailableHooks, hooks.HookType(h)) {
stderr.Fatalf("Unknown hook event type in -hooks-enabled-events flag: %s", h)
}
Flags.EnabledHooks = append(Flags.EnabledHooks, hooks.HookType(h))
}
}
if len(Flags.EnabledHooks) == 0 {
Flags.EnabledHooks = hooks.AvailableHooks
}
}