summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/caddy/main.go1
-rw-r--r--cmd/commands.go81
-rw-r--r--cmd/main.go65
3 files changed, 131 insertions, 16 deletions
diff --git a/cmd/caddy/main.go b/cmd/caddy/main.go
index c1824d7..5f6b8bb 100644
--- a/cmd/caddy/main.go
+++ b/cmd/caddy/main.go
@@ -18,6 +18,7 @@ import (
caddycmd "github.com/caddyserver/caddy/v2/cmd"
// this is where modules get plugged in
+ _ "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
_ "github.com/caddyserver/caddy/v2/modules/caddyhttp"
_ "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode"
_ "github.com/caddyserver/caddy/v2/modules/caddyhttp/encode/brotli"
diff --git a/cmd/commands.go b/cmd/commands.go
index e63e2d5..99ec642 100644
--- a/cmd/commands.go
+++ b/cmd/commands.go
@@ -31,6 +31,7 @@ import (
"strings"
"github.com/caddyserver/caddy/v2"
+ "github.com/caddyserver/caddy/v2/caddyconfig"
"github.com/mholt/certmagic"
"github.com/mitchellh/go-ps"
)
@@ -38,6 +39,7 @@ import (
func cmdStart() (int, error) {
startCmd := flag.NewFlagSet("start", flag.ExitOnError)
startCmdConfigFlag := startCmd.String("config", "", "Configuration file")
+ startCmdConfigAdapterFlag := startCmd.String("config-adapter", "", "Name of config adapter to apply")
startCmd.Parse(os.Args[2:])
// open a listener to which the child process will connect when
@@ -62,6 +64,9 @@ func cmdStart() (int, error) {
if *startCmdConfigFlag != "" {
cmd.Args = append(cmd.Args, "--config", *startCmdConfigFlag)
}
+ if *startCmdConfigAdapterFlag != "" {
+ cmd.Args = append(cmd.Args, "--config-adapter", *startCmdConfigAdapterFlag)
+ }
stdinpipe, err := cmd.StdinPipe()
if err != nil {
return caddy.ExitCodeFailedStartup,
@@ -137,7 +142,8 @@ func cmdStart() (int, error) {
func cmdRun() (int, error) {
runCmd := flag.NewFlagSet("run", flag.ExitOnError)
runCmdConfigFlag := runCmd.String("config", "", "Configuration file")
- runCmdPrintEnvFlag := runCmd.Bool("print-env", false, "Print environment (useful for debugging)")
+ runCmdConfigAdapterFlag := runCmd.String("config-adapter", "", "Name of config adapter to apply")
+ runCmdPrintEnvFlag := runCmd.Bool("print-env", false, "Print environment")
runCmdPingbackFlag := runCmd.String("pingback", "", "Echo confirmation bytes to this address on success")
runCmd.Parse(os.Args[2:])
@@ -149,16 +155,10 @@ func cmdRun() (int, error) {
}
}
- // if a config file was specified for bootstrapping
- // the server instance, load it now
- var config []byte
- if *runCmdConfigFlag != "" {
- var err error
- config, err = ioutil.ReadFile(*runCmdConfigFlag)
- if err != nil {
- return caddy.ExitCodeFailedStartup,
- fmt.Errorf("reading config file: %v", err)
- }
+ // get the config in caddy's native format
+ config, err := loadConfig(*runCmdConfigFlag, *runCmdConfigAdapterFlag)
+ if err != nil {
+ return caddy.ExitCodeFailedStartup, err
}
// set a fitting User-Agent for ACME requests
@@ -167,7 +167,7 @@ func cmdRun() (int, error) {
certmagic.UserAgent = "Caddy/" + cleanModVersion
// start the admin endpoint along with any initial config
- err := caddy.StartAdmin(config)
+ err = caddy.StartAdmin(config)
if err != nil {
return caddy.ExitCodeFailedStartup,
fmt.Errorf("starting caddy administration endpoint: %v", err)
@@ -226,6 +226,7 @@ func cmdStop() (int, error) {
func cmdReload() (int, error) {
reloadCmd := flag.NewFlagSet("load", flag.ExitOnError)
reloadCmdConfigFlag := reloadCmd.String("config", "", "Configuration file")
+ reloadCmdConfigAdapterFlag := reloadCmd.String("config-adapter", "", "Name of config adapter to apply")
reloadCmdAddrFlag := reloadCmd.String("address", "", "Address of the administration listener, if different from config")
reloadCmd.Parse(os.Args[2:])
@@ -235,11 +236,10 @@ func cmdReload() (int, error) {
fmt.Errorf("no configuration to load (use --config)")
}
- // load the configuration file
- config, err := ioutil.ReadFile(*reloadCmdConfigFlag)
+ // get the config in caddy's native format
+ config, err := loadConfig(*reloadCmdConfigFlag, *reloadCmdConfigAdapterFlag)
if err != nil {
- return caddy.ExitCodeFailedStartup,
- fmt.Errorf("reading config file: %v", err)
+ return caddy.ExitCodeFailedStartup, err
}
// get the address of the admin listener and craft endpoint URL
@@ -306,3 +306,52 @@ func cmdEnviron() (int, error) {
}
return caddy.ExitCodeSuccess, nil
}
+
+func cmdAdaptConfig() (int, error) {
+ adaptCmd := flag.NewFlagSet("adapt", flag.ExitOnError)
+ adaptCmdAdapterFlag := adaptCmd.String("adapter", "", "Name of config adapter")
+ adaptCmdInputFlag := adaptCmd.String("input", "", "Configuration file to adapt")
+ adaptCmdPrettyFlag := adaptCmd.Bool("pretty", false, "Format the output for human readability")
+ adaptCmd.Parse(os.Args[2:])
+
+ if *adaptCmdAdapterFlag == "" || *adaptCmdInputFlag == "" {
+ return caddy.ExitCodeFailedStartup,
+ fmt.Errorf("usage: caddy adapt-config --adapter <name> --input <file>")
+ }
+
+ cfgAdapter := caddyconfig.GetAdapter(*adaptCmdAdapterFlag)
+ if cfgAdapter == nil {
+ return caddy.ExitCodeFailedStartup,
+ fmt.Errorf("unrecognized config adapter: %s", *adaptCmdAdapterFlag)
+ }
+
+ input, err := ioutil.ReadFile(*adaptCmdInputFlag)
+ if err != nil {
+ return caddy.ExitCodeFailedStartup,
+ fmt.Errorf("reading input file: %v", err)
+ }
+
+ opts := make(map[string]string)
+ if *adaptCmdPrettyFlag {
+ opts["pretty"] = "true"
+ }
+
+ adaptedConfig, warnings, err := cfgAdapter.Adapt(input, opts)
+ if err != nil {
+ return caddy.ExitCodeFailedStartup, err
+ }
+
+ // print warnings to stderr
+ for _, warn := range warnings {
+ msg := warn.Message
+ if warn.Directive != "" {
+ msg = fmt.Sprintf("%s: %s", warn.Directive, warn.Message)
+ }
+ log.Printf("[WARNING][%s] %s:%d: %s", *adaptCmdAdapterFlag, warn.File, warn.Line, msg)
+ }
+
+ // print result to stdout
+ fmt.Println(string(adaptedConfig))
+
+ return caddy.ExitCodeSuccess, nil
+}
diff --git a/cmd/main.go b/cmd/main.go
index 16d065b..e0a3686 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -25,6 +25,7 @@ import (
"os"
"github.com/caddyserver/caddy/v2"
+ "github.com/caddyserver/caddy/v2/caddyconfig"
)
// Main implements the main function of the caddy command.
@@ -62,6 +63,7 @@ var commands = map[string]commandFunc{
"version": cmdVersion,
"list-modules": cmdListModules,
"environ": cmdEnviron,
+ "adapt-config": cmdAdaptConfig,
}
func usageString() string {
@@ -85,3 +87,66 @@ func handlePingbackConn(conn net.Conn, expect []byte) error {
}
return nil
}
+
+// loadConfig loads the config from configFile and adapts it
+// using adapterName. If adapterName is specified, configFile
+// must be also. It prints any warnings to stderr, and returns
+// the resulting JSON config bytes.
+func loadConfig(configFile, adapterName string) ([]byte, error) {
+ // specifying an adapter without a config file is ambiguous
+ if configFile == "" && adapterName != "" {
+ return nil, fmt.Errorf("cannot adapt config without config file (use --config)")
+ }
+
+ // load initial config and adapter
+ var config []byte
+ var cfgAdapter caddyconfig.Adapter
+ var err error
+ if configFile != "" {
+ config, err = ioutil.ReadFile(configFile)
+ if err != nil {
+ return nil, fmt.Errorf("reading config file: %v", err)
+ }
+ } else if adapterName == "" {
+ // as a special case when no config file or adapter
+ // is specified, see if the Caddyfile adapter is
+ // plugged in, and if so, try using a default Caddyfile
+ cfgAdapter = caddyconfig.GetAdapter("caddyfile")
+ if cfgAdapter != nil {
+ config, err = ioutil.ReadFile("Caddyfile")
+ if err != nil && !os.IsNotExist(err) {
+ return nil, fmt.Errorf("reading default Caddyfile: %v", err)
+ }
+ configFile = "Caddyfile"
+ }
+ }
+
+ // load config adapter
+ if adapterName != "" {
+ cfgAdapter = caddyconfig.GetAdapter(adapterName)
+ if cfgAdapter == nil {
+ return nil, fmt.Errorf("unrecognized config adapter: %s", adapterName)
+ }
+ }
+
+ // adapt config
+ if cfgAdapter != nil {
+ adaptedConfig, warnings, err := cfgAdapter.Adapt(config, map[string]string{
+ "filename": configFile,
+ // TODO: all other options... (http-port, etc...)
+ })
+ if err != nil {
+ return nil, fmt.Errorf("adapting config using %s: %v", adapterName, err)
+ }
+ for _, warn := range warnings {
+ msg := warn.Message
+ if warn.Directive != "" {
+ msg = fmt.Sprintf("%s: %s", warn.Directive, warn.Message)
+ }
+ fmt.Printf("[WARNING][%s] %s:%d: %s", adapterName, warn.File, warn.Line, msg)
+ }
+ config = adaptedConfig
+ }
+
+ return config, nil
+}