PgIsReady gets the status from the pg_isready command
()
| 1286 | |
| 1287 | // PgIsReady gets the status from the pg_isready command |
| 1288 | func PgIsReady() error { |
| 1289 | // We just use the environment variables we already have |
| 1290 | // to pass the connection parameters |
| 1291 | options := []string{ |
| 1292 | "-U", "postgres", |
| 1293 | "-d", "postgres", |
| 1294 | "-q", |
| 1295 | } |
| 1296 | |
| 1297 | // Run `pg_isready` which returns 0 if everything is OK. |
| 1298 | // It returns 1 when PostgreSQL is not ready to accept |
| 1299 | // connections but, it is starting up (this is a valid |
| 1300 | // condition for example for a standby that is fetching |
| 1301 | // WAL files and trying to reach a consistent state). |
| 1302 | cmd := exec.Command(pgIsReady, options...) // #nosec G204 |
| 1303 | err := cmd.Run() |
| 1304 | |
| 1305 | // Verify that `pg_isready` has been executed correctly. |
| 1306 | // We expect that `pg_isready` returns 0 (err == nil) or another |
| 1307 | // valid exit code such as 1 or 2 |
| 1308 | var exitError *exec.ExitError |
| 1309 | if err == nil || errors.As(err, &exitError) { |
| 1310 | switch code := cmd.ProcessState.ExitCode(); code { |
| 1311 | case pqPingOk: |
| 1312 | return nil |
| 1313 | case pqPingReject: |
| 1314 | return ErrPgRejectingConnection |
| 1315 | case pqPingNoResponse: |
| 1316 | return ErrNoConnectionEstablished |
| 1317 | case pgPingNoAttempt: |
| 1318 | return fmt.Errorf("pg_isready usage error: %w", err) |
| 1319 | default: |
| 1320 | return fmt.Errorf("unknown exit code %d: %w", code, err) |
| 1321 | } |
| 1322 | } |
| 1323 | |
| 1324 | // `pg_isready` had an unexpected failure |
| 1325 | return fmt.Errorf("failure executing %s: %w", pgIsReady, err) |
| 1326 | } |
| 1327 | |
| 1328 | func (instance *Instance) buildPgControldataCommand() *exec.Cmd { |
| 1329 | pgControlDataCmd := exec.Command(pgControlDataName) |