Go API Documentation

github.com/caddyserver/caddy/v2/cmd

No package summary is available.

Package

Files: 9. Third party imports: 7. Imports from organisation: 1. Tests: 0. Benchmarks: 0.

Constants

const downloadPath = "https://caddyserver.com/api/download"
const fullDocsFooter = `Full documentation is available at:
https://caddyserver.com/docs/command-line`

Vars

Interface guard

var _ flag.Value = (*StringSlice)(nil)
var commandNameRegex = regexp.MustCompile(`^[a-z0-9]$|^([a-z0-9]+-?[a-z0-9]*)+[a-z0-9]$`)
var commands = make(map[string]Command)
var defaultFactory = newRootCommandFactory(func() *cobra.Command {
	return &cobra.Command{
		Use:	"caddy",
		Long: `Caddy is an extensible server platform written in Go.

At its core, Caddy merely manages configuration. Modules are plugged
in statically at compile-time to provide useful functionality. Caddy's
standard distribution includes common modules to serve HTTP, TLS,
and PKI applications, including the automation of certificates.

To run Caddy, use:

	- 'caddy run' to run Caddy in the foreground (recommended).
	- 'caddy start' to start Caddy in the background; only do this
	  if you will be keeping the terminal window open until you run
	  'caddy stop' to close the server.

When Caddy is started, it opens a locally-bound administrative socket
to which configuration can be POSTed via a restful HTTP API (see
https://caddyserver.com/docs/api).

Caddy's native configuration format is JSON. However, config adapters
can be used to convert other config formats to JSON when Caddy receives
its configuration. The Caddyfile is a built-in config adapter that is
popular for hand-written configurations due to its straightforward
syntax (see https://caddyserver.com/docs/caddyfile). Many third-party
adapters are available (see https://caddyserver.com/docs/config-adapters).
Use 'caddy adapt' to see how a config translates to JSON.

For convenience, the CLI can act as an HTTP client to give Caddy its
initial configuration for you. If a file named Caddyfile is in the
current working directory, it will do this automatically. Otherwise,
you can use the --config flag to specify the path to a config file.

Some special-purpose subcommands build and load a configuration file
for you directly from command line input; for example:

	- caddy file-server
	- caddy reverse-proxy
	- caddy respond

These commands disable the administration endpoint because their
configuration is specified solely on the command line.

In general, the most common way to run Caddy is simply:

	$ caddy run

Or, with a configuration file:

	$ caddy run --config caddy.json

If running interactively in a terminal, running Caddy in the
background may be more convenient:

	$ caddy start
	...
	$ caddy stop

This allows you to run other commands while Caddy stays running.
Be sure to stop Caddy before you close the terminal!

Depending on the system, Caddy may need permission to bind to low
ports. One way to do this on Linux is to use setcap:

	$ sudo setcap cap_net_bind_service=+ep $(which caddy)

Remember to run that command again after replacing the binary.

See the Caddy website for tutorials, configuration structure,
syntax, and module documentation: https://caddyserver.com/docs/

Custom Caddy builds are available on the Caddy download page at:
https://caddyserver.com/download

The xcaddy command can be used to build Caddy from source with or
without additional plugins: https://github.com/caddyserver/xcaddy

Where possible, Caddy should be installed using officially-supported
package installers: https://caddyserver.com/docs/install

Instructions for running Caddy in production are also available:
https://caddyserver.com/docs/running
`,
		Example: `  $ caddy run
  $ caddy run --config caddy.json
  $ caddy reload --config caddy.json
  $ caddy stop`,

		// 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(),
	}
})

Types

Command

Command represents a subcommand. Name, Func, and Short are required.

