diff options
-rw-r--r-- | internal/gitaly/config/config.go | 92 |
1 files changed, 54 insertions, 38 deletions
diff --git a/internal/gitaly/config/config.go b/internal/gitaly/config/config.go index 29718876f..c269eabd1 100644 --- a/internal/gitaly/config/config.go +++ b/internal/gitaly/config/config.go @@ -232,45 +232,11 @@ func (cfg *Cfg) setDefaults() error { cfg.Hooks.CustomHooksDir = filepath.Join(cfg.GitlabShell.Dir, "hooks") } - if cfg.RuntimeDir == "" { - // If there is no runtime directory configured we just use a temporary runtime - // directory. This may not always be an ideal choice given that it's typically - // created at `/tmp`, which may get periodically pruned if `noatime` is set. - runtimeDir, err := os.MkdirTemp("", "gitaly-") - if err != nil { - return fmt.Errorf("creating temporary runtime directory: %w", err) - } - - cfg.RuntimeDir = runtimeDir - } else { - // Otherwise, we use the configured runtime directory. Note that we don't use the - // runtime directory directly, but instead create a subdirectory within it which is - // based on the process's PID. While we could use `MkdirTemp()` instead and don't - // bother with preexisting directories, the benefit of using the PID here is that we - // can determine whether the directory may still be in use by checking whether the - // PID exists. Furthermore, it allows easier debugging in case one wants to inspect - // the runtime directory of a running Gitaly node. - - runtimeDir := filepath.Join(cfg.RuntimeDir, fmt.Sprintf("gitaly-%d", os.Getpid())) - - if _, err := os.Stat(runtimeDir); err != nil && !os.IsNotExist(err) { - return fmt.Errorf("statting runtime directory: %w", err) - } else if err != nil { - // If the directory exists already then it must be from an old invocation of - // Gitaly. Because we use the PID as path component we know that the old - // instance cannot exist anymore though, so it's safe to remove this - // directory now. - if err := os.RemoveAll(runtimeDir); err != nil { - return fmt.Errorf("removing old runtime directory: %w", err) - } - } - - if err := os.Mkdir(runtimeDir, 0o700); err != nil { - return fmt.Errorf("creating runtime directory: %w", err) - } - - cfg.RuntimeDir = runtimeDir + runtimeDir, err := SetupRuntimeDirectory(*cfg, os.Getpid()) + if err != nil { + return err } + cfg.RuntimeDir = runtimeDir // The socket path must be short-ish because listen(2) fails on long // socket paths. We hope/expect that os.MkdirTemp creates a directory @@ -604,3 +570,53 @@ func (cfg *Cfg) configurePackObjectsCache() error { return nil } + +// SetupRuntimeDirectory creates a new runtime directory. Runtime directory contains internal +// runtime data generated by Gitaly such as the internal sockets. If cfg.RuntimeDir is set, +// it's used as the parent directory for the runtime directory. Runtime directory owner process +// can be identified by the suffix process ID suffixed in the directory name. If a directory already +// exists for this process' ID, it's removed and recreated. If cfg.RuntimeDir is not set, a temporary +// directory is used instead. SetupRuntimeDirectory returns the absolute path to the created runtime +// directory. +func SetupRuntimeDirectory(cfg Cfg, processID int) (string, error) { + var runtimeDir string + if cfg.RuntimeDir == "" { + // If there is no parent directory provided, we just use a temporary directory + // as the runtime directory. This may not always be an ideal choice given that + // it's typically created at `/tmp`, which may get periodically pruned if `noatime` + // is set. + var err error + runtimeDir, err = os.MkdirTemp("", "gitaly-") + if err != nil { + return "", fmt.Errorf("creating temporary runtime directory: %w", err) + } + } else { + // Otherwise, we use the configured runtime directory. Note that we don't use the + // runtime directory directly, but instead create a subdirectory within it which is + // based on the process's PID. While we could use `MkdirTemp()` instead and don't + // bother with preexisting directories, the benefit of using the PID here is that we + // can determine whether the directory may still be in use by checking whether the + // PID exists. Furthermore, it allows easier debugging in case one wants to inspect + // the runtime directory of a running Gitaly node. + + runtimeDir = filepath.Join(cfg.RuntimeDir, fmt.Sprintf("gitaly-%d", processID)) + + if _, err := os.Stat(runtimeDir); err != nil && !os.IsNotExist(err) { + return "", fmt.Errorf("statting runtime directory: %w", err) + } else if err != nil { + // If the directory exists already then it must be from an old invocation of + // Gitaly. Because we use the PID as path component we know that the old + // instance cannot exist anymore though, so it's safe to remove this + // directory now. + if err := os.RemoveAll(runtimeDir); err != nil { + return "", fmt.Errorf("removing old runtime directory: %w", err) + } + } + + if err := os.Mkdir(runtimeDir, 0o700); err != nil { + return "", fmt.Errorf("creating runtime directory: %w", err) + } + } + + return runtimeDir, nil +} |