Line data Source code
1 : use std::fs::{File, OpenOptions};
2 : use std::io;
3 : use std::io::prelude::*;
4 : use std::path::Path;
5 :
6 : use anyhow::Result;
7 :
8 : use crate::pg_helpers::escape_conf_value;
9 : use crate::pg_helpers::PgOptionsSerialize;
10 : use compute_api::spec::{ComputeMode, ComputeSpec};
11 :
12 : /// Check that `line` is inside a text file and put it there if it is not.
13 : /// Create file if it doesn't exist.
14 581 : pub fn line_in_file(path: &Path, line: &str) -> Result<bool> {
15 581 : let mut file = OpenOptions::new()
16 581 : .read(true)
17 581 : .write(true)
18 581 : .create(true)
19 581 : .append(false)
20 581 : .open(path)?;
21 581 : let buf = io::BufReader::new(&file);
22 581 : let mut count: usize = 0;
23 :
24 56360 : for l in buf.lines() {
25 56360 : if l? == line {
26 2 : return Ok(false);
27 56358 : }
28 56358 : count = 1;
29 : }
30 :
31 579 : write!(file, "{}{}", "\n".repeat(count), line)?;
32 579 : Ok(true)
33 581 : }
34 :
35 : /// Create or completely rewrite configuration file specified by `path`
36 796 : pub fn write_postgres_conf(
37 796 : path: &Path,
38 796 : spec: &ComputeSpec,
39 796 : extension_server_port: Option<u16>,
40 796 : ) -> Result<()> {
41 : // File::create() destroys the file content if it exists.
42 796 : let mut file = File::create(path)?;
43 :
44 : // Write the postgresql.conf content from the spec file as is.
45 796 : if let Some(conf) = &spec.cluster.postgresql_conf {
46 796 : writeln!(file, "{}", conf)?;
47 0 : }
48 :
49 : // Add options for connecting to storage
50 796 : writeln!(file, "# Neon storage settings")?;
51 796 : if let Some(s) = &spec.pageserver_connstring {
52 796 : writeln!(file, "neon.pageserver_connstring={}", escape_conf_value(s))?;
53 0 : }
54 796 : if !spec.safekeeper_connstrings.is_empty() {
55 747 : writeln!(
56 747 : file,
57 747 : "neon.safekeepers={}",
58 747 : escape_conf_value(&spec.safekeeper_connstrings.join(","))
59 747 : )?;
60 49 : }
61 796 : if let Some(s) = &spec.tenant_id {
62 796 : writeln!(file, "neon.tenant_id={}", escape_conf_value(&s.to_string()))?;
63 0 : }
64 796 : if let Some(s) = &spec.timeline_id {
65 796 : writeln!(
66 796 : file,
67 796 : "neon.timeline_id={}",
68 796 : escape_conf_value(&s.to_string())
69 796 : )?;
70 0 : }
71 :
72 796 : match spec.mode {
73 747 : ComputeMode::Primary => {}
74 44 : ComputeMode::Static(lsn) => {
75 44 : // hot_standby is 'on' by default, but let's be explicit
76 44 : writeln!(file, "hot_standby=on")?;
77 44 : writeln!(file, "recovery_target_lsn='{lsn}'")?;
78 : }
79 : ComputeMode::Replica => {
80 : // hot_standby is 'on' by default, but let's be explicit
81 5 : writeln!(file, "hot_standby=on")?;
82 : }
83 : }
84 :
85 : // If there are any extra options in the 'settings' field, append those
86 796 : if spec.cluster.settings.is_some() {
87 0 : writeln!(file, "# Managed by compute_ctl: begin")?;
88 0 : write!(file, "{}", spec.cluster.settings.as_pg_settings())?;
89 0 : writeln!(file, "# Managed by compute_ctl: end")?;
90 796 : }
91 :
92 796 : if let Some(port) = extension_server_port {
93 575 : writeln!(file, "neon.extension_server_port={}", port)?;
94 221 : }
95 :
96 : // This is essential to keep this line at the end of the file,
97 : // because it is intended to override any settings above.
98 796 : writeln!(file, "include_if_exists = 'compute_ctl_temp_override.conf'")?;
99 :
100 796 : Ok(())
101 796 : }
102 :
103 : /// create file compute_ctl_temp_override.conf in pgdata_dir
104 : /// add provided options to this file
105 229 : pub fn compute_ctl_temp_override_create(pgdata_path: &Path, options: &str) -> Result<()> {
106 229 : let path = pgdata_path.join("compute_ctl_temp_override.conf");
107 229 : let mut file = File::create(path)?;
108 229 : write!(file, "{}", options)?;
109 229 : Ok(())
110 229 : }
111 :
112 : /// remove file compute_ctl_temp_override.conf in pgdata_dir
113 229 : pub fn compute_ctl_temp_override_remove(pgdata_path: &Path) -> Result<()> {
114 229 : let path = pgdata_path.join("compute_ctl_temp_override.conf");
115 229 : std::fs::remove_file(path)?;
116 229 : Ok(())
117 229 : }
|