type Command struct {
	// The name of the subcommand. Must conform to the
	// format described by the RegisterCommand() godoc.
	// Required.
	Name	string

	// Usage is a brief message describing the syntax of
	// the subcommand's flags and args. Use [] to indicate
	// optional parameters and <> to enclose literal values
	// intended to be replaced by the user. Do not prefix
	// the string with "caddy" or the name of the command
	// since these will be prepended for you; only include
	// the actual parameters for this command.
	Usage	string

	// Short is a one-line message explaining what the
	// command does. Should not end with punctuation.
	// Required.
	Short	string

	// Long is the full help text shown to the user.
	// Will be trimmed of whitespace on both ends before
	// being printed.
	Long	string

	// Flags is the flagset for command.
	// This is ignored if CobraFunc is set.
	Flags	*flag.FlagSet

	// Func is a function that executes a subcommand using
	// the parsed flags. It returns an exit code and any
	// associated error.
	// Required if CobraFunc is not set.
	Func	CommandFunc

	// CobraFunc allows further configuration of the command
	// via cobra's APIs. If this is set, then Func and Flags
	// are ignored, with the assumption that they are set in
	// this function. A caddycmd.WrapCommandFuncForCobra helper
	// exists to simplify porting CommandFunc to Cobra's RunE.
	CobraFunc	func(*cobra.Command)
}

CommandFunc

CommandFunc is a command's function. It runs the command and returns the proper exit code along with any error that occurred.

type CommandFunc func(Flags) (int, error)

Flags

Flags wraps a FlagSet so that typed values from flags can be easily retrieved.

type Flags struct {
	*pflag.FlagSet
}

StringSlice

StringSlice is a flag.Value that enables repeated use of a string flag.

type StringSlice []string

exitError

exitError carries the exit code from CommandFunc to Main()

type exitError struct {
	ExitCode	int
	Err		error
}

moduleInfo

This type doesn't have documentation.

type moduleInfo struct {
	caddyModuleID	string
	goModule	*debug.Module
	err		error
}

pluginPackage

This type doesn't have documentation.

type pluginPackage struct {
	Version	string
	Path	string
}

rootCommandFactory

This type doesn't have documentation.

type rootCommandFactory struct {
	constructor	func() *cobra.Command
	options		[]func(*cobra.Command)
}

storVal

This type doesn't have documentation.

type storVal struct {
	StorageRaw json.RawMessage `json:"storage,omitempty" caddy:"namespace=caddy.storage inline_key=module"`
}

Functions

func AdminAPIRequest

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 the response body. Should only be used by Caddy CLI commands which need to interact with a running instance of Caddy via the admin API.

func AdminAPIRequest(adminAddr, method, uri string, headers http.Header, body io.Reader) (*http.Response, error) {
	parsedAddr, err := caddy.ParseNetworkAddress(adminAddr)
	if err != nil || parsedAddr.PortRangeSize() > 1 {
		return nil, fmt.Errorf("invalid admin address %s: %v", adminAddr, err)
	}
	origin := "http://" + parsedAddr.JoinHostPort(0)
	if parsedAddr.IsUnixNetwork() {
		origin = "http://127.0.0.1"	// bogus host is a hack so that http.NewRequest() is happy

		// the unix address at this point might still contain the optional
		// unix socket permissions, which are part of the address/host.
		// those need to be removed first, as they aren't part of the
		// resulting unix file path
		addr, _, err := internal.SplitUnixSocketPermissionsBits(parsedAddr.Host)
		if err != nil {
			return nil, err
		}
		parsedAddr.Host = addr
	} else if parsedAddr.IsFdNetwork() {
		origin = "http://127.0.0.1"
	}

	// form the request
	req, err := http.NewRequest(method, origin+uri, body)
	if err != nil {
		return nil, fmt.Errorf("making request: %v", err)
	}
	if parsedAddr.IsUnixNetwork() || parsedAddr.IsFdNetwork() {
		// We used to conform to RFC 2616 Section 14.26 which requires
		// an empty host header when there is no host, as is the case
		// with unix sockets and socket fds. However, Go required a
		// Host value so we used a hack of a space character as the host
		// (it would see the Host was non-empty, then trim the space later).
		// As of Go 1.20.6 (July 2023), this hack no longer works. See:
		// https://github.com/golang/go/issues/60374
		// See also the discussion here:
		// https://github.com/golang/go/issues/61431
		//
		// After that, we now require a Host value of either 127.0.0.1
		// or ::1 if one is set. Above I choose to use 127.0.0.1. Even
		// though the value should be completely irrelevant (it could be
		// "srldkjfsd"), if for some reason the Host *is* used, at least
		// we can have some reasonable assurance it will stay on the local
		// machine and that browsers, if they ever allow access to unix
		// sockets, can still enforce CORS, ensuring it is still coming
		// from the local machine.
	} else {
		req.Header.Set("Origin", origin)
	}
	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	for k, v := range headers {
		req.Header[k] = v
	}

	// make an HTTP client that dials our network type, since admin
	// endpoints aren't always TCP, which is what the default transport
	// expects; reuse is not of particular concern here
	client := http.Client{
		Transport: &http.Transport{
			DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
				return net.Dial(parsedAddr.Network, parsedAddr.JoinHostPort(0))
			},
		},
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("performing request: %v", err)
	}

	// if it didn't work, let the user know
	if resp.StatusCode >= 400 {
		respBody, err := io.ReadAll(io.LimitReader(resp.Body, 1024*1024*2))
		if err != nil {
			return nil, fmt.Errorf("HTTP %d: reading error message: %v", resp.StatusCode, err)
		}
		return nil, fmt.Errorf("caddy responded with error: HTTP %d: %s", resp.StatusCode, respBody)
	}

	return resp, nil
}

