Repository: moby/moby
File: daemon/config/config.go (Go)

Code before:

	for _, h := range config.Hosts {
		if _, err := opts.ValidateHost(h); err != nil {
			return err
		}
	}

	for _, mirror := range config.ServiceOptions.Mirrors {
		if _, err := registry.ValidateMirror(mirror); err != nil {
			return err
		}
	}

	if config.CorsHeaders != "" {
		// TODO(thaJeztah): option is used to produce error when used; remove in next release
		return errors.New(`DEPRECATED: The "api-cors-header" config parameter and the dockerd "--api-cors-header" option have been removed; use a reverse proxy if you need CORS headers`)
	}

	if _, err := parseExecOptions(config.ExecOptions); err != nil {
		return err
	}

	if err := libnetwork.ValidateFirewallBackend(config.FirewallBackend); err != nil {
		return err
	}

	// validate platform-specific settings
	return validatePlatformConfig(config)
}

// parseExecOptions parses the given exec-options into a map. It returns an
// error if the exec-options are formatted incorrectly, or when options are
// used that are not supported on this platform.
//
// TODO(thaJeztah): consider making this more strict: make options case-sensitive and disallow whitespace around "=".
func parseExecOptions(execOptions []string) (map[string]string, error) {
	o := make(map[string]string)
	for _, keyValue := range execOptions {
		k, v, ok := strings.Cut(keyValue, "=")
		k = strings.ToLower(strings.TrimSpace(k))
		v = strings.TrimSpace(v)
		if !ok || k == "" || v == "" {
			return nil, fmt.Errorf("invalid exec-opt (%s): must be formatted 'opt=value'", keyValue)
		}
		if err := validatePlatformExecOpt(k, v); err != nil {
			return nil, fmt.Errorf("invalid exec-opt (%s): %w", keyValue, err)
		}
		o[k] = v
	}
	return o, nil
}

Review comment (suggestion):
Looks like this is the only place where this function is used; looking at the implementation, it does not need any knowledge about libnetwork, only checking if it's acceptable values; somewhat tempted to move it to the `daemon/config`  package (can even be un-exported if we only use it here);


```go
func ValidateFirewallBackend(val string) error {
	switch val {
	case "", "iptables", "nftables":
		return nil
	}
	return fmt.Errorf(`firewall-backend %q is invalid, allowed values are "iptables" and "nftables"`, val)
}
```



Code after:

	for _, h := range config.Hosts {
		if _, err := opts.ValidateHost(h); err != nil {
			return err
		}
	}

	for _, mirror := range config.ServiceOptions.Mirrors {
		if _, err := registry.ValidateMirror(mirror); err != nil {
			return err
		}
	}

	if config.CorsHeaders != "" {
		// TODO(thaJeztah): option is used to produce error when used; remove in next release
		return errors.New(`DEPRECATED: The "api-cors-header" config parameter and the dockerd "--api-cors-header" option have been removed; use a reverse proxy if you need CORS headers`)
	}

	if _, err := parseExecOptions(config.ExecOptions); err != nil {
		return err
	}

	// validate platform-specific settings
	return validatePlatformConfig(config)
}

// parseExecOptions parses the given exec-options into a map. It returns an
// error if the exec-options are formatted incorrectly, or when options are
// used that are not supported on this platform.
//
// TODO(thaJeztah): consider making this more strict: make options case-sensitive and disallow whitespace around "=".
func parseExecOptions(execOptions []string) (map[string]string, error) {
	o := make(map[string]string)
	for _, keyValue := range execOptions {
		k, v, ok := strings.Cut(keyValue, "=")
		k = strings.ToLower(strings.TrimSpace(k))
		v = strings.TrimSpace(v)
		if !ok || k == "" || v == "" {
			return nil, fmt.Errorf("invalid exec-opt (%s): must be formatted 'opt=value'", keyValue)
		}
		if err := validatePlatformExecOpt(k, v); err != nil {
			return nil, fmt.Errorf("invalid exec-opt (%s): %w", keyValue, err)
		}
		o[k] = v
	}
	return o, nil
}

// MaskCredentials masks credentials that are in an URL.
func MaskCredentials(rawURL string) string {
	parsedURL, err := url.Parse(rawURL)