Skip to content

Commit 70a0682

Browse files
cbandyandrewlecuyer
authored andcommitted
Create directories with group-write permissions
The group-write permission is important for persistent file systems in environments where different containers are assigned different UIDs over time. Some network file systems, however, reject attempts to set POSIX directory permissions. CIFS and NFS are notable in this regard. Issue: PGO-2417
1 parent e55ae53 commit 70a0682

File tree

9 files changed

+37
-30
lines changed

9 files changed

+37
-30
lines changed

internal/collector/instance.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,7 @@ func startCommand(logDirectories []string, includeLogrotate bool) []string {
180180
if len(logDirectories) != 0 {
181181
for _, logDir := range logDirectories {
182182
mkdirScript = mkdirScript + `
183-
` + shell.MakeDirectories(0o775, logDir,
184-
path.Join(logDir, "receiver"))
183+
` + shell.MakeDirectories(logDir, path.Join(logDir, "receiver"))
185184
}
186185
}
187186

internal/controller/standalone_pgadmin/pod.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -442,10 +442,10 @@ with open('` + configMountPath + `/` + gunicornConfigFilePath + `') as _f:
442442
script := strings.Join([]string{
443443
// Create the config directory so Kubernetes can mount it later.
444444
// - https://issue.k8s.io/121294
445-
shell.MakeDirectories(0o775, scriptMountPath, configMountPath),
445+
shell.MakeDirectories(scriptMountPath, configMountPath),
446446

447-
// Create the logs directory with g+rwx to ensure pgAdmin can write to it as well.
448-
shell.MakeDirectories(0o775, dataMountPath, LogDirectoryAbsolutePath),
447+
// Create the logs directory and ensure pgAdmin can write to it as well.
448+
shell.MakeDirectories(dataMountPath, LogDirectoryAbsolutePath),
449449

450450
// Write the system and server configurations.
451451
`echo "$1" > ` + scriptMountPath + `/config_system.py`,

internal/controller/standalone_pgadmin/pod_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ initContainers:
137137
- -ceu
138138
- --
139139
- |-
140-
mkdir -p '/etc/pgadmin/conf.d' && chmod 0775 '/etc/pgadmin/conf.d'
141-
mkdir -p '/var/lib/pgadmin/logs' && chmod 0775 '/var/lib/pgadmin/logs'
140+
mkdir -p '/etc/pgadmin/conf.d' && { chmod 0775 '/etc/pgadmin/conf.d' || :; }
141+
mkdir -p '/var/lib/pgadmin/logs' && { chmod 0775 '/var/lib/pgadmin/logs' || :; }
142142
echo "$1" > /etc/pgadmin/config_system.py
143143
echo "$2" > /etc/pgadmin/gunicorn_config.py
144144
- startup
@@ -342,8 +342,8 @@ initContainers:
342342
- -ceu
343343
- --
344344
- |-
345-
mkdir -p '/etc/pgadmin/conf.d' && chmod 0775 '/etc/pgadmin/conf.d'
346-
mkdir -p '/var/lib/pgadmin/logs' && chmod 0775 '/var/lib/pgadmin/logs'
345+
mkdir -p '/etc/pgadmin/conf.d' && { chmod 0775 '/etc/pgadmin/conf.d' || :; }
346+
mkdir -p '/var/lib/pgadmin/logs' && { chmod 0775 '/var/lib/pgadmin/logs' || :; }
347347
echo "$1" > /etc/pgadmin/config_system.py
348348
echo "$2" > /etc/pgadmin/gunicorn_config.py
349349
- startup

internal/pgbackrest/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func MakePGBackrestLogDir(template *corev1.PodTemplateSpec,
177177
container := corev1.Container{
178178
// TODO(log-rotation): The second argument here should be the path
179179
// of the volume mount. Find a way to calculate that consistently.
180-
Command: []string{"bash", "-c", shell.MakeDirectories(0o775, path.Dir(pgBackRestLogPath), pgBackRestLogPath)},
180+
Command: []string{"bash", "-c", shell.MakeDirectories(path.Dir(pgBackRestLogPath), pgBackRestLogPath)},
181181
Image: config.PGBackRestContainerImage(cluster),
182182
ImagePullPolicy: cluster.Spec.ImagePullPolicy,
183183
Name: naming.ContainerPGBackRestLogDirInit,

internal/pgbackrest/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func TestMakePGBackrestLogDir(t *testing.T) {
292292
for _, c := range podTemplate.Spec.InitContainers {
293293
if c.Name == naming.ContainerPGBackRestLogDirInit {
294294
// ignore "bash -c", should skip repo with no volume
295-
assert.Equal(t, `mkdir -p '/pgbackrest/repo2/log' && chmod 0775 '/pgbackrest/repo2/log'`, c.Command[2])
295+
assert.Equal(t, `mkdir -p '/pgbackrest/repo2/log' && { chmod 0775 '/pgbackrest/repo2/log' || :; }`, c.Command[2])
296296
assert.Equal(t, c.Image, "test-image")
297297
assert.Equal(t, c.ImagePullPolicy, corev1.PullAlways)
298298
assert.Assert(t, !cmp.DeepEqual(c.SecurityContext,

internal/postgres/config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,11 +375,11 @@ chmod +x /tmp/pg_rewind_tde.sh
375375
`halt "$(permissions "${postgres_data_directory}" ||:)"`,
376376

377377
// Create log directories.
378-
`(` + shell.MakeDirectories(0o775, dataMountPath, naming.PGBackRestPGDataLogPath) + `) ||`,
378+
`(` + shell.MakeDirectories(dataMountPath, naming.PGBackRestPGDataLogPath) + `) ||`,
379379
`halt "$(permissions ` + naming.PGBackRestPGDataLogPath + ` ||:)"`,
380-
`(` + shell.MakeDirectories(0o775, dataMountPath, naming.PatroniPGDataLogPath) + `) ||`,
380+
`(` + shell.MakeDirectories(dataMountPath, naming.PatroniPGDataLogPath) + `) ||`,
381381
`halt "$(permissions ` + naming.PatroniPGDataLogPath + ` ||:)"`,
382-
`(` + shell.MakeDirectories(0o775, dataMountPath, LogDirectory()) + `) ||`,
382+
`(` + shell.MakeDirectories(dataMountPath, LogDirectory()) + `) ||`,
383383
`halt "$(permissions ` + LogDirectory() + ` ||:)"`,
384384

385385
// Copy replication client certificate files

internal/postgres/reconcile_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,11 @@ initContainers:
268268
recreate "${postgres_data_directory}" '0700'
269269
else (halt Permissions!); fi ||
270270
halt "$(permissions "${postgres_data_directory}" ||:)"
271-
(mkdir -p '/pgdata/pgbackrest/log' && chmod 0775 '/pgdata/pgbackrest/log' '/pgdata/pgbackrest') ||
271+
(mkdir -p '/pgdata/pgbackrest/log' && { chmod 0775 '/pgdata/pgbackrest/log' '/pgdata/pgbackrest' || :; }) ||
272272
halt "$(permissions /pgdata/pgbackrest/log ||:)"
273-
(mkdir -p '/pgdata/patroni/log' && chmod 0775 '/pgdata/patroni/log' '/pgdata/patroni') ||
273+
(mkdir -p '/pgdata/patroni/log' && { chmod 0775 '/pgdata/patroni/log' '/pgdata/patroni' || :; }) ||
274274
halt "$(permissions /pgdata/patroni/log ||:)"
275-
(mkdir -p '/pgdata/logs/postgres' && chmod 0775 '/pgdata/logs/postgres' '/pgdata/logs') ||
275+
(mkdir -p '/pgdata/logs/postgres' && { chmod 0775 '/pgdata/logs/postgres' '/pgdata/logs' || :; }) ||
276276
halt "$(permissions /pgdata/logs/postgres ||:)"
277277
install -D --mode=0600 -t "/tmp/replication" "/pgconf/tls/replication"/{tls.crt,tls.key,ca.crt}
278278

internal/shell/paths.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ func CleanFileName(path string) string {
3333

3434
// MakeDirectories returns a list of POSIX shell commands that ensure each path
3535
// exists. It creates every directory leading to path from (but not including)
36-
// base and sets their permissions to exactly perms, regardless of umask.
36+
// base and sets their permissions for Kubernetes, regardless of umask.
3737
//
3838
// See:
3939
// - https://pubs.opengroup.org/onlinepubs/9799919799/utilities/chmod.html
4040
// - https://pubs.opengroup.org/onlinepubs/9799919799/utilities/mkdir.html
4141
// - https://pubs.opengroup.org/onlinepubs/9799919799/utilities/test.html
4242
// - https://pubs.opengroup.org/onlinepubs/9799919799/utilities/umask.html
43-
func MakeDirectories(perms fs.FileMode, base string, paths ...string) string {
43+
func MakeDirectories(base string, paths ...string) string {
4444
// Without any paths, return a command that succeeds when the base path
4545
// exists.
4646
if len(paths) == 0 {
@@ -61,14 +61,22 @@ func MakeDirectories(perms fs.FileMode, base string, paths ...string) string {
6161
}
6262
}
6363

64+
const perms fs.FileMode = 0 |
65+
// S_IRWXU: enable owner read, write, and execute permissions.
66+
0o0700 |
67+
// S_IRWXG: enable group read, write, and execute permissions.
68+
0o0070 |
69+
// S_IXOTH, S_IROTH: enable other read and execute permissions.
70+
0o0001 | 0o0004
71+
6472
return `` +
6573
// Create all the paths and any missing parents.
6674
`mkdir -p ` + strings.Join(QuoteWords(paths...), " ") +
6775

68-
// Set the permissions of every path and each parent.
69-
// NOTE: FileMode bits other than file permissions are ignored.
70-
fmt.Sprintf(` && chmod %#o %s`,
71-
perms&fs.ModePerm,
72-
strings.Join(QuoteWords(allPaths...), " "),
76+
// Try to set the permissions of every path and each parent.
77+
// This swallows the exit status of `chmod` because not all filesystems
78+
// tolerate the operation; CIFS and NFS are notable examples.
79+
fmt.Sprintf(` && { chmod %#o %s || :; }`,
80+
perms, strings.Join(QuoteWords(allPaths...), " "),
7381
)
7482
}

internal/shell/paths_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ func TestMakeDirectories(t *testing.T) {
5252

5353
t.Run("NoPaths", func(t *testing.T) {
5454
assert.Equal(t,
55-
MakeDirectories(0o755, "/asdf/jklm"),
55+
MakeDirectories("/asdf/jklm"),
5656
`test -d '/asdf/jklm'`)
5757
})
5858

5959
t.Run("Children", func(t *testing.T) {
6060
assert.DeepEqual(t,
61-
MakeDirectories(0o775, "/asdf", "/asdf/jklm", "/asdf/qwerty"),
62-
`mkdir -p '/asdf/jklm' '/asdf/qwerty' && chmod 0775 '/asdf/jklm' '/asdf/qwerty'`)
61+
MakeDirectories("/asdf", "/asdf/jklm", "/asdf/qwerty"),
62+
`mkdir -p '/asdf/jklm' '/asdf/qwerty' && { chmod 0775 '/asdf/jklm' '/asdf/qwerty' || :; }`)
6363
})
6464

6565
t.Run("Grandchild", func(t *testing.T) {
66-
script := MakeDirectories(0o775, "/asdf", "/asdf/qwerty/boots")
66+
script := MakeDirectories("/asdf", "/asdf/qwerty/boots")
6767
assert.DeepEqual(t, script,
68-
`mkdir -p '/asdf/qwerty/boots' && chmod 0775 '/asdf/qwerty/boots' '/asdf/qwerty'`)
68+
`mkdir -p '/asdf/qwerty/boots' && { chmod 0775 '/asdf/qwerty/boots' '/asdf/qwerty' || :; }`)
6969

7070
t.Run("ShellCheckPOSIX", func(t *testing.T) {
7171
shellcheck := require.ShellCheck(t)
@@ -83,7 +83,7 @@ func TestMakeDirectories(t *testing.T) {
8383
})
8484

8585
t.Run("Long", func(t *testing.T) {
86-
script := MakeDirectories(0o700, "/", strings.Repeat("/asdf", 20))
86+
script := MakeDirectories("/", strings.Repeat("/asdf", 20))
8787

8888
t.Run("PrettyYAML", func(t *testing.T) {
8989
b, err := yaml.Marshal(script)

0 commit comments

Comments
 (0)