Cognitive complexity: 6, Cyclomatic complexity: 5

Uses: context.Context, fmt.Errorf, http.Client, http.NewRequest, http.Transport, io.LimitReader, io.ReadAll, net.Conn, net.Dial.

func Commands

Commands returns a list of commands initialised by RegisterCommand

func Commands() map[string]Command {
	return commands
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func DetermineAdminAPIAddress

DetermineAdminAPIAddress determines which admin API endpoint address should be used based on the inputs. By priority: if address is specified, then it is returned; if config is specified, then that config will be used for finding the admin address; if configFile (and configAdapter) are specified, then that config will be loaded to find the admin address; otherwise, the default admin listen address will be returned.

func DetermineAdminAPIAddress(address string, config []byte, configFile, configAdapter string) (string, error) {
	// Prefer the address if specified and non-empty
	if address != "" {
		return address, nil
	}

	// Try to load the config from file if specified, with the given adapter name
	if configFile != "" {
		var loadedConfigFile string
		var err error

		// use the provided loaded config if non-empty
		// otherwise, load it from the specified file/adapter
		loadedConfig := config
		if len(loadedConfig) == 0 {
			// get the config in caddy's native format
			loadedConfig, loadedConfigFile, err = LoadConfig(configFile, configAdapter)
			if err != nil {
				return "", err
			}
			if loadedConfigFile == "" {
				return "", fmt.Errorf("no config file to load; either use --config flag or ensure Caddyfile exists in current directory")
			}
		}

		// get the address of the admin listener from the config
		if len(loadedConfig) > 0 {
			var tmpStruct struct {
				Admin caddy.AdminConfig `json:"admin"`
			}
			err := json.Unmarshal(loadedConfig, &tmpStruct)
			if err != nil {
				return "", fmt.Errorf("unmarshaling admin listener address from config: %v", err)
			}
			if tmpStruct.Admin.Listen != "" {
				return tmpStruct.Admin.Listen, nil
			}
		}
	}

	// Fallback to the default listen address otherwise
	return caddy.DefaultAdminListen, nil
}

Cognitive complexity: 17, Cyclomatic complexity: 9

Uses: fmt.Errorf, json.Unmarshal.

func LoadConfig

LoadConfig loads the config from configFile and adapts it using adapterName. If adapterName is specified, configFile must be also. If no configFile is specified, it tries loading a default config file. The lack of a config file is not treated as an error, but false will be returned if there is no config available. It prints any warnings to stderr, and returns the resulting JSON config bytes along with the name of the loaded config file (if any).

func LoadConfig(configFile, adapterName string) ([]byte, string, error) {
	return loadConfigWithLogger(caddy.Log(), configFile, adapterName)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func Main

Main implements the main function of the caddy command. Call this if Caddy is to be the main() of your program.

func Main() {
	if len(os.Args) == 0 {
		fmt.Printf("[FATAL] no arguments provided by OS; args[0] must be command\n")
		os.Exit(caddy.ExitCodeFailedStartup)
	}

	undo, err := maxprocs.Set()
	defer undo()
	if err != nil {
		caddy.Log().Warn("failed to set GOMAXPROCS", zap.Error(err))
	}

	if err := defaultFactory.Build().Execute(); err != nil {
		var exitError *exitError
		if errors.As(err, &exitError) {
			os.Exit(exitError.ExitCode)
		}
		os.Exit(1)
	}
}

Cognitive complexity: 8, Cyclomatic complexity: 5

Uses: errors.As, fmt.Printf, maxprocs.Set, os.Args, os.Exit, zap.Error.

func RegisterCommand

RegisterCommand registers the command cmd. cmd.Name must be unique and conform to the following format:

  • lowercase
  • alphanumeric and hyphen characters only
  • cannot start or end with a hyphen
  • hyphen cannot be adjacent to another hyphen

This function panics if the name is already registered, if the name does not meet the described format, or if any of the fields are missing from cmd.

This function should be used in init().

func RegisterCommand(cmd Command) {
	if cmd.Name == "" {
		panic("command name is required")
	}
	if cmd.Func == nil && cmd.CobraFunc == nil {
		panic("command function missing")
	}
	if cmd.Short == "" {
		panic("command short string is required")
	}
	if _, exists := commands[cmd.Name]; exists {
		panic("command already registered: " + cmd.Name)
	}
	if !commandNameRegex.MatchString(cmd.Name) {
		panic("invalid command name")
	}
	defaultFactory.Use(func(rootCmd *cobra.Command) {
		rootCmd.AddCommand(caddyCmdToCobra(cmd))
	})
}

Cognitive complexity: 11, Cyclomatic complexity: 7

Uses: cobra.Command.

func WrapCommandFuncForCobra

WrapCommandFuncForCobra wraps a Caddy CommandFunc for use in a cobra command's RunE field.

func WrapCommandFuncForCobra(f CommandFunc) func(cmd *cobra.Command, _ []string) error {
	return func(cmd *cobra.Command, _ []string) error {
		status, err := f(Flags{cmd.Flags()})
		if status > 1 {
			cmd.SilenceErrors = true
			return &exitError{ExitCode: status, Err: err}
		}
		return err
	}
}

Cognitive complexity: 5, Cyclomatic complexity: 2

Uses: cobra.Command.

func (*StringSlice) Set

func (ss *StringSlice) Set(value string) error {
	*ss = append(*ss, value)
	return nil
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (*exitError) Error

func (e *exitError) Error() string {
	if e.Err == nil {
		return fmt.Sprintf("exiting with status %d", e.ExitCode)
	}
	return e.Err.Error()
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: fmt.Sprintf.

func (*rootCommandFactory) Build

func (f *rootCommandFactory) Build() *cobra.Command {
	o := f.constructor()
	for _, v := range f.options {
		v(o)
	}
	return o
}

Cognitive complexity: 3, Cyclomatic complexity: 2

func (*rootCommandFactory) Use

func (f *rootCommandFactory) Use(fn func(cmd *cobra.Command)) {
	f.options = append(f.options, fn)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (Flags) Bool

Bool returns the boolean representation of the flag given by name. It returns false if the flag is not a boolean type. It panics if the flag is not in the flag set.

func (f Flags) Bool(name string) bool {
	val, _ := strconv.ParseBool(f.String(name))
	return val
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: strconv.ParseBool.

func (Flags) Duration

Duration returns the duration representation of the flag given by name. It returns false if the flag is not a duration type. It panics if the flag is not in the flag set.

func (f Flags) Duration(name string) time.Duration {
	val, _ := caddy.ParseDuration(f.String(name))
	return val
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func (Flags) Float64

Float64 returns the float64 representation of the flag given by name. It returns false if the flag is not a float64 type. It panics if the flag is not in the flag set.

func (f Flags) Float64(name string) float64 {
	val, _ := strconv.ParseFloat(f.String(name), 64)
	return val
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: strconv.ParseFloat.

func (Flags) Int

Int returns the integer representation of the flag given by name. It returns 0 if the flag is not an integer type. It panics if the flag is not in the flag set.

func (f Flags) Int(name string) int {
	val, _ := strconv.ParseInt(f.String(name), 0, strconv.IntSize)
	return int(val)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: strconv.IntSize, strconv.ParseInt.

func (Flags) String

String returns the string representation of the flag given by name. It panics if the flag is not in the flag set.

func (f Flags) String(name string) string {
	return f.FlagSet.Lookup(name).Value.String()
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Private functions

func caddyCmdToCobra

caddyCmdToCobra (caddyCmd Command) *cobra.Command
References: cobra.Command.

func cmdAdaptConfig

cmdAdaptConfig (fl Flags) (int, error)
References: bytes.Buffer, caddyconfig.GetAdapter, fmt.Errorf, fmt.Println, fmt.Sprintf, json.Indent, os.ReadFile, zap.Int, zap.String.

func cmdAddPackage

cmdAddPackage (fl Flags) (int, error)
References: fmt.Errorf.

func cmdBuildInfo

cmdBuildInfo (_ Flags) (int, error)
References: debug.ReadBuildInfo, fmt.Errorf, fmt.Println.

func cmdEnviron

cmdEnviron (fl Flags) (int, error)

func cmdExportStorage

cmdExportStorage (fl Flags) (int, error)
References: certmagic.Storage, context.Background, errors.Is, errors.New, fmt.Errorf, fmt.Sprintf, fs.ErrNotExist, os.Create, os.File, os.Stdout, tar.Header, tar.NewWriter.

func cmdFmt

cmdFmt (fl Flags) (int, error)
References: caddyfile.Format, caddyfile.FormattingDifference, difflib.Common, difflib.Diff, difflib.LeftOnly, difflib.RightOnly, fmt.Errorf, fmt.Print, fmt.Printf, io.ReadAll, os.ReadFile, os.Stdin, os.WriteFile, strings.Join, strings.Split.

func cmdImportStorage

cmdImportStorage (fl Flags) (int, error)
References: certmagic.Storage, context.Background, errors.New, fmt.Errorf, fmt.Println, io.EOF, io.ReadAll, os.File, os.Open, os.Stdin, tar.NewReader.

func cmdListModules

cmdListModules (fl Flags) (int, error)
References: fmt.Print, fmt.Printf, fmt.Println.

func cmdReload

cmdReload (fl Flags) (int, error)
References: bytes.NewReader, fmt.Errorf, http.Header, http.MethodPost.

func cmdRemovePackage

cmdRemovePackage (fl Flags) (int, error)
References: fmt.Errorf.

func cmdRun

cmdRun (fl Flags) (int, error)
References: errors.Is, fmt.Errorf, fs.ErrNotExist, io.ReadAll, net.Dial, os.Getenv, os.ReadFile, os.Stdin, runtime.GOOS, zap.Error, zap.String.

func cmdStart

cmdStart (fl Flags) (int, error)
References: errors.Is, exec.Command, exec.ErrDot, fmt.Errorf, fmt.Printf, log.Println, net.ErrClosed, net.Listen, os.Args, os.Stderr, os.Stdout, rand.Read.

func cmdStop

cmdStop (fl Flags) (int, error)
References: fmt.Errorf, http.MethodPost, zap.Error.

func cmdUpgrade

cmdUpgrade (fl Flags) (int, error)
References: fmt.Errorf.

func cmdValidateConfig

cmdValidateConfig (fl Flags) (int, error)
References: fmt.Errorf, fmt.Println.

func cmdVersion

cmdVersion (_ Flags) (int, error)
References: fmt.Println.

func configFileWithRespectToDefault

configFileWithRespectToDefault returns the filename to use for loading the config, based on whether a config file is already specified and a supported default config file exists.

configFileWithRespectToDefault (logger *zap.Logger, configFile string) (string, error)
References: caddyconfig.GetAdapter, errors.Is, fmt.Errorf, fs.ErrNotExist, os.Stat.

func determineStorage

determineStorage returns the top-level storage module from the given config. It may return nil even if no error.

determineStorage (configFile string, configAdapter string) (*storVal, error)
References: errors.As, json.SyntaxError, json.Unmarshal, json.Valid.

func downloadBuild

downloadBuild (qs url.Values) (*http.Response, error)
References: fmt.Errorf, fmt.Sprintf, http.Get, json.NewDecoder, zap.String, zap.Strings.

func getModules

getModules () ([]moduleInfo, error)
References: debug.Module, debug.ReadBuildInfo, fmt.Errorf, reflect.New, reflect.Ptr, reflect.TypeOf, reflect.ValueOf, strings.HasPrefix.

func getPluginPackages

getPluginPackages (modules []moduleInfo) (map[string]pluginPackage, error)
References: fmt.Errorf.

func handleEnvFileFlag

handleEnvFileFlag loads the environment variables from the given --envfile flag if specified. This should be called as early in the command function.

handleEnvFileFlag (fl Flags) error
References: fmt.Errorf.

func handlePingbackConn

handlePingbackConn reads from conn and ensures it matches the bytes in expect, or returns an error if it doesn't.

handlePingbackConn (conn net.Conn, expect []byte) error
References: bytes.Equal, fmt.Errorf, io.LimitReader, io.ReadAll.

func init

init ()
References: cobra.Command.

func isCaddyfile

isCaddyfile (configFile,adapterName string) (bool, error)
References: filepath.Base, filepath.Ext, strings.HasPrefix, strings.HasSuffix, strings.ToLower.

func listModules

listModules (path string) error
References: exec.Command, os.Stderr, os.Stdout.

func loadConfigWithLogger

loadConfigWithLogger (logger *zap.Logger, configFile,adapterName string) ([]byte, string, error)
References: caddyconfig.Adapter, caddyconfig.GetAdapter, errors.Is, fmt.Errorf, fmt.Sprintf, fs.ErrNotExist, io.ReadAll, json.Unmarshal, os.ReadFile, os.Stdin, zap.Int, zap.NewNop, zap.String.

func loadEnvFromFile

loadEnvFromFile (envFile string) error
References: certmagic.FileStorage, filepath.Join, fmt.Errorf, os.LookupEnv, os.Open, os.Setenv.

func newRootCommandFactory

newRootCommandFactory (fn func() *cobra.Command) *rootCommandFactory

func onlyVersionText

onlyVersionText () string

func parseEnvFile

parseEnvFile parses an env file from KEY=VALUE format. It's pretty naive. Limited value quotation is supported, but variable and command expansions are not supported.

parseEnvFile (envInput io.Reader) (map[string]string, error)
References: bufio.NewScanner, fmt.Errorf, strings.Contains, strings.Cut, strings.HasPrefix, strings.HasSuffix, strings.ReplaceAll, strings.TrimPrefix, strings.TrimRight, strings.TrimSpace, strings.TrimSuffix.

func printEnvironment

printEnvironment ()
References: fmt.Printf, fmt.Println, fmt.Sprintf, os.Environ, os.Getwd, runtime.Compiler, runtime.GOARCH, runtime.GOMAXPROCS, runtime.GOOS, runtime.NumCPU, runtime.Version.

func removeCaddyBinary

removeCaddyBinary removes the Caddy binary at the given path.

On any non-Windows OS, this simply calls os.Remove, since they should probably not exhibit any issue with processes deleting themselves.

removeCaddyBinary (path string) error
References: os.Remove.

func showVersion

showVersion (path string) error
References: exec.Command, os.Stderr, os.Stdout.

func splitModule

splitModule (arg string) (string, error)
References: fmt.Errorf, strings.LastIndex.

func upgradeBuild

upgradeBuild (pluginPkgs map[string]pluginPackage, fl Flags) (int, error)
References: filepath.EvalSymlinks, fmt.Errorf, fmt.Print, fmt.Println, os.Executable, os.ModeSymlink, os.Rename, os.Stat, runtime.GOARCH, runtime.GOOS, url.Values, zap.Error, zap.String.

func watchConfigFile

watchConfigFile watches the config file at filename for changes and reloads the config if the file was updated. This function blocks indefinitely; it only quits if the poller has errors for long enough time. The filename passed in must be the actual config file used, not one to be discovered. Each second the config files is loaded and parsed into an object and is compared to the last config object that was loaded

watchConfigFile (filename,adapterName string)
References: bytes.Equal, debug.Stack, log.Printf, time.Second, time.Tick, zap.Error, zap.Logger, zap.String.

func writeCaddyBinary

writeCaddyBinary (path string, body *io.ReadCloser, fileInfo os.FileInfo) error
References: fmt.Errorf, io.Copy, os.O_CREATE, os.O_RDWR, os.O_TRUNC, os.OpenFile, zap.String.


Tests

Files: 1. Third party imports: 0. Imports from organisation: 0. Tests: 2. Benchmarks: 0.

Test functions

TestParseEnvFile

References: reflect.DeepEqual, strings.NewReader.

Test_isCaddyfile

References: testing.T.