Skip to content

Commit

Permalink
Clean up CLI parsing and stop depending on Accumulo internals (#61)
Browse files Browse the repository at this point in the history
* Remove dependencies on Accumulo internal CLI parsing code
  by addeing ClientOpts and Help
* Remove trace code from TestIngest
  • Loading branch information
mikewalch committed Feb 27, 2019
1 parent 33c0f38 commit 65c55d0
Show file tree
Hide file tree
Showing 19 changed files with 362 additions and 154 deletions.
8 changes: 0 additions & 8 deletions contrib/import-control.xml
Expand Up @@ -46,14 +46,6 @@
<allow class="org.apache.accumulo.core.clientImpl.TabletServerBatchWriter"/>
<allow class="org.apache.accumulo.core.util.SimpleThreadPool"/>
<allow class="org.apache.accumulo.core.util.FastFormat"/>
<allow class="org.apache.accumulo.core.cli.ClientOnRequiredTable"/>
<allow class="org.apache.accumulo.core.cli.BatchScannerOpts"/>
<allow class="org.apache.accumulo.core.cli.ClientOnDefaultTable"/>
<allow class="org.apache.accumulo.core.cli.ClientOpts.TimeConverter"/>
<allow class="org.apache.accumulo.core.cli.Help"/>
<allow class="org.apache.accumulo.core.cli.BatchWriterOpts"/>
<allow class="org.apache.accumulo.core.cli.ClientOpts"/>
<allow class="org.apache.accumulo.core.cli.ScannerOpts"/>
<allow class="org.apache.accumulo.core.util.Pair"/>
<allow class="org.apache.accumulo.core.trace.Trace"/>
<allow class="org.apache.accumulo.core.trace.TraceSamplers"/>
Expand Down
213 changes: 213 additions & 0 deletions src/main/java/org/apache/accumulo/testing/cli/ClientOpts.java
@@ -0,0 +1,213 @@
/*
* 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.testing.cli;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;

import org.apache.accumulo.core.client.Accumulo;
import org.apache.accumulo.core.client.AccumuloClient;
import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
import org.apache.accumulo.core.conf.ClientProperty;
import org.apache.accumulo.core.conf.ConfigurationTypeHelper;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.accumulo.core.security.ColumnVisibility;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.beust.jcommander.IStringConverter;
import com.beust.jcommander.Parameter;

public class ClientOpts extends Help {

public static class TimeConverter implements IStringConverter<Long> {
@Override
public Long convert(String value) {
return ConfigurationTypeHelper.getTimeInMillis(value);
}
}

public static class AuthConverter implements IStringConverter<Authorizations> {
@Override
public Authorizations convert(String value) {
return new Authorizations(value.split(","));
}
}

public static class Password {
public byte[] value;

public Password(String dfault) {
value = dfault.getBytes(UTF_8);
}

@Override
public String toString() {
return new String(value, UTF_8);
}
}

public static class PasswordConverter implements IStringConverter<Password> {
@Override
public Password convert(String value) {
return new Password(value);
}
}

public static class VisibilityConverter implements IStringConverter<ColumnVisibility> {
@Override
public ColumnVisibility convert(String value) {
return new ColumnVisibility(value);
}
}

@Parameter(names = {"-u", "--user"}, description = "Connection user")
private String principal = null;

@Parameter(names = "-p", converter = PasswordConverter.class, description = "Connection password")
private Password password = null;

@Parameter(names = "--password", converter = PasswordConverter.class,
description = "Enter the connection password", password = true)
private Password securePassword = null;

public AuthenticationToken getToken() {
return ClientProperty.getAuthenticationToken(getClientProperties());
}

@Parameter(names = {"-z", "--keepers"},
description = "Comma separated list of zookeeper hosts (host:port,host:port)")
protected String zookeepers = null;

@Parameter(names = {"-i", "--instance"}, description = "The name of the accumulo instance")
protected String instance = null;

@Parameter(names = {"-auths", "--auths"}, converter = AuthConverter.class,
description = "the authorizations to use when reading or writing")
public Authorizations auths = Authorizations.EMPTY;

@Parameter(names = "--debug", description = "turn on TRACE-level log messages")
public boolean debug = false;

@Parameter(names = "--ssl", description = "Connect to accumulo over SSL")
private boolean sslEnabled = false;

@Parameter(names = "--sasl", description = "Connecto to Accumulo using SASL (supports Kerberos)")
private boolean saslEnabled = false;

@Parameter(names = "--config-file", description = "Read the given client config file. "
+ "If omitted, the classpath will be searched for file named accumulo-client.properties")
private String clientConfigFile = null;

public void startDebugLogging() {
if (debug)
Logger.getLogger("org.apache.accumulo.testing").setLevel(Level.TRACE);
}

@Parameter(names = "--trace", description = "turn on distributed tracing")
public boolean trace = false;

@Parameter(names = "--keytab", description = "Kerberos keytab on the local filesystem")
private String keytabPath = null;

@Override
public void parseArgs(String programName, String[] args, Object... others) {
super.parseArgs(programName, args, others);
startDebugLogging();
}

private Properties cachedProps = null;

public String getPrincipal() {
return ClientProperty.AUTH_PRINCIPAL.getValue(getClientProperties());
}

public void setPrincipal(String principal) {
this.principal = principal;
}

public void setClientProperties(Properties clientProps) {
this.cachedProps = clientProps;
}

/**
* @return {@link AccumuloClient} that must be closed by user
*/
public AccumuloClient createClient() {
return Accumulo.newClient().from(getClientProperties()).build();
}

public String getClientConfigFile() {
if (clientConfigFile == null) {
URL clientPropsUrl = ClientOpts.class.getClassLoader().getResource(
"accumulo-client.properties");
if (clientPropsUrl != null) {
clientConfigFile = clientPropsUrl.getFile();
}
}
return clientConfigFile;
}

public Properties getClientProperties() {
if (cachedProps == null) {
cachedProps = new Properties();
if (getClientConfigFile() != null) {
cachedProps = toProperties(Paths.get(getClientConfigFile()));
}
if (saslEnabled) {
cachedProps.setProperty(ClientProperty.SASL_ENABLED.getKey(), "true");
}
if (sslEnabled) {
cachedProps.setProperty(ClientProperty.SSL_ENABLED.getKey(), "true");
}
if (principal != null) {
cachedProps.setProperty(ClientProperty.AUTH_PRINCIPAL.getKey(), principal);
}
if (zookeepers != null) {
cachedProps.setProperty(ClientProperty.INSTANCE_ZOOKEEPERS.getKey(), zookeepers);
}
if (instance != null) {
cachedProps.setProperty(ClientProperty.INSTANCE_NAME.getKey(), instance);
}
if (securePassword != null) {
ClientProperty.setPassword(cachedProps, securePassword.toString());
} else if (password != null) {
ClientProperty.setPassword(cachedProps, password.toString());
} else if (keytabPath != null) {
ClientProperty.setKerberosKeytab(cachedProps, keytabPath);
}
}
return cachedProps;
}

private static Properties toProperties(Path propertiesFile) {
Properties properties = new Properties();
try (InputStream is = new FileInputStream(propertiesFile.toFile())) {
properties.load(is);
} catch (IOException e) {
throw new IllegalArgumentException("Failed to load properties from " + propertiesFile, e);
}
return properties;
}
}
53 changes: 53 additions & 0 deletions src/main/java/org/apache/accumulo/testing/cli/Help.java
@@ -0,0 +1,53 @@
/*
* 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.testing.cli;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;

public class Help {
@Parameter(names = {"-h", "-?", "--help", "-help"}, help = true)
public boolean help = false;

public void parseArgs(String programName, String[] args, Object... others) {
JCommander commander = new JCommander();
commander.addObject(this);
for (Object other : others)
commander.addObject(other);
commander.setProgramName(programName);
try {
commander.parse(args);
} catch (ParameterException ex) {
commander.usage();
exitWithError(ex.getMessage(), 1);
}
if (help) {
commander.usage();
exit(0);
}
}

public void exit(int status) {
System.exit(status);
}

public void exitWithError(String message, int status) {
System.err.println(message);
exit(status);
}
}
Expand Up @@ -27,8 +27,8 @@
import java.util.Set;
import java.util.TreeMap;

import org.apache.accumulo.core.cli.ClientOpts.TimeConverter;
import org.apache.accumulo.core.cli.Help;
import org.apache.accumulo.testing.cli.ClientOpts.TimeConverter;
import org.apache.accumulo.testing.cli.Help;

import com.beust.jcommander.Parameter;

Expand Down
Expand Up @@ -18,7 +18,6 @@

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
Expand All @@ -31,16 +30,14 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import com.beust.jcommander.Parameter;
import org.apache.accumulo.core.cli.BatchScannerOpts;
import org.apache.accumulo.core.cli.ClientOnDefaultTable;
import org.apache.accumulo.core.client.AccumuloClient;
import org.apache.accumulo.core.client.BatchScanner;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Range;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.testing.cli.ClientOpts;
import org.apache.hadoop.io.Text;

import static java.nio.charset.StandardCharsets.UTF_8;
Expand Down Expand Up @@ -235,14 +232,12 @@ TabletAssignment findMostRecentAssignment(String row, long time1, long time2) {
}
}

static class Opts extends ClientOnDefaultTable {
static class Opts extends ClientOpts {
@Parameter(names = "--logdir", description = "directory containing the log files",
required = true)
String logDir;

Opts() {
super("ci");
}
@Parameter(names = {"-t", "--table"}, description = "table to use")
String tableName = "ci";
}

/**
Expand All @@ -251,8 +246,7 @@ static class Opts extends ClientOnDefaultTable {
*/
public static void main(String[] args) throws Exception {
Opts opts = new Opts();
BatchScannerOpts bsOpts = new BatchScannerOpts();
opts.parseArgs(UndefinedAnalyzer.class.getName(), args, bsOpts);
opts.parseArgs(UndefinedAnalyzer.class.getName(), args);

List<UndefinedNode> undefs = new ArrayList<>();

Expand All @@ -268,9 +262,7 @@ public static void main(String[] args) throws Exception {
}

try (AccumuloClient client = opts.createClient();
BatchScanner bscanner = client.createBatchScanner(opts.getTableName(), opts.auths,
bsOpts.scanThreads)) {
bscanner.setTimeout(bsOpts.scanTimeout, TimeUnit.MILLISECONDS);
BatchScanner bscanner = client.createBatchScanner(opts.tableName, opts.auths)) {
List<Range> refs = new ArrayList<>();

for (UndefinedNode undefinedNode : undefs)
Expand All @@ -287,7 +279,7 @@ public static void main(String[] args) throws Exception {
}

IngestInfo ingestInfo = new IngestInfo(opts.logDir);
String tableId = client.tableOperations().tableIdMap().get(opts.getTableName());
String tableId = client.tableOperations().tableIdMap().get(opts.tableName);
TabletHistory tabletHistory = new TabletHistory(tableId, opts.logDir);

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Expand Down
Expand Up @@ -18,18 +18,20 @@

import java.io.IOException;

import org.apache.accumulo.core.cli.ClientOnRequiredTable;
import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.testing.cli.ClientOpts;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import com.beust.jcommander.Parameter;

public class BulkImportDirectory {
static class Opts extends ClientOnRequiredTable {
static class Opts extends ClientOpts {
@Parameter(names = {"-t", "--table"}, required = true, description = "table to use")
String tableName;
@Parameter(names = {"-s", "--source"}, description = "directory to import from")
String source = null;
@Parameter(names = {"-f", "--failures"},
Expand All @@ -47,6 +49,6 @@ public static void main(String[] args) throws IOException, AccumuloException,
fs.delete(new Path(opts.failures), true);
fs.mkdirs(new Path(opts.failures));
opts.createClient().tableOperations()
.importDirectory(opts.getTableName(), opts.source, opts.failures, false);
.importDirectory(opts.tableName, opts.source, opts.failures, false);
}
}

0 comments on commit 65c55d0

Please sign in to comment.