Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion pkg/runfileconfig/run_file_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type App struct {
standalone.RunConfig `yaml:",inline"`
ContainerConfiguration `yaml:",inline"`
AppDirPath string `yaml:"appDirPath"`
LogsDir string `yaml:"logsDir,omitempty"`
AppLogFileName string
DaprdLogFileName string
AppLogWriteCloser io.WriteCloser
Expand All @@ -60,10 +61,17 @@ type App struct {
// Common represents the configuration options for the common section in the run file.
type Common struct {
standalone.SharedRunConfig `yaml:",inline"`
LogsDir string `yaml:"logsDir,omitempty"`
}

// GetLogsDir returns the directory where the app and daprd log files are written.
// It defaults to '<appDirPath>/.dapr/logs' unless a custom 'logsDir' is provided
// in the run template file. The directory is created if it does not exist.
func (a *App) GetLogsDir() string {
logsPath := filepath.Join(a.AppDirPath, standalone.DefaultDaprDirName, logsDir)
logsPath := a.LogsDir
if logsPath == "" {
logsPath = filepath.Join(a.AppDirPath, standalone.DefaultDaprDirName, logsDir)
}
os.MkdirAll(logsPath, 0o755)
return logsPath
}
Expand Down
30 changes: 30 additions & 0 deletions pkg/runfileconfig/run_file_config_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ func (a *RunFileConfig) validateRunConfig(runFilePath string) error {
a.Common.ResourcesPaths = append(a.Common.ResourcesPaths, a.Common.ResourcesPath)
}

// Resolve common's section LogsDir to an absolute path. The directory is not
// required to exist, it is created when the log files are written.
if err := a.resolvePathToAbs(baseDir, &a.Common.LogsDir); err != nil {
return err
}

for i := range len(a.Apps) {
if a.Apps[i].AppDirPath == "" {
return errors.New("required field 'appDirPath' not found in the provided app config file")
Expand Down Expand Up @@ -100,6 +106,16 @@ func (a *RunFileConfig) validateRunConfig(runFilePath string) error {
a.Apps[i].ResourcesPaths = append(a.Apps[i].ResourcesPaths, a.Apps[i].ResourcesPath)
}

// Resolve the app's LogsDir to an absolute path relative to AppDirPath.
// The directory is not required to exist, it is created when the log files are written.
// Precedence order -> apps[i].logsDir > common.logsDir > default (<appDirPath>/.dapr/logs).
if err := a.resolvePathToAbs(a.Apps[i].AppDirPath, &a.Apps[i].LogsDir); err != nil {
return err
}
if a.Apps[i].LogsDir == "" {
a.Apps[i].LogsDir = a.Common.LogsDir
}

// Check containerImagePullPolicy is valid.
if a.Apps[i].ContainerImagePullPolicy != "" {
if !utils.Contains(imagePullPolicyValuesAllowed, a.Apps[i].ContainerImagePullPolicy) {
Expand Down Expand Up @@ -211,6 +227,20 @@ func (a *RunFileConfig) getBasePathFromAbsPath(appDirPath string) (string, error
return "", fmt.Errorf("error in getting the base path from the provided appDirPath %q: ", appDirPath)
}

// resolvePathToAbs resolves a relative path in the run file to an absolute path
// without validating that it exists.
func (a *RunFileConfig) resolvePathToAbs(baseDir string, path *string) error {
if *path == "" {
return nil
}
resolved, err := utils.ResolveHomeDir(*path)
if err != nil {
return err
}
*path = utils.GetAbsPath(baseDir, resolved)
return nil
}

// resolvePathToAbsAndValidate resolves the relative paths in run file to absolute path and validates the file path.
func (a *RunFileConfig) resolvePathToAbsAndValidate(baseDir string, paths ...*string) error {
var err error
Expand Down
55 changes: 55 additions & 0 deletions pkg/runfileconfig/run_file_config_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var (
runFileForPrecedenceRuleDaprDir = filepath.Join(".", "testdata", "test_run_config_precedence_rule_dapr_dir.yaml")
runFileForLogDestination = filepath.Join(".", "testdata", "test_run_config_log_destination.yaml")
runFileForMultiResourcePaths = filepath.Join(".", "testdata", "test_run_config_multiple_resources_paths.yaml")
runFileForLogsDir = filepath.Join(".", "testdata", "test_run_config_logs_dir.yaml")

runFileForContainerImagePullPolicy = filepath.Join(".", "testdata", "test_run_config_container_image_pull_policy.yaml")
runFileForContainerImagePullPolicyInvalid = filepath.Join(".", "testdata", "test_run_config_container_image_pull_policy_invalid.yaml")
Expand Down Expand Up @@ -405,3 +406,57 @@ func getResourcesAndConfigFilePaths(t *testing.T, daprInstallPath string) []stri
result[1] = standalone.GetDaprConfigPath(daprDirPath)
return result
}

func TestLogsDirPrecedenceAndResolution(t *testing.T) {
config := RunFileConfig{}
apps, err := config.GetApps(runFileForLogsDir)
assert.NoError(t, err)
assert.Len(t, apps, 3)

testDataDir, err := filepath.Abs(filepath.Join(".", "testdata"))
assert.NoError(t, err)

// common's relative logsDir is resolved against the run file's directory.
expectedCommonLogsDir := filepath.Join(testDataDir, "central-logs")
// app_2's relative logsDir is resolved against its appDirPath.
expectedApp2LogsDir := filepath.Join(testDataDir, "webapp", "custom-logs")

t.Run("app without logsDir inherits common's logsDir", func(t *testing.T) {
assert.Equal(t, expectedCommonLogsDir, apps[0].LogsDir)
assert.Equal(t, expectedCommonLogsDir, apps[0].GetLogsDir())
})

t.Run("app's relative logsDir overrides common and resolves against appDirPath", func(t *testing.T) {
assert.Equal(t, expectedApp2LogsDir, apps[1].LogsDir)
assert.Equal(t, expectedApp2LogsDir, apps[1].GetLogsDir())
})

t.Run("app's absolute logsDir is used as is", func(t *testing.T) {
assert.Equal(t, "/tmp/dapr-abs-logs", apps[2].LogsDir)
assert.Equal(t, "/tmp/dapr-abs-logs", apps[2].GetLogsDir())
})

t.Run("logs directory is created on use", func(t *testing.T) {
logsDir := apps[0].GetLogsDir()
stat, err := os.Stat(logsDir)
assert.NoError(t, err)
assert.True(t, stat.IsDir())
})

t.Cleanup(func() {
os.RemoveAll(expectedCommonLogsDir)
os.RemoveAll(expectedApp2LogsDir)
os.RemoveAll("/tmp/dapr-abs-logs")
})
}

func TestLogsDirDefault(t *testing.T) {
config := RunFileConfig{}
apps, err := config.GetApps(validRunFilePath)
assert.NoError(t, err)
for _, app := range apps {
assert.Empty(t, app.LogsDir)
expected := filepath.Join(app.AppDirPath, standalone.DefaultDaprDirName, "logs")
assert.Equal(t, expected, app.GetLogsDir())
}
}
12 changes: 12 additions & 0 deletions pkg/runfileconfig/testdata/test_run_config_logs_dir.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 1
common:
logsDir: ./central-logs/
apps:
- appDirPath: ./webapp/
appID: app_1
- appDirPath: ./webapp/
appID: app_2
logsDir: ./custom-logs/
- appDirPath: ./backend/
appID: app_3
logsDir: /tmp/dapr-abs-logs