mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-16 21:56:40 -05:00
cmd: Fix exiting with custom status code, add caddy -v
(#5874)
* Simplify variables for commands * Add --envfile support for adapt command * Carry custom status code for commands to os.Exit() * cmd: add `-v` and `--version` to root caddy command * Add `--envfile` to `caddy environ`, extract flag parsing to func --------- Co-authored-by: Mohammed Al Sahaf <msaa1990@gmail.com>
This commit is contained in:
parent
b245ecd325
commit
9c419f1e1a
5 changed files with 167 additions and 109 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,6 +12,7 @@ Caddyfile.*
|
|||
cmd/caddy/caddy
|
||||
cmd/caddy/caddy.exe
|
||||
cmd/caddy/tmp/*.exe
|
||||
cmd/caddy/.env
|
||||
|
||||
# mac specific
|
||||
.DS_Store
|
||||
|
|
30
cmd/cobra.go
30
cmd/cobra.go
|
@ -1,7 +1,11 @@
|
|||
package caddycmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
|
@ -95,15 +99,22 @@ https://caddyserver.com/docs/running
|
|||
// kind of annoying to have all the help text printed out if
|
||||
// caddy has an error provisioning its modules, for instance...
|
||||
SilenceUsage: true,
|
||||
Version: onlyVersionText(),
|
||||
}
|
||||
|
||||
const fullDocsFooter = `Full documentation is available at:
|
||||
https://caddyserver.com/docs/command-line`
|
||||
|
||||
func init() {
|
||||
rootCmd.SetVersionTemplate("{{.Version}}")
|
||||
rootCmd.SetHelpTemplate(rootCmd.HelpTemplate() + "\n" + fullDocsFooter + "\n")
|
||||
}
|
||||
|
||||
func onlyVersionText() string {
|
||||
_, f := caddy.Version()
|
||||
return f
|
||||
}
|
||||
|
||||
func caddyCmdToCobra(caddyCmd Command) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: caddyCmd.Name,
|
||||
|
@ -123,7 +134,24 @@ func caddyCmdToCobra(caddyCmd Command) *cobra.Command {
|
|||
// in a cobra command's RunE field.
|
||||
func WrapCommandFuncForCobra(f CommandFunc) func(cmd *cobra.Command, _ []string) error {
|
||||
return func(cmd *cobra.Command, _ []string) error {
|
||||
_, err := f(Flags{cmd.Flags()})
|
||||
status, err := f(Flags{cmd.Flags()})
|
||||
if status > 1 {
|
||||
cmd.SilenceErrors = true
|
||||
return &exitError{ExitCode: status, Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// exitError carries the exit code from CommandFunc to Main()
|
||||
type exitError struct {
|
||||
ExitCode int
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *exitError) Error() string {
|
||||
if e.Err == nil {
|
||||
return fmt.Sprintf("exiting with status %d", e.ExitCode)
|
||||
}
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
|
|
@ -42,14 +42,14 @@ import (
|
|||
)
|
||||
|
||||
func cmdStart(fl Flags) (int, error) {
|
||||
startCmdConfigFlag := fl.String("config")
|
||||
startCmdConfigAdapterFlag := fl.String("adapter")
|
||||
startCmdPidfileFlag := fl.String("pidfile")
|
||||
startCmdWatchFlag := fl.Bool("watch")
|
||||
configFlag := fl.String("config")
|
||||
configAdapterFlag := fl.String("adapter")
|
||||
pidfileFlag := fl.String("pidfile")
|
||||
watchFlag := fl.Bool("watch")
|
||||
|
||||
var err error
|
||||
var startCmdEnvfileFlag []string
|
||||
startCmdEnvfileFlag, err = fl.GetStringSlice("envfile")
|
||||
var envfileFlag []string
|
||||
envfileFlag, err = fl.GetStringSlice("envfile")
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("reading envfile flag: %v", err)
|
||||
|
@ -74,23 +74,23 @@ func cmdStart(fl Flags) (int, error) {
|
|||
// sure by giving it some random bytes and having it echo
|
||||
// them back to us)
|
||||
cmd := exec.Command(os.Args[0], "run", "--pingback", ln.Addr().String())
|
||||
if startCmdConfigFlag != "" {
|
||||
cmd.Args = append(cmd.Args, "--config", startCmdConfigFlag)
|
||||
if configFlag != "" {
|
||||
cmd.Args = append(cmd.Args, "--config", configFlag)
|
||||
}
|
||||
|
||||
for _, envFile := range startCmdEnvfileFlag {
|
||||
cmd.Args = append(cmd.Args, "--envfile", envFile)
|
||||
for _, envfile := range envfileFlag {
|
||||
cmd.Args = append(cmd.Args, "--envfile", envfile)
|
||||
}
|
||||
if startCmdConfigAdapterFlag != "" {
|
||||
cmd.Args = append(cmd.Args, "--adapter", startCmdConfigAdapterFlag)
|
||||
if configAdapterFlag != "" {
|
||||
cmd.Args = append(cmd.Args, "--adapter", configAdapterFlag)
|
||||
}
|
||||
if startCmdWatchFlag {
|
||||
if watchFlag {
|
||||
cmd.Args = append(cmd.Args, "--watch")
|
||||
}
|
||||
if startCmdPidfileFlag != "" {
|
||||
cmd.Args = append(cmd.Args, "--pidfile", startCmdPidfileFlag)
|
||||
if pidfileFlag != "" {
|
||||
cmd.Args = append(cmd.Args, "--pidfile", pidfileFlag)
|
||||
}
|
||||
stdinpipe, err := cmd.StdinPipe()
|
||||
stdinPipe, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("creating stdin pipe: %v", err)
|
||||
|
@ -102,7 +102,8 @@ func cmdStart(fl Flags) (int, error) {
|
|||
expect := make([]byte, 32)
|
||||
_, err = rand.Read(expect)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("generating random confirmation bytes: %v", err)
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("generating random confirmation bytes: %v", err)
|
||||
}
|
||||
|
||||
// begin writing the confirmation bytes to the child's
|
||||
|
@ -110,14 +111,15 @@ func cmdStart(fl Flags) (int, error) {
|
|||
// started yet, and writing synchronously would result
|
||||
// in a deadlock
|
||||
go func() {
|
||||
_, _ = stdinpipe.Write(expect)
|
||||
stdinpipe.Close()
|
||||
_, _ = stdinPipe.Write(expect)
|
||||
stdinPipe.Close()
|
||||
}()
|
||||
|
||||
// start the process
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("starting caddy process: %v", err)
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("starting caddy process: %v", err)
|
||||
}
|
||||
|
||||
// there are two ways we know we're done: either
|
||||
|
@ -165,47 +167,37 @@ func cmdStart(fl Flags) (int, error) {
|
|||
func cmdRun(fl Flags) (int, error) {
|
||||
caddy.TrapSignals()
|
||||
|
||||
runCmdConfigFlag := fl.String("config")
|
||||
runCmdConfigAdapterFlag := fl.String("adapter")
|
||||
runCmdResumeFlag := fl.Bool("resume")
|
||||
runCmdPrintEnvFlag := fl.Bool("environ")
|
||||
runCmdWatchFlag := fl.Bool("watch")
|
||||
runCmdPidfileFlag := fl.String("pidfile")
|
||||
runCmdPingbackFlag := fl.String("pingback")
|
||||
|
||||
var err error
|
||||
var runCmdLoadEnvfileFlag []string
|
||||
runCmdLoadEnvfileFlag, err = fl.GetStringSlice("envfile")
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("reading envfile flag: %v", err)
|
||||
}
|
||||
configFlag := fl.String("config")
|
||||
configAdapterFlag := fl.String("adapter")
|
||||
resumeFlag := fl.Bool("resume")
|
||||
printEnvFlag := fl.Bool("environ")
|
||||
watchFlag := fl.Bool("watch")
|
||||
pidfileFlag := fl.String("pidfile")
|
||||
pingbackFlag := fl.String("pingback")
|
||||
|
||||
// load all additional envs as soon as possible
|
||||
for _, envFile := range runCmdLoadEnvfileFlag {
|
||||
if err := loadEnvFromFile(envFile); err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("loading additional environment variables: %v", err)
|
||||
}
|
||||
err := handleEnvFileFlag(fl)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
// if we are supposed to print the environment, do that first
|
||||
if runCmdPrintEnvFlag {
|
||||
if printEnvFlag {
|
||||
printEnvironment()
|
||||
}
|
||||
|
||||
// load the config, depending on flags
|
||||
var config []byte
|
||||
if runCmdResumeFlag {
|
||||
if resumeFlag {
|
||||
config, err = os.ReadFile(caddy.ConfigAutosavePath)
|
||||
if os.IsNotExist(err) {
|
||||
// not a bad error; just can't resume if autosave file doesn't exist
|
||||
caddy.Log().Info("no autosave file exists", zap.String("autosave_file", caddy.ConfigAutosavePath))
|
||||
runCmdResumeFlag = false
|
||||
resumeFlag = false
|
||||
} else if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
} else {
|
||||
if runCmdConfigFlag == "" {
|
||||
if configFlag == "" {
|
||||
caddy.Log().Info("resuming from last configuration",
|
||||
zap.String("autosave_file", caddy.ConfigAutosavePath))
|
||||
} else {
|
||||
|
@ -218,19 +210,19 @@ func cmdRun(fl Flags) (int, error) {
|
|||
}
|
||||
// we don't use 'else' here since this value might have been changed in 'if' block; i.e. not mutually exclusive
|
||||
var configFile string
|
||||
if !runCmdResumeFlag {
|
||||
config, configFile, err = LoadConfig(runCmdConfigFlag, runCmdConfigAdapterFlag)
|
||||
if !resumeFlag {
|
||||
config, configFile, err = LoadConfig(configFlag, configAdapterFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
}
|
||||
|
||||
// create pidfile now, in case loading config takes a while (issue #5477)
|
||||
if runCmdPidfileFlag != "" {
|
||||
err := caddy.PIDFile(runCmdPidfileFlag)
|
||||
if pidfileFlag != "" {
|
||||
err := caddy.PIDFile(pidfileFlag)
|
||||
if err != nil {
|
||||
caddy.Log().Error("unable to write PID file",
|
||||
zap.String("pidfile", runCmdPidfileFlag),
|
||||
zap.String("pidfile", pidfileFlag),
|
||||
zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
@ -244,13 +236,13 @@ func cmdRun(fl Flags) (int, error) {
|
|||
|
||||
// if we are to report to another process the successful start
|
||||
// of the server, do so now by echoing back contents of stdin
|
||||
if runCmdPingbackFlag != "" {
|
||||
if pingbackFlag != "" {
|
||||
confirmationBytes, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("reading confirmation bytes from stdin: %v", err)
|
||||
}
|
||||
conn, err := net.Dial("tcp", runCmdPingbackFlag)
|
||||
conn, err := net.Dial("tcp", pingbackFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("dialing confirmation address: %v", err)
|
||||
|
@ -259,14 +251,14 @@ func cmdRun(fl Flags) (int, error) {
|
|||
_, err = conn.Write(confirmationBytes)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("writing confirmation bytes to %s: %v", runCmdPingbackFlag, err)
|
||||
fmt.Errorf("writing confirmation bytes to %s: %v", pingbackFlag, err)
|
||||
}
|
||||
}
|
||||
|
||||
// if enabled, reload config file automatically on changes
|
||||
// (this better only be used in dev!)
|
||||
if runCmdWatchFlag {
|
||||
go watchConfigFile(configFile, runCmdConfigAdapterFlag)
|
||||
if watchFlag {
|
||||
go watchConfigFile(configFile, configAdapterFlag)
|
||||
}
|
||||
|
||||
// warn if the environment does not provide enough information about the disk
|
||||
|
@ -292,11 +284,11 @@ func cmdRun(fl Flags) (int, error) {
|
|||
}
|
||||
|
||||
func cmdStop(fl Flags) (int, error) {
|
||||
addrFlag := fl.String("address")
|
||||
addressFlag := fl.String("address")
|
||||
configFlag := fl.String("config")
|
||||
configAdapterFlag := fl.String("adapter")
|
||||
|
||||
adminAddr, err := DetermineAdminAPIAddress(addrFlag, nil, configFlag, configAdapterFlag)
|
||||
adminAddr, err := DetermineAdminAPIAddress(addressFlag, nil, configFlag, configAdapterFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("couldn't determine admin API address: %v", err)
|
||||
}
|
||||
|
@ -314,7 +306,7 @@ func cmdStop(fl Flags) (int, error) {
|
|||
func cmdReload(fl Flags) (int, error) {
|
||||
configFlag := fl.String("config")
|
||||
configAdapterFlag := fl.String("adapter")
|
||||
addrFlag := fl.String("address")
|
||||
addressFlag := fl.String("address")
|
||||
forceFlag := fl.Bool("force")
|
||||
|
||||
// get the config in caddy's native format
|
||||
|
@ -326,7 +318,7 @@ func cmdReload(fl Flags) (int, error) {
|
|||
return caddy.ExitCodeFailedStartup, fmt.Errorf("no config file to load")
|
||||
}
|
||||
|
||||
adminAddr, err := DetermineAdminAPIAddress(addrFlag, config, configFlag, configAdapterFlag)
|
||||
adminAddr, err := DetermineAdminAPIAddress(addressFlag, config, configFlag, configAdapterFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("couldn't determine admin API address: %v", err)
|
||||
}
|
||||
|
@ -428,48 +420,60 @@ func cmdListModules(fl Flags) (int, error) {
|
|||
return caddy.ExitCodeSuccess, nil
|
||||
}
|
||||
|
||||
func cmdEnviron(_ Flags) (int, error) {
|
||||
func cmdEnviron(fl Flags) (int, error) {
|
||||
// load all additional envs as soon as possible
|
||||
err := handleEnvFileFlag(fl)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
printEnvironment()
|
||||
return caddy.ExitCodeSuccess, nil
|
||||
}
|
||||
|
||||
func cmdAdaptConfig(fl Flags) (int, error) {
|
||||
adaptCmdInputFlag := fl.String("config")
|
||||
adaptCmdAdapterFlag := fl.String("adapter")
|
||||
adaptCmdPrettyFlag := fl.Bool("pretty")
|
||||
adaptCmdValidateFlag := fl.Bool("validate")
|
||||
inputFlag := fl.String("config")
|
||||
adapterFlag := fl.String("adapter")
|
||||
prettyFlag := fl.Bool("pretty")
|
||||
validateFlag := fl.Bool("validate")
|
||||
|
||||
var err error
|
||||
adaptCmdInputFlag, err = configFileWithRespectToDefault(caddy.Log(), adaptCmdInputFlag)
|
||||
inputFlag, err = configFileWithRespectToDefault(caddy.Log(), inputFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
if adaptCmdAdapterFlag == "" {
|
||||
// load all additional envs as soon as possible
|
||||
err = handleEnvFileFlag(fl)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
if adapterFlag == "" {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("adapter name is required (use --adapt flag or leave unspecified for default)")
|
||||
}
|
||||
|
||||
cfgAdapter := caddyconfig.GetAdapter(adaptCmdAdapterFlag)
|
||||
cfgAdapter := caddyconfig.GetAdapter(adapterFlag)
|
||||
if cfgAdapter == nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("unrecognized config adapter: %s", adaptCmdAdapterFlag)
|
||||
fmt.Errorf("unrecognized config adapter: %s", adapterFlag)
|
||||
}
|
||||
|
||||
input, err := os.ReadFile(adaptCmdInputFlag)
|
||||
input, err := os.ReadFile(inputFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("reading input file: %v", err)
|
||||
}
|
||||
|
||||
opts := map[string]any{"filename": adaptCmdInputFlag}
|
||||
opts := map[string]any{"filename": inputFlag}
|
||||
|
||||
adaptedConfig, warnings, err := cfgAdapter.Adapt(input, opts)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
||||
if adaptCmdPrettyFlag {
|
||||
if prettyFlag {
|
||||
var prettyBuf bytes.Buffer
|
||||
err = json.Indent(&prettyBuf, adaptedConfig, "", "\t")
|
||||
if err != nil {
|
||||
|
@ -487,13 +491,13 @@ func cmdAdaptConfig(fl Flags) (int, error) {
|
|||
if warn.Directive != "" {
|
||||
msg = fmt.Sprintf("%s: %s", warn.Directive, warn.Message)
|
||||
}
|
||||
caddy.Log().Named(adaptCmdAdapterFlag).Warn(msg,
|
||||
caddy.Log().Named(adapterFlag).Warn(msg,
|
||||
zap.String("file", warn.File),
|
||||
zap.Int("line", warn.Line))
|
||||
}
|
||||
|
||||
// validate output if requested
|
||||
if adaptCmdValidateFlag {
|
||||
if validateFlag {
|
||||
var cfg *caddy.Config
|
||||
err = caddy.StrictUnmarshalJSON(adaptedConfig, &cfg)
|
||||
if err != nil {
|
||||
|
@ -509,36 +513,26 @@ func cmdAdaptConfig(fl Flags) (int, error) {
|
|||
}
|
||||
|
||||
func cmdValidateConfig(fl Flags) (int, error) {
|
||||
validateCmdConfigFlag := fl.String("config")
|
||||
validateCmdAdapterFlag := fl.String("adapter")
|
||||
|
||||
var err error
|
||||
var runCmdLoadEnvfileFlag []string
|
||||
runCmdLoadEnvfileFlag, err = fl.GetStringSlice("envfile")
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("reading envfile flag: %v", err)
|
||||
}
|
||||
configFlag := fl.String("config")
|
||||
adapterFlag := fl.String("adapter")
|
||||
|
||||
// load all additional envs as soon as possible
|
||||
for _, envFile := range runCmdLoadEnvfileFlag {
|
||||
if err := loadEnvFromFile(envFile); err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("loading additional environment variables: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// use default config and ensure a config file is specified
|
||||
validateCmdConfigFlag, err = configFileWithRespectToDefault(caddy.Log(), validateCmdConfigFlag)
|
||||
err := handleEnvFileFlag(fl)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
if validateCmdConfigFlag == "" {
|
||||
|
||||
// use default config and ensure a config file is specified
|
||||
configFlag, err = configFileWithRespectToDefault(caddy.Log(), configFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
if configFlag == "" {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("input file required when there is no Caddyfile in current directory (use --config flag)")
|
||||
}
|
||||
|
||||
input, _, err := LoadConfig(validateCmdConfigFlag, validateCmdAdapterFlag)
|
||||
input, _, err := LoadConfig(configFlag, adapterFlag)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup, err
|
||||
}
|
||||
|
@ -561,13 +555,13 @@ func cmdValidateConfig(fl Flags) (int, error) {
|
|||
}
|
||||
|
||||
func cmdFmt(fl Flags) (int, error) {
|
||||
formatCmdConfigFile := fl.Arg(0)
|
||||
if formatCmdConfigFile == "" {
|
||||
formatCmdConfigFile = "Caddyfile"
|
||||
configFile := fl.Arg(0)
|
||||
if configFile == "" {
|
||||
configFile = "Caddyfile"
|
||||
}
|
||||
|
||||
// as a special case, read from stdin if the file name is "-"
|
||||
if formatCmdConfigFile == "-" {
|
||||
if configFile == "-" {
|
||||
input, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
|
@ -577,7 +571,7 @@ func cmdFmt(fl Flags) (int, error) {
|
|||
return caddy.ExitCodeSuccess, nil
|
||||
}
|
||||
|
||||
input, err := os.ReadFile(formatCmdConfigFile)
|
||||
input, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return caddy.ExitCodeFailedStartup,
|
||||
fmt.Errorf("reading input file: %v", err)
|
||||
|
@ -586,7 +580,7 @@ func cmdFmt(fl Flags) (int, error) {
|
|||
output := caddyfile.Format(input)
|
||||
|
||||
if fl.Bool("overwrite") {
|
||||
if err := os.WriteFile(formatCmdConfigFile, output, 0o600); err != nil {
|
||||
if err := os.WriteFile(configFile, output, 0o600); err != nil {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("overwriting formatted file: %v", err)
|
||||
}
|
||||
return caddy.ExitCodeSuccess, nil
|
||||
|
@ -610,7 +604,7 @@ func cmdFmt(fl Flags) (int, error) {
|
|||
fmt.Print(string(output))
|
||||
}
|
||||
|
||||
if warning, diff := caddyfile.FormattingDifference(formatCmdConfigFile, input); diff {
|
||||
if warning, diff := caddyfile.FormattingDifference(configFile, input); diff {
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf(`%s:%d: Caddyfile input is not formatted; Tip: use '--overwrite' to update your Caddyfile in-place instead of previewing it. Consult '--help' for more options`,
|
||||
warning.File,
|
||||
warning.Line,
|
||||
|
@ -620,6 +614,25 @@ func cmdFmt(fl Flags) (int, error) {
|
|||
return caddy.ExitCodeSuccess, nil
|
||||
}
|
||||
|
||||
// handleEnvFileFlag loads the environment variables from the given --envfile
|
||||
// flag if specified. This should be called as early in the command function.
|
||||
func handleEnvFileFlag(fl Flags) error {
|
||||
var err error
|
||||
var envfileFlag []string
|
||||
envfileFlag, err = fl.GetStringSlice("envfile")
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading envfile flag: %v", err)
|
||||
}
|
||||
|
||||
for _, envfile := range envfileFlag {
|
||||
if err := loadEnvFromFile(envfile); err != nil {
|
||||
return fmt.Errorf("loading additional environment variables: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AdminAPIRequest makes an API request according to the CLI flags given,
|
||||
// with the given HTTP method and request URI. If body is non-nil, it will
|
||||
// be assumed to be Content-Type application/json. The caller should close
|
||||
|
|
|
@ -94,8 +94,8 @@ func init() {
|
|||
Starts the Caddy process, optionally bootstrapped with an initial config file.
|
||||
This command unblocks after the server starts running or fails to run.
|
||||
|
||||
If --envfile is specified, an environment file with environment variables in
|
||||
the KEY=VALUE format will be loaded into the Caddy process.
|
||||
If --envfile is specified, an environment file with environment variables
|
||||
in the KEY=VALUE format will be loaded into the Caddy process.
|
||||
|
||||
On Windows, the spawned child process will remain attached to the terminal, so
|
||||
closing the window will forcefully stop Caddy; to avoid forgetting this, try
|
||||
|
@ -133,8 +133,8 @@ As a special case, if the current working directory has a file called
|
|||
that file will be loaded and used to configure Caddy, even without any command
|
||||
line flags.
|
||||
|
||||
If --envfile is specified, an environment file with environment variables in
|
||||
the KEY=VALUE format will be loaded into the Caddy process.
|
||||
If --envfile is specified, an environment file with environment variables
|
||||
in the KEY=VALUE format will be loaded into the Caddy process.
|
||||
|
||||
If --environ is specified, the environment as seen by the Caddy process will
|
||||
be printed before starting. This is the same as the environ command but does
|
||||
|
@ -240,6 +240,7 @@ documentation: https://go.dev/doc/modules/version-numbers
|
|||
|
||||
RegisterCommand(Command{
|
||||
Name: "environ",
|
||||
Usage: "[--envfile <path>]",
|
||||
Short: "Prints the environment",
|
||||
Long: `
|
||||
Prints the environment as seen by this Caddy process.
|
||||
|
@ -249,6 +250,9 @@ configuration uses environment variables (e.g. "{env.VARIABLE}") then
|
|||
this command can be useful for verifying that the variables will have
|
||||
the values you expect in your config.
|
||||
|
||||
If --envfile is specified, an environment file with environment variables
|
||||
in the KEY=VALUE format will be loaded into the Caddy process.
|
||||
|
||||
Note that environments may be different depending on how you run Caddy.
|
||||
Environments for Caddy instances started by service managers such as
|
||||
systemd are often different than the environment inherited from your
|
||||
|
@ -259,12 +263,15 @@ by adding the "--environ" flag.
|
|||
|
||||
Environments may contain sensitive data.
|
||||
`,
|
||||
Func: cmdEnviron,
|
||||
CobraFunc: func(cmd *cobra.Command) {
|
||||
cmd.Flags().StringSliceP("envfile", "", []string{}, "Environment file(s) to load")
|
||||
cmd.RunE = WrapCommandFuncForCobra(cmdEnviron)
|
||||
},
|
||||
})
|
||||
|
||||
RegisterCommand(Command{
|
||||
Name: "adapt",
|
||||
Usage: "--config <path> [--adapter <name>] [--pretty] [--validate]",
|
||||
Usage: "--config <path> [--adapter <name>] [--pretty] [--validate] [--envfile <path>]",
|
||||
Short: "Adapts a configuration to Caddy's native JSON",
|
||||
Long: `
|
||||
Adapts a configuration to Caddy's native JSON format and writes the
|
||||
|
@ -276,12 +283,16 @@ for human readability.
|
|||
If --validate is used, the adapted config will be checked for validity.
|
||||
If the config is invalid, an error will be printed to stderr and a non-
|
||||
zero exit status will be returned.
|
||||
|
||||
If --envfile is specified, an environment file with environment variables
|
||||
in the KEY=VALUE format will be loaded into the Caddy process.
|
||||
`,
|
||||
CobraFunc: func(cmd *cobra.Command) {
|
||||
cmd.Flags().StringP("config", "c", "", "Configuration file to adapt (required)")
|
||||
cmd.Flags().StringP("adapter", "a", "caddyfile", "Name of config adapter")
|
||||
cmd.Flags().BoolP("pretty", "p", false, "Format the output for human readability")
|
||||
cmd.Flags().BoolP("validate", "", false, "Validate the output")
|
||||
cmd.Flags().StringSliceP("envfile", "", []string{}, "Environment file(s) to load")
|
||||
cmd.RunE = WrapCommandFuncForCobra(cmdAdaptConfig)
|
||||
},
|
||||
})
|
||||
|
@ -295,8 +306,8 @@ Loads and provisions the provided config, but does not start running it.
|
|||
This reveals any errors with the configuration through the loading and
|
||||
provisioning stages.
|
||||
|
||||
If --envfile is specified, an environment file with environment variables in
|
||||
the KEY=VALUE format will be loaded into the Caddy process.
|
||||
If --envfile is specified, an environment file with environment variables
|
||||
in the KEY=VALUE format will be loaded into the Caddy process.
|
||||
`,
|
||||
CobraFunc: func(cmd *cobra.Command) {
|
||||
cmd.Flags().StringP("config", "c", "", "Input configuration file")
|
||||
|
|
|
@ -17,6 +17,7 @@ package caddycmd
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -63,6 +64,10 @@ func Main() {
|
|||
}
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
var exitError *exitError
|
||||
if errors.As(err, &exitError) {
|
||||
os.Exit(exitError.ExitCode)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue