EdColeman commented on code in PR #2751:
URL: https://github.com/apache/accumulo/pull/2751#discussion_r925560342


##########
server/base/src/main/java/org/apache/accumulo/server/conf/util/ZooInfoViewer.java:
##########
@@ -0,0 +1,540 @@
+/*
+ * 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.accumulo.server.conf.util;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.core.Constants.ZINSTANCES;
+import static org.apache.accumulo.core.Constants.ZNAMESPACES;
+import static org.apache.accumulo.core.Constants.ZNAMESPACE_NAME;
+import static org.apache.accumulo.core.Constants.ZROOT;
+import static org.apache.accumulo.core.Constants.ZTABLES;
+import static org.apache.accumulo.core.Constants.ZTABLE_NAME;
+import static org.apache.accumulo.core.Constants.ZTABLE_NAMESPACE;
+
+import java.io.BufferedWriter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import org.apache.accumulo.core.cli.ConfigOpts;
+import org.apache.accumulo.core.clientImpl.Namespace;
+import org.apache.accumulo.core.conf.SiteConfiguration;
+import org.apache.accumulo.core.data.InstanceId;
+import org.apache.accumulo.core.data.NamespaceId;
+import org.apache.accumulo.core.data.TableId;
+import org.apache.accumulo.fate.zookeeper.ZooReader;
+import org.apache.accumulo.fate.zookeeper.ZooReaderWriter;
+import org.apache.accumulo.fate.zookeeper.ZooUtil;
+import org.apache.accumulo.server.ServerContext;
+import org.apache.accumulo.server.conf.codec.VersionedProperties;
+import org.apache.accumulo.server.conf.store.NamespacePropKey;
+import org.apache.accumulo.server.conf.store.SystemPropKey;
+import org.apache.accumulo.server.conf.store.TablePropKey;
+import org.apache.accumulo.server.conf.store.impl.PropStoreWatcher;
+import org.apache.accumulo.server.conf.store.impl.ReadyMonitor;
+import org.apache.accumulo.server.conf.store.impl.ZooPropStore;
+import org.apache.accumulo.start.spi.KeywordExecutable;
+import org.apache.zookeeper.KeeperException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.beust.jcommander.Parameter;
+import com.google.auto.service.AutoService;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+@AutoService(KeywordExecutable.class)
+@SuppressFBWarnings(value = "PATH_TRAVERSAL_OUT",
+    justification = "app is run in same security context as user providing the 
filename")
+public class ZooInfoViewer implements KeywordExecutable {
+  public static final DateTimeFormatter tsFormat =
+      
DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.from(ZoneOffset.UTC));
+  private static final Logger log = 
LoggerFactory.getLogger(ZooInfoViewer.class);
+  private final NullWatcher nullWatcher =
+      new NullWatcher(new ReadyMonitor(ZooInfoViewer.class.getSimpleName(), 
20_000L));
+
+  private static final String INDENT = "  ";
+
+  /**
+   * No-op constructor - provided so ServiceLoader autoload does not consume 
resources.
+   */
+  public ZooInfoViewer() {}
+
+  public static void main(String[] args) throws Exception {
+    new ZooInfoViewer().execute(args);
+  }
+
+  @Override
+  public String keyword() {
+    return "zoo-info-viewer";
+  }
+
+  @Override
+  public String description() {
+    return "view Accumulo instance and property information stored in 
ZooKeeper";
+  }
+
+  @Override
+  public void execute(String[] args) {
+
+    ZooInfoViewer.Opts opts = new ZooInfoViewer.Opts();
+    opts.parseArgs(ZooInfoViewer.class.getName(), args);
+
+    log.info("print ids map: {}", opts.printIdMap);
+    log.info("print properties: {}", opts.printProps);
+    log.info("print instances: {}", opts.printInstanceIds);
+
+    ZooReader zooReader = new ZooReaderWriter(opts.getSiteConfiguration());
+
+    InstanceId iid = getInstanceId(zooReader, opts);
+    try {
+      generateReport(iid, opts, zooReader);
+    } catch (FileNotFoundException ex) {
+      throw new IllegalStateException("Failed to generate ZooKeeper info 
report", ex);
+    }
+  }
+
+  void generateReport(final InstanceId iid, final ZooInfoViewer.Opts opts,
+      final ZooReader zooReader) throws FileNotFoundException {
+
+    OutputStream outStream;
+
+    String outfile = opts.getOutfile();
+    if (outfile == null || outfile.isEmpty()) {
+      log.trace("No output file, using stdout.");
+      outStream = System.out;
+    } else {
+      outStream = new FileOutputStream(outfile);
+    }
+
+    try (PrintWriter writer =
+        new PrintWriter(new BufferedWriter(new OutputStreamWriter(outStream, 
UTF_8)))) {
+
+      writer.println("-----------------------------------------------");
+      writer.println("Report Time: " + tsFormat.format(Instant.now()));
+      writer.println("-----------------------------------------------");
+      if (opts.printInstanceIds) {
+        Map<String,InstanceId> instanceMap = readInstancesFromZk(zooReader);
+        printInstanceIds(instanceMap, writer);
+      }
+
+      if (opts.printIdMap) {
+        printIdMapping(iid, zooReader, writer);
+      }
+
+      if (opts.printProps) {
+        printProps(iid, zooReader, opts, writer);
+      }
+
+      writer.println("-----------------------------------------------");
+    }
+  }
+
+  /**
+   * Get the instanceID from the command line options, or from value stored in 
HDFS. The search
+   * order is:
+   * <ol>
+   * <li>command line: --instanceId option</li>
+   * <li>command line: --instanceName option</li>
+   * <li>HDFS</li>
+   * </ol>
+   *
+   * @param zooReader
+   *          a ZooReader
+   * @param opts
+   *          the parsed command line options.
+   * @return an instance id
+   */
+  InstanceId getInstanceId(final ZooReader zooReader, final ZooInfoViewer.Opts 
opts) {
+
+    if (!opts.instanceId.isEmpty()) {
+      return InstanceId.of(opts.instanceId);
+    }
+    if (!opts.instanceName.isEmpty()) {
+      Map<String,InstanceId> instanceNameToIdMap = 
readInstancesFromZk(zooReader);
+      String instanceName = opts.instanceName;
+      for (Map.Entry<String,InstanceId> e : instanceNameToIdMap.entrySet()) {
+        if (e.getKey().equals(instanceName)) {
+          return e.getValue();
+        }
+      }
+      throw new IllegalArgumentException(
+          "Specified instance name '" + instanceName + "' not found in 
ZooKeeper");
+    }
+
+    try (ServerContext context = new ServerContext(SiteConfiguration.auto())) {
+      return context.getInstanceID();
+    } catch (Exception ex) {
+      throw new IllegalArgumentException(
+          "Failed to read instance id from HDFS. Instances can be specified on 
the command line",
+          ex);
+    }
+  }
+
+  Map<NamespaceId,String> getNamespaceIdToNameMap(InstanceId iid, final 
ZooReader zooReader) {
+    SortedMap<NamespaceId,String> namespaceToName = new TreeMap<>();
+    String zooNsRoot = ZooUtil.getRoot(iid) + ZNAMESPACES;
+    try {
+      List<String> nsids = zooReader.getChildren(zooNsRoot);
+      for (String id : nsids) {
+        String path = zooNsRoot + "/" + id + ZNAMESPACE_NAME;
+        String name = new String(zooReader.getData(path), UTF_8);
+        namespaceToName.put(NamespaceId.of(id), name);
+      }
+    } catch (InterruptedException ex) {
+      Thread.currentThread().interrupt();
+      throw new IllegalStateException("Interrupted reading namespace ids from 
ZooKeeper", ex);
+    } catch (KeeperException ex) {
+      throw new IllegalStateException("Failed to read namespace ids from 
ZooKeeper", ex);
+    }
+    return namespaceToName;
+  }
+
+  private void printProps(final InstanceId iid, final ZooReader zooReader, 
final Opts opts,
+      final PrintWriter writer) {
+
+    if (opts.printAllProps()) {
+      log.info("all: {}", opts.printAllProps());
+    } else {
+      log.info("Filters:");
+      log.info("system: {}", opts.printSysProps());
+      log.info("namespaces: {} {}", opts.printNamespaceProps(),
+          opts.getNamespaces().size() > 0 ? opts.getNamespaces() : "");
+      log.info("tables: {} {}", opts.printTableProps(),
+          opts.getTables().size() > 0 ? opts.getTables() : "");

Review Comment:
   I will defer this for a follow on if someone else thinks it needs to change.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to