Skip to content
Permalink
Browse files Browse the repository at this point in the history
Improve error messages on failure to launch backup process
ztexec can include env vars in the error message which we don't want in this case.
  • Loading branch information
chadlwilson committed Nov 24, 2022
1 parent e3facea commit 6545481
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 31 deletions.
Expand Up @@ -23,4 +23,12 @@ public interface BackupProcessor {
void backup(File targetDir, DataSource dataSource, DbProperties dbProperties) throws Exception;

boolean accepts(String url);

default void throwBackupError(String command, int errorCode) {
throwBackupError(command, errorCode, null);
}

default void throwBackupError(String command, int errorCode, Throwable cause) {
throw new RuntimeException(String.format("There was an error backing up the database using `%s`. The `%s` process failed with code %s. Please see the server logs for more detail.", command, command, errorCode), cause);
}
}
Expand Up @@ -23,32 +23,35 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.tools.ant.types.Commandline;
import org.zeroturnaround.exec.ProcessExecutor;
import org.zeroturnaround.exec.ProcessInitException;
import org.zeroturnaround.exec.ProcessResult;
import org.zeroturnaround.exec.stream.slf4j.Slf4jStream;

import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.*;
import java.util.concurrent.TimeoutException;

import static org.apache.commons.lang3.StringUtils.isNotBlank;

@Slf4j
public class MySQLBackupProcessor implements BackupProcessor {

private static final String COMMAND = "mysqldump";

@Override
public void backup(File targetDir, DataSource dataSource, DbProperties dbProperties) throws InterruptedException, TimeoutException, IOException {
ProcessResult processResult = createProcessExecutor(targetDir, dbProperties).execute();

if (processResult.getExitValue() == 0) {
log.info("MySQL backup finished successfully.");
} else {
log.warn("There was an error backing up the database using `mysqldump`. The `mysqldump` process exited with status code {}.", processResult.getExitValue());
throw new RuntimeException("There was an error backing up the database using `mysqldump`. The `mysqldump` process exited with status code " + processResult.getExitValue() +
". Please see the server logs for more errors");
try {
ProcessResult processResult = createProcessExecutor(targetDir, dbProperties).execute();

if (processResult.getExitValue() == 0) {
log.info("MySQL backup finished successfully.");
} else {
throwBackupError(COMMAND, processResult.getExitValue());
}
} catch (ProcessInitException e) {
throwBackupError(COMMAND, e.getErrorCode(), e.getCause());
}
}

Expand All @@ -60,16 +63,15 @@ public boolean accepts(String url) {
private ProcessExecutor createProcessExecutor(File targetDir, DbProperties dbProperties) {
ConnectionUrl connectionUrlInstance = ConnectionUrl.getConnectionUrlInstance(dbProperties.url(), dbProperties.connectionProperties());

LinkedHashMap<String, String> env = new LinkedHashMap<>();
Map<String, String> env = new LinkedHashMap<>();
if (isNotBlank(dbProperties.password())) {
env.put("MYSQL_PWD", dbProperties.password());
}
// override with any user specified environment
env.putAll(dbProperties.extraBackupEnv());

ArrayList<String> argv = new ArrayList<>();
argv.add("mysqldump");

List<String> argv = new ArrayList<>();
argv.add(COMMAND);

String dbName = connectionUrlInstance.getDatabase();
HostInfo mainHost = connectionUrlInstance.getMainHost();
Expand All @@ -87,7 +89,7 @@ private ProcessExecutor createProcessExecutor(File targetDir, DbProperties dbPro
Collections.addAll(argv, Commandline.translateCommandline(dbProperties.extraBackupCommandArgs()));
}

argv.add("--result-file=" + new File(targetDir, "db." + dbName).toString());
argv.add("--result-file=" + new File(targetDir, "db." + dbName));
argv.add(connectionUrlInstance.getDatabase());

ProcessExecutor processExecutor = new ProcessExecutor();
Expand Down
Expand Up @@ -22,32 +22,33 @@
import org.apache.tools.ant.types.Commandline;
import org.postgresql.Driver;
import org.zeroturnaround.exec.ProcessExecutor;
import org.zeroturnaround.exec.ProcessInitException;
import org.zeroturnaround.exec.ProcessResult;
import org.zeroturnaround.exec.stream.slf4j.Slf4jStream;

import javax.sql.DataSource;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.*;

import static org.apache.commons.lang3.StringUtils.isNotBlank;

@Slf4j
public class PostgresqlBackupProcessor implements BackupProcessor {

private static final String COMMAND = "pg_dump";

@Override
public void backup(File targetDir, DataSource dataSource, DbProperties dbProperties) throws Exception {
ProcessResult processResult = createProcessExecutor(targetDir, dbProperties).execute();

if (processResult.getExitValue() == 0) {
log.info("PostgreSQL backup finished successfully.");
} else {
log.warn("There was an error backing up the database using `pg_dump`. The `pg_dump` process exited with status code {}.", processResult.getExitValue());
throw new RuntimeException("There was an error backing up the database using `pg_dump`. The `pg_dump` process exited with status code " + processResult.getExitValue() +
". Please see the server logs for more errors.");
try {
ProcessResult processResult = createProcessExecutor(targetDir, dbProperties).execute();

if (processResult.getExitValue() == 0) {
log.info("PostgreSQL backup finished successfully.");
} else {
throwBackupError(COMMAND, processResult.getExitValue());
}
} catch (ProcessInitException e) {
throwBackupError(COMMAND, e.getErrorCode(), e.getCause());
}
}

Expand All @@ -60,17 +61,18 @@ ProcessExecutor createProcessExecutor(File targetDir, DbProperties dbProperties)
Properties connectionProperties = dbProperties.connectionProperties();
Properties pgProperties = Driver.parseURL(dbProperties.url(), connectionProperties);

ArrayList<String> argv = new ArrayList<>();
LinkedHashMap<String, String> env = new LinkedHashMap<>();
Map<String, String> env = new LinkedHashMap<>();
if (isNotBlank(dbProperties.password())) {
env.put("PGPASSWORD", dbProperties.password());
}

// override with any user specified environment
env.putAll(dbProperties.extraBackupEnv());

List<String> argv = new ArrayList<>();
argv.add(COMMAND);

String dbName = pgProperties.getProperty("PGDBNAME");
argv.add("pg_dump");
argv.add("--host=" + pgProperties.getProperty("PGHOST"));
argv.add("--port=" + pgProperties.getProperty("PGPORT"));
argv.add("--dbname=" + dbName);
Expand Down

0 comments on commit 6545481

Please sign in to comment.