diff --git a/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md b/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md index aeccf1dcfce..411f4d89f8f 100644 --- a/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md +++ b/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md @@ -46,11 +46,13 @@ ZooKeeper -server host:port cmd args deleteall path delquota [-n|-b|-N|-B] path exit + export path filepath get [-s] [-w] path getAcl [-s] path getAllChildrenNumber path getEphemerals path history + import path filepath listquota path ls [-s] [-w] [-R] path printwatches on|off @@ -194,8 +196,15 @@ Delete the quota under a path [zkshell: 4] delquota -N /c2 [zkshell: 5] delquota -b /c3 [zkshell: 6] delquota -B /c4 +``` + +## export +Download the contents of a znode to an external file +```bash +[zkshell: 1] export /zookeeper/config path/to/config.txt ``` + ## get Get the data of the specific path @@ -285,6 +294,13 @@ Showing the history about the recent 11 commands that you have executed 7 - history ``` +## import +Upload the contents of an external file to a znode, replacing the znode's previous contents + +```bash +[zkshell: 1] import /zookeeper/config path/to/config.txt +``` + ## listquota Listing the quota of one path diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CommandFactory.java b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CommandFactory.java index 681eabad512..bb5b740473f 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CommandFactory.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/CommandFactory.java @@ -38,6 +38,8 @@ public enum Command { LS(LsCommand::new), GET_ACL(GetAclCommand::new), SET_ACL(SetAclCommand::new), + EXPORT(ExportCommand::new), + IMPORT(ImportCommand::new), STAT(StatCommand::new), SYNC(SyncCommand::new), SET_QUOTA(SetQuotaCommand::new), diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/ExportCommand.java b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/ExportCommand.java new file mode 100644 index 00000000000..4f39d03a270 --- /dev/null +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/ExportCommand.java @@ -0,0 +1,93 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.zookeeper.cli; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.data.Stat; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +/** + * export command for cli + */ +public class ExportCommand extends CliCommand { + + private static Options options = new Options(); + private String args[]; + private CommandLine cl; + + static { + options.addOption("s", false, "stats"); + options.addOption("w", false, "watch"); + } + + public ExportCommand() { + super("export", "[-s] [-w] path filepath"); + } + + @Override + public CliCommand parse(String[] cmdArgs) throws CliParseException { + + CommandLineParser parser = new DefaultParser(); + try { + cl = parser.parse(options, cmdArgs); + } catch (ParseException ex) { + throw new CliParseException(ex); + } + args = cl.getArgs(); + if (args.length < 3) { + throw new CliParseException(getUsageStr()); + } + + return this; + } + + @Override + public boolean exec() throws CliException { + boolean watch = cl.hasOption("w"); + String path = args[1]; + String filepath = args[2]; + Stat stat = new Stat(); + byte data[]; + try { + data = zk.getData(path, watch, stat); + } catch (IllegalArgumentException ex) { + throw new MalformedPathException(ex.getMessage()); + } catch (KeeperException|InterruptedException ex) { + throw new CliException(ex); + } + data = (data == null) ? "null".getBytes() : data; + try { + Files.write(Paths.get(filepath), data, StandardOpenOption.CREATE); + } catch (IOException ex) { + throw new CliException("Unable to write data to file \"" + filepath + "\"", ex); + } + if (cl.hasOption("s")) { + new StatPrinter(out).print(stat); + } + return watch; + } +} diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/cli/ImportCommand.java b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/ImportCommand.java new file mode 100644 index 00000000000..afe5f9187e5 --- /dev/null +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/cli/ImportCommand.java @@ -0,0 +1,95 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.zookeeper.cli; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.data.Stat; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +/** + * import command for cli + */ +public class ImportCommand extends CliCommand { + + private static Options options = new Options(); + private String[] args; + private CommandLine cl; + + static { + options.addOption("s", false, "stats"); + options.addOption("v", true, "version"); + } + + public ImportCommand() { + super("import", "[-s] [-v version] path filepath"); + } + + @Override + public CliCommand parse(String[] cmdArgs) throws CliParseException { + CommandLineParser parser = new DefaultParser(); + try { + cl = parser.parse(options, cmdArgs); + } catch (ParseException ex) { + throw new CliParseException(ex); + } + args = cl.getArgs(); + if (args.length < 3) { + throw new CliParseException(getUsageStr()); + } + + return this; + } + + @Override + public boolean exec() throws CliException { + String path = args[1]; + String filepath = args[2]; + byte[] data; + try { + data = Files.readAllBytes(Paths.get(filepath)); + } catch (IOException ex) { + throw new CliException("Unable to read data from file \"" + filepath + "\"", ex); + } + int version; + if (cl.hasOption("v")) { + version = Integer.parseInt(cl.getOptionValue("v")); + } else { + version = -1; + } + + try { + Stat stat = zk.setData(path, data, version); + if (cl.hasOption("s")) { + new StatPrinter(out).print(stat); + } + } catch (IllegalArgumentException ex) { + throw new MalformedPathException(ex.getMessage()); + } catch (KeeperException|InterruptedException ex) { + throw new CliWrapperException(ex); + } + return false; + } +}