MakeDirectories returns a list of POSIX shell commands that ensure each path exists. It creates every directory leading to path from (but not including) base and sets their permissions for Kubernetes, regardless of umask. Relative paths are expanded relative to base. See: - https://pubs.opengroup.
(base string, paths ...string)
| 44 | // - https://pubs.opengroup.org/onlinepubs/9799919799/utilities/test.html |
| 45 | // - https://pubs.opengroup.org/onlinepubs/9799919799/utilities/umask.html |
| 46 | func MakeDirectories(base string, paths ...string) string { |
| 47 | // Without any paths, return a command that succeeds when the base path exists. |
| 48 | if len(paths) == 0 { |
| 49 | return `test -d ` + QuoteWord(base) |
| 50 | } |
| 51 | |
| 52 | // Expand each path relative to the base path. |
| 53 | expandedPaths := make([]string, len(paths)) |
| 54 | for i, p := range paths { |
| 55 | if filepath.IsAbs(p) { |
| 56 | expandedPaths[i] = p |
| 57 | } else { |
| 58 | expandedPaths[i] = filepath.Join(base, p) |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | // Gather parent directories of each path. |
| 63 | allPaths := slices.Clone(expandedPaths) |
| 64 | for _, p := range expandedPaths { |
| 65 | if r, err := filepath.Rel(base, p); err == nil && filepath.IsLocal(r) { |
| 66 | // The result of [filepath.Rel] is a shorter representation of the full path; skip it. |
| 67 | r = filepath.Dir(r) |
| 68 | |
| 69 | for r != "." { |
| 70 | allPaths = append(allPaths, filepath.Join(base, r)) |
| 71 | r = filepath.Dir(r) |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | // Pod "securityContext.fsGroup" ensures processes and filesystems agree on a GID. |
| 77 | // Use the same permissions for group and owner. |
| 78 | const perms fs.FileMode = 0 | |
| 79 | // S_IRWXU: enable owner read, write, and execute permissions. |
| 80 | 0o0700 | |
| 81 | // S_IRWXG: enable group read, write, and execute permissions. |
| 82 | 0o0070 | |
| 83 | // S_IXOTH, S_IROTH: enable other read and execute permissions. |
| 84 | 0o0001 | 0o0004 |
| 85 | |
| 86 | return `` + |
| 87 | // Create all the paths and any missing parents. |
| 88 | `mkdir -p ` + strings.Join(QuoteWords(expandedPaths...), " ") + |
| 89 | |
| 90 | // Try to set the permissions of every path and each parent. |
| 91 | // This swallows the exit status of `chmod` because not all filesystems |
| 92 | // tolerate the operation; CIFS and NFS are notable examples. |
| 93 | fmt.Sprintf(` && { chmod %#o %s || :; }`, |
| 94 | perms, strings.Join(QuoteWords(allPaths...), " "), |
| 95 | ) |
| 96 | } |