startupCommand returns an entrypoint that prepares the filesystem for PostgreSQL.
( ctx context.Context, cluster *v1beta1.PostgresCluster, instance *v1beta1.PostgresInstanceSetSpec, parameters *ParameterSet, )
| 399 | // startupCommand returns an entrypoint that prepares the filesystem for |
| 400 | // PostgreSQL. |
| 401 | func startupCommand( |
| 402 | ctx context.Context, |
| 403 | cluster *v1beta1.PostgresCluster, |
| 404 | instance *v1beta1.PostgresInstanceSetSpec, |
| 405 | parameters *ParameterSet, |
| 406 | ) []string { |
| 407 | version := cluster.Spec.PostgresVersion |
| 408 | dataDir := DataDirectory(cluster) |
| 409 | logDir := parameters.Value("log_directory") |
| 410 | walDir := WALDirectory(cluster, instance) |
| 411 | |
| 412 | mkdirs := make([]string, 0, 9+len(instance.TablespaceVolumes)) |
| 413 | mkdirs = append(mkdirs, `dataDirectory "${postgres_data_directory}" || halt "$(permissions "${postgres_data_directory}" ||:)"`) |
| 414 | |
| 415 | // If the user requests tablespaces, we want to make sure the directories exist with the correct owner and permissions. |
| 416 | // |
| 417 | // The path for tablespaces volumes is /tablespaces/NAME/data -- the `data` directory is so we can arrange the permissions. |
| 418 | if feature.Enabled(ctx, feature.TablespaceVolumes) { |
| 419 | for _, tablespace := range instance.TablespaceVolumes { |
| 420 | dir := shell.QuoteWord("/tablespaces/" + tablespace.Name + "/data") |
| 421 | mkdirs = append(mkdirs, `dataDirectory `+dir+` || halt "$(permissions `+dir+` ||:)"`) |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | // Postgres creates "log_directory" but does *not* create any of its parent directories. |
| 426 | // Postgres omits group-write S_IWGRP permission when creating the directory. |
| 427 | // |
| 428 | // Do both here while being careful to *not* touch "data_directory" contents until after |
| 429 | // `initdb` or Patroni bootstrap; those abort unless "data_directory" is entirely empty. |
| 430 | if path.IsAbs(logDir) && !strings.HasPrefix(logDir, dataDir) { |
| 431 | mkdirs = append(mkdirs, |
| 432 | `(`+shell.MakeDirectories(dataMountPath, logDir)+`) ||`, |
| 433 | `halt "$(permissions `+shell.QuoteWord(logDir)+` ||:)"`, |
| 434 | ) |
| 435 | } else { |
| 436 | // Postgres interprets "log_directory" relative to "data_directory" so do the same here. |
| 437 | mkdirs = append(mkdirs, |
| 438 | `[[ ! -f `+shell.QuoteWord(path.Join(dataDir, "PG_VERSION"))+` ]] ||`, |
| 439 | `(`+shell.MakeDirectories(dataDir, logDir)+`) ||`, |
| 440 | `halt "$(permissions `+shell.QuoteWord(path.Join(dataDir, logDir))+` ||:)"`, |
| 441 | ) |
| 442 | } |
| 443 | |
| 444 | // These directories are outside "data_directory" and can be created. |
| 445 | mkdirs = append(mkdirs, |
| 446 | `(`+shell.MakeDirectories(dataMountPath, naming.PatroniPGDataLogPath)+`) ||`, |
| 447 | `halt "$(permissions `+shell.QuoteWord(naming.PatroniPGDataLogPath)+` ||:)"`, |
| 448 | |
| 449 | `(`+shell.MakeDirectories(dataMountPath, util.GetPGBackRestLogPathForInstance(cluster))+`) ||`, |
| 450 | `halt "$(permissions `+shell.QuoteWord(util.GetPGBackRestLogPathForInstance(cluster))+` ||:)"`, |
| 451 | ) |
| 452 | |
| 453 | args := []string{fmt.Sprint(version), walDir} |
| 454 | script := strings.Join([]string{ |
| 455 | `declare -r expected_major_version="$1" pgwal_directory="$2"`, |
| 456 | |
| 457 | // Function to create a Postgres data directory. |
| 458 | bashDataDirectory, |