Skip to content

Commit

Permalink
0001063: Add export-config and import-config command line options to
Browse files Browse the repository at this point in the history
symadmin
  • Loading branch information
JishLong committed Jul 19, 2023
1 parent 189c005 commit 916c3bb
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 4 deletions.
Expand Up @@ -30,6 +30,7 @@
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
Expand All @@ -54,6 +55,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.sql.SqlScript;
import org.jumpmind.exception.IoException;
import org.jumpmind.properties.TypedProperties;
import org.jumpmind.security.ISecurityService;
Expand All @@ -62,6 +64,10 @@
import org.jumpmind.security.SecurityServiceFactory.SecurityServiceType;
import org.jumpmind.symmetric.common.ParameterConstants;
import org.jumpmind.symmetric.common.ServerConstants;
import org.jumpmind.symmetric.common.TableConstants;
import org.jumpmind.symmetric.io.data.DbExportUtils;
import org.jumpmind.symmetric.model.AbstractBatch.Status;
import org.jumpmind.symmetric.model.IncomingBatch;
import org.jumpmind.symmetric.model.Node;
import org.jumpmind.symmetric.model.TriggerHistory;
import org.jumpmind.symmetric.service.IDataExtractorService;
Expand All @@ -70,9 +76,9 @@
import org.jumpmind.symmetric.service.IPurgeService;
import org.jumpmind.symmetric.service.IRegistrationService;
import org.jumpmind.symmetric.service.ITriggerRouterService;
import org.jumpmind.symmetric.util.PropertiesUtil;
import org.jumpmind.symmetric.util.ModuleException;
import org.jumpmind.symmetric.util.ModuleManager;
import org.jumpmind.symmetric.util.PropertiesUtil;
import org.jumpmind.util.AppUtils;
import org.jumpmind.util.JarBuilder;
import org.jumpmind.util.ZipBuilder;
Expand Down Expand Up @@ -107,6 +113,8 @@ public class SymmetricAdmin extends AbstractCommandLauncher {
private static final String CMD_SEND_SCHEMA = "send-schema";
private static final String CMD_BACKUP_FILE_CONFIGURATION = "backup-config";
private static final String CMD_RESTORE_FILE_CONFIGURATION = "restore-config";
private static final String CMD_IMPORT_CONFIG = "import-config";
private static final String CMD_EXPORT_CONFIG = "export-config";
private static final String[] NO_ENGINE_REQUIRED = { CMD_EXPORT_PROPERTIES, CMD_ENCRYPT_TEXT, CMD_OBFUSCATE_TEXT, CMD_UNOBFUSCATE_TEXT, CMD_LIST_ENGINES,
CMD_MODULE, CMD_BACKUP_FILE_CONFIGURATION, CMD_RESTORE_FILE_CONFIGURATION, CMD_CREATE_WAR };
private static final String OPTION_NODE = "node";
Expand Down Expand Up @@ -191,6 +199,8 @@ protected void printHelp(CommandLine line, Options options) {
printHelpLine(pw, CMD_RESTORE_FILE_CONFIGURATION);
printHelpLine(pw, CMD_UNINSTALL);
printHelpLine(pw, CMD_MODULE);
printHelpLine(pw, CMD_IMPORT_CONFIG);
printHelpLine(pw, CMD_EXPORT_CONFIG);
pw.flush();
}
}
Expand Down Expand Up @@ -375,6 +385,12 @@ protected boolean executeWithOptions(CommandLine line) throws Exception {
} else if (cmd.equals(CMD_RESTORE_FILE_CONFIGURATION)) {
restore(line, args);
return true;
} else if (cmd.equals(CMD_IMPORT_CONFIG)) {
importConfig(line, args);
return true;
} else if (cmd.equals(CMD_EXPORT_CONFIG)) {
exportConfig(line, args);
return true;
} else {
throw new ParseException("ERROR: no subcommand '" + cmd + "' was found.");
}
Expand All @@ -388,6 +404,52 @@ private String popArg(List<String> args, String argName) {
return args.remove(0);
}

private void importConfig(CommandLine line, List<String> args) {
String fileName = popArg(args, "file name");
try {
File configFile = new File(fileName);
if (fileName.toLowerCase().endsWith(".csv")) {
String content = FileUtils.readFileToString(configFile, Charset.defaultCharset());
IDataLoaderService service = getSymmetricEngine().getDataLoaderService();
List<IncomingBatch> batches = service.loadDataBatch(content);
for (IncomingBatch batch : batches) {
if (batch.getStatus() == Status.ER) {
System.err.println("ERROR: batch failed with batch ID " + batch.getBatchId() + ".");
System.exit(1);
}
}
} else if (fileName.toLowerCase().endsWith(".sql")) {
URL url = configFile.toURI().toURL();
SqlScript script = new SqlScript(url, getSymmetricEngine().getDatabasePlatform().getSqlTemplate());
script.execute();
} else {
System.err.println("ERROR: Expected a .csv or .sql file.");
System.exit(1);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void exportConfig(CommandLine line, List<String> args) {
String fileName = popArg(args, "file name");
try (FileWriter fw = new FileWriter(fileName)) {
if (fileName.toLowerCase().endsWith(".csv")) {
IDataExtractorService dataExtractorService = getSymmetricEngine().getDataExtractorService();
Node me = getSymmetricEngine().getNodeService().findIdentity();
dataExtractorService.extractConfigurationStandalone(me, fw, TableConstants.getConfigTablesExcludedFromExport());
} else if (fileName.toLowerCase().endsWith(".sql")) {
DbExportUtils.extractConfigurationStandalone(getSymmetricEngine().getDatabasePlatform(), TableConstants.getConfigTablesForExport(
getSymmetricEngine().getTablePrefix()), fw);
} else {
System.err.println("ERROR: Expected a .csv or .sql file.");
System.exit(1);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void listEngines(CommandLine line, List<String> args) {
System.out.println("Engines directory is " + new File(PropertiesUtil.getEnginesDir()).getAbsolutePath());
System.out.println("The following engines and properties files are available:");
Expand Down
Expand Up @@ -76,6 +76,8 @@ SymAdmin.Cmd.uninstall=Uninstall all SymmetricDS objects from the database
SymAdmin.Cmd.module=Manage modules to add or remove features
SymAdmin.Cmd.backup-config=Backup configuration files
SymAdmin.Cmd.restore-config=Restore configuration files
SymAdmin.Cmd.import-config=Import a node configuration file
SymAdmin.Cmd.export-config=Export a node configuration file
SymAdmin.Usage.reload-node=<node-id>
SymAdmin.Usage.reload-table=<table> [<table> ...]
SymAdmin.Usage.export-batch=<node-id> <batch number> [<filename>]
Expand All @@ -100,6 +102,8 @@ SymAdmin.Usage.uninstall=
SymAdmin.Usage.backup-config=
SymAdmin.Usage.restore-config=
SymAdmin.Usage.module=[install <module> | remove <module> | list-files <module> | list | list-all | upgrade | convert]
SymAdmin.Usage.import-config=<filename>
SymAdmin.Usage.export-config=<filename>
SymAdmin.Help.export-sym-tables=Output the SQL to create the SymmetricDS tables. If --alters is specified, then alters to the existing tables will be output. If a filename is given, the SQL statements are written to it, otherwise standard output is used.
SymAdmin.Help.run-job=Run one of the scheduled jobs immediately.
SymAdmin.Help.list-engines=List each engine name and properties file configured on this instance.
Expand All @@ -124,6 +128,8 @@ SymAdmin.Help.uninstall=Uninstall all SymmetricDS objects from the database, inc
SymAdmin.Help.module=\nManage modules to add or remove features.\n\nmodule list List modules that are currently installed\nmodule list-all List all modules available to install\nmodule list-files <module> List files for a module that is installed\nmodule list-deps <module> List dependencies for a module\nmodule install <module> Install a module\nmodule remove <module> Remove a module\nmodule upgrade Upgrade modules to latest version\nmodule convert Read engine files and install required modules
SymAdmin.Help.backup-config=Backup configuration files to a zip file for later restoration if necessary.
SymAdmin.Help.restore-config=Restore configuration files from a zip file.
SymAdmin.Help.import-config=Import configuration for a node in the form of CSV or SQL data.
SymAdmin.Help.export-config=Export a node's configuration in the form of CSV or SQL data.
SymAdmin.Option.catalog=Look for tables in catalog.
SymAdmin.Option.schema=Look for tables in schema.
SymAdmin.Option.where=Add where clause to SQL statement that selects data from table.
Expand Down
Expand Up @@ -202,13 +202,13 @@ public void contextComplete(Context context) {
if (context.remove(CTX_KEY_FLUSH_TRANSFORMS_NEEDED) != null) {
flushTransforms();
}
if (context.remove(CTX_KEY_RESTART_JOB_MANAGER_NEEDED) != null) {
if (context.remove(CTX_KEY_RESTART_JOB_MANAGER_NEEDED) != null && engine.isStarted()) {
log.info("Clearing cache for jobs and restarting jobs");
engine.getJobManager().init();
engine.getJobManager().startJobs();
context.remove(CTX_KEY_CHANGED_JOB_IDS);
}
if (context.get(CTX_KEY_CHANGED_JOB_IDS) != null) {
if (context.get(CTX_KEY_CHANGED_JOB_IDS) != null && engine.isStarted()) {
restartJobs(context);
}
if (context.remove(CTX_KEY_RESYNC_NEEDED) != null && isSyncTriggersAllowed(context)) {
Expand Down Expand Up @@ -286,7 +286,7 @@ private void enableDisableFileSync(Context context) {
engine.getConfigurationService().initDefaultChannels();
engine.getFileSyncService().clearCache();
IJobManager jobManager = engine.getJobManager();
if (jobManager != null) {
if (jobManager != null && engine.isStarted()) {
jobManager.restartJob(ClusterConstants.FILE_SYNC_TRACKER);
jobManager.restartJob(ClusterConstants.FILE_SYNC_PULL);
jobManager.restartJob(ClusterConstants.FILE_SYNC_PUSH);
Expand Down
@@ -0,0 +1,39 @@
package org.jumpmind.symmetric.io.data;

import java.io.IOException;
import java.io.Writer;
import java.util.List;

import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.platform.IDatabasePlatform;
import org.jumpmind.symmetric.io.data.DbExport.Format;

public class DbExportUtils {
public static void extractConfigurationStandalone(IDatabasePlatform platform, List<String> tables, Writer out) throws IOException {
DbExport export = new DbExport(platform);
export.setFormat(Format.SQL);
export.setNoCreateInfo(true);
export.setUseQuotedIdentifiers(false);
for (int i = tables.size() - 1; i >= 0; i--) {
String tableName = platform.alterCaseToMatchDatabaseDefaultCase(tables.get(i));
out.write(String.format("delete from %s;\n", tableName));
}
String quote = platform.getDdlBuilder().getDatabaseInfo().getDelimiterToken();
for (String tableName : tables) {
String appendSql = "order by ";
Table table = platform.getTableFromCache(null, null, tableName, false);
if (table != null) {
Column[] pkColumns = table.getPrimaryKeyColumns();
for (int j = 0; j < pkColumns.length; j++) {
if (j > 0) {
appendSql += ", ";
}
appendSql += quote + pkColumns[j].getName() + quote;
}
}
export.setWhereClause(appendSql);
out.write(export.exportTables(new String[] { tableName }));
}
}
}

0 comments on commit 916c3bb

Please sign in to comment.