Rationalize default configuration file paths and update documentation
All checks were successful
ci/woodpecker/tag/release Pipeline was successful
All checks were successful
ci/woodpecker/tag/release Pipeline was successful
This commit is contained in:
@@ -137,7 +137,7 @@ For subprocess orchestration guidance, see [`docs/subprocess-operations.md`](doc
|
||||
|
||||
Precedence:
|
||||
1. defaults
|
||||
2. config file (`--config`, `AUDITA_CONFIG`, or `/etc/audita/config.yml` when present)
|
||||
2. config file (`--config`, `AUDITA_CONFIG`, or default search paths when present: `/usr/local/etc/audita/config.yml`, then `/etc/audita/config.yml`)
|
||||
3. environment (`AUDITA_*`)
|
||||
4. CLI flags
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ audita config print-effective [--config <config.yml>]
|
||||
Current runtime flow (`internal/cli/run.go`):
|
||||
1. Build runtime config from:
|
||||
- defaults;
|
||||
- file config source (`--config`, `AUDITA_CONFIG`, or `/etc/audita/config.yml` when present);
|
||||
- file config source (`--config`, `AUDITA_CONFIG`, or default search paths when present: `/usr/local/etc/audita/config.yml`, then `/etc/audita/config.yml`);
|
||||
- environment overrides;
|
||||
- CLI overrides.
|
||||
2. Parse flags and apply CLI overrides.
|
||||
@@ -304,9 +304,9 @@ File-config source behavior:
|
||||
- required to exist, otherwise process fails clearly.
|
||||
- `AUDITA_CONFIG` (when `--config` is not provided):
|
||||
- required to exist, otherwise process fails clearly.
|
||||
- default path `/etc/audita/config.yml` (when neither explicit source is provided):
|
||||
- used only when present;
|
||||
- silently ignored when missing.
|
||||
- default paths `/usr/local/etc/audita/config.yml`, then `/etc/audita/config.yml` (when neither explicit source is provided):
|
||||
- first existing path in that order is used;
|
||||
- both missing is silently ignored.
|
||||
|
||||
Versioned file-config behavior (`internal/core/config/file_config.go`):
|
||||
- supported version: `version: 1`;
|
||||
|
||||
@@ -54,7 +54,7 @@ Precedence for `audita process`:
|
||||
Config source behavior:
|
||||
- `--config <path>`: missing path is a clear failure
|
||||
- `AUDITA_CONFIG`: missing path is a clear failure
|
||||
- default `/etc/audita/config.yml`: missing file is non-fatal
|
||||
- defaults `/usr/local/etc/audita/config.yml`, then `/etc/audita/config.yml`: both missing is non-fatal
|
||||
|
||||
## Supported transcript input forms
|
||||
|
||||
|
||||
@@ -26,13 +26,14 @@ For `audita process`, config path resolution is:
|
||||
|
||||
1. `--config <path>` if provided
|
||||
2. `AUDITA_CONFIG` if set and `--config` is not provided
|
||||
3. default `/etc/audita/config.yml` if present
|
||||
3. default `/usr/local/etc/audita/config.yml` if present
|
||||
4. fallback default `/etc/audita/config.yml` if present
|
||||
|
||||
Missing-file behavior:
|
||||
|
||||
- missing `--config` path: hard failure;
|
||||
- missing `AUDITA_CONFIG` path: hard failure;
|
||||
- missing `/etc/audita/config.yml`: non-fatal, run continues.
|
||||
- missing both default-path files: non-fatal, run continues.
|
||||
|
||||
## Precedence model
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ Use this checklist before cutting a pre-1.0 or 1.0 release candidate.
|
||||
- `audita config print-effective --config <path>`
|
||||
- Confirm precedence behavior:
|
||||
- defaults -> file config -> environment -> CLI.
|
||||
- Confirm missing `/etc/audita/config.yml` is non-fatal when `--config`/`AUDITA_CONFIG` are unset.
|
||||
- Confirm default config search order:
|
||||
- `/usr/local/etc/audita/config.yml` first, then `/etc/audita/config.yml`.
|
||||
- Confirm missing both default-path config files is non-fatal when `--config`/`AUDITA_CONFIG` are unset.
|
||||
|
||||
## Output schema checks
|
||||
|
||||
|
||||
@@ -982,13 +982,15 @@ func findConfigPathOverride(args []string) (path string, set bool, err error) {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
var statConfigPath = os.Stat
|
||||
|
||||
func resolveConfigPath(cliConfigPath string, cliConfigPathSet bool, lookup func(string) (string, bool)) (path string, source string, err error) {
|
||||
if cliConfigPathSet {
|
||||
path = strings.TrimSpace(cliConfigPath)
|
||||
if path == "" {
|
||||
return "", "", fmt.Errorf("--config requires a non-empty path")
|
||||
}
|
||||
if _, statErr := os.Stat(path); statErr != nil {
|
||||
if _, statErr := statConfigPath(path); statErr != nil {
|
||||
if os.IsNotExist(statErr) {
|
||||
return "", "", fmt.Errorf("config file not found: %s", path)
|
||||
}
|
||||
@@ -1002,7 +1004,7 @@ func resolveConfigPath(cliConfigPath string, cliConfigPathSet bool, lookup func(
|
||||
if path == "" {
|
||||
return "", "", fmt.Errorf("AUDITA_CONFIG must not be empty")
|
||||
}
|
||||
if _, statErr := os.Stat(path); statErr != nil {
|
||||
if _, statErr := statConfigPath(path); statErr != nil {
|
||||
if os.IsNotExist(statErr) {
|
||||
return "", "", fmt.Errorf("config file not found: %s", path)
|
||||
}
|
||||
@@ -1011,11 +1013,12 @@ func resolveConfigPath(cliConfigPath string, cliConfigPathSet bool, lookup func(
|
||||
return path, "env", nil
|
||||
}
|
||||
|
||||
defaultPath := config.DefaultConfigPath
|
||||
if _, statErr := os.Stat(defaultPath); statErr == nil {
|
||||
return defaultPath, "default", nil
|
||||
} else if !os.IsNotExist(statErr) {
|
||||
return "", "", fmt.Errorf("cannot access config file %s: %w", defaultPath, statErr)
|
||||
for _, defaultPath := range config.DefaultConfigSearchPaths {
|
||||
if _, statErr := statConfigPath(defaultPath); statErr == nil {
|
||||
return defaultPath, "default", nil
|
||||
} else if !os.IsNotExist(statErr) {
|
||||
return "", "", fmt.Errorf("cannot access config file %s: %w", defaultPath, statErr)
|
||||
}
|
||||
}
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
@@ -110,6 +110,55 @@ func TestResolveConfigPathDefaultIgnoredWhenMissing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveConfigPathDefaultPrefersUsrLocalOverEtc(t *testing.T) {
|
||||
oldStat := statConfigPath
|
||||
statConfigPath = func(path string) (os.FileInfo, error) {
|
||||
if path == config.DefaultConfigPathUsrLocal || path == config.DefaultConfigPath {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
t.Cleanup(func() { statConfigPath = oldStat })
|
||||
|
||||
lookup := func(string) (string, bool) { return "", false }
|
||||
path, source, err := resolveConfigPath("", false, lookup)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if source != "default" {
|
||||
t.Fatalf("expected default source, got %q", source)
|
||||
}
|
||||
if path != config.DefaultConfigPathUsrLocal {
|
||||
t.Fatalf("expected %q, got %q", config.DefaultConfigPathUsrLocal, path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveConfigPathDefaultFallsBackToEtc(t *testing.T) {
|
||||
oldStat := statConfigPath
|
||||
statConfigPath = func(path string) (os.FileInfo, error) {
|
||||
if path == config.DefaultConfigPathUsrLocal {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
if path == config.DefaultConfigPath {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
t.Cleanup(func() { statConfigPath = oldStat })
|
||||
|
||||
lookup := func(string) (string, bool) { return "", false }
|
||||
path, source, err := resolveConfigPath("", false, lookup)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if source != "default" {
|
||||
t.Fatalf("expected default source, got %q", source)
|
||||
}
|
||||
if path != config.DefaultConfigPath {
|
||||
t.Fatalf("expected %q, got %q", config.DefaultConfigPath, path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunConfigValidateSuccess(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
@@ -6,7 +6,15 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const DefaultConfigPath = "/etc/audita/config.yml"
|
||||
const (
|
||||
DefaultConfigPath = "/etc/audita/config.yml"
|
||||
DefaultConfigPathUsrLocal = "/usr/local/etc/audita/config.yml"
|
||||
)
|
||||
|
||||
var DefaultConfigSearchPaths = []string{
|
||||
DefaultConfigPathUsrLocal,
|
||||
DefaultConfigPath,
|
||||
}
|
||||
|
||||
func LoadFromEnv() (Config, error) {
|
||||
cfg := Default()
|
||||
|
||||
Reference in New Issue
Block a user