accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mwa...@apache.org
Subject [accumulo] branch master updated: More work to remove usage of Instance (#532)
Date Tue, 26 Jun 2018 17:39:55 GMT
This is an automated email from the ASF dual-hosted git repository.

mwalch pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/accumulo.git


The following commit(s) were added to refs/heads/master by this push:
     new 99851cd  More work to remove usage of Instance (#532)
99851cd is described below

commit 99851cd0f508033dfc3d7b82e48cbeb9effd0767
Author: Mike Walch <mwalch@apache.org>
AuthorDate: Tue Jun 26 13:39:52 2018 -0400

    More work to remove usage of Instance (#532)
    
    * Created Connector.changeUser() method
    * Added getClientInfo() to AccumuloOutputFormat
    * Set ZK session timeout for clients in ITs
    * Refactored shell code to remove use of Instance
---
 .../core/client/mapred/AbstractInputFormat.java    |  33 ++--
 .../core/client/mapred/AccumuloOutputFormat.java   |  27 ++-
 .../core/client/mapreduce/AbstractInputFormat.java |  32 ++--
 .../client/mapreduce/AccumuloOutputFormat.java     |  30 ++--
 .../mapreduce/lib/impl/InputConfigurator.java      |  13 +-
 .../mapreduce/lib/impl/MapReduceClientOpts.java    |   3 +-
 .../apache/accumulo/core/client/ClientInfo.java    |  15 ++
 .../org/apache/accumulo/core/client/Connector.java |  13 ++
 .../core/client/impl/ConditionalWriterImpl.java    |   4 +-
 .../accumulo/core/client/impl/ConnectorImpl.java   |   8 +-
 .../accumulo/core/client/impl/OfflineIterator.java |  15 +-
 .../accumulo/core/client/impl/OfflineScanner.java  |  17 +-
 .../core/client/impl/TableOperationsImpl.java      |  22 +--
 .../apache/accumulo/core/client/impl/Tables.java   |  13 ++
 .../impl/TabletServerBatchReaderIterator.java      |  11 +-
 .../core/client/impl/TabletServerBatchWriter.java  |   4 +-
 .../accumulo/core/client/impl/ThriftScanner.java   |  15 +-
 .../apache/accumulo/core/conf/ClientProperty.java  |   6 +
 .../core/client/impl/TableOperationsImplTest.java  |   4 +-
 .../java/org/apache/accumulo/master/Master.java    |   2 +-
 .../master/metrics/Metrics2ReplicationMetrics.java |   2 +-
 .../master/metrics/ReplicationMetrics.java         |   2 +-
 .../accumulo/master/tableOps/CompactionDriver.java |   6 +-
 .../accumulo/master/tableOps/RenameTable.java      |   2 +-
 .../accumulo/master/tableOps/WriteExportFiles.java |  11 +-
 .../master/tableOps/bulkVer1/BulkImport.java       |   4 +-
 .../master/tableOps/bulkVer1/CopyFailed.java       |   4 +-
 .../master/tableOps/bulkVer2/PrepBulkImport.java   |   2 +-
 .../java/org/apache/accumulo/monitor/Monitor.java  |  16 +-
 .../org/apache/accumulo/tracer/TraceServer.java    |  18 +-
 .../tserver/replication/AccumuloReplicaSystem.java |   7 +-
 .../accumulo/tserver/tablet/MinorCompactor.java    |   3 +-
 shell/pom.xml                                      |   5 -
 .../main/java/org/apache/accumulo/shell/Shell.java | 187 +++++++--------------
 .../org/apache/accumulo/shell/ShellOptionsJC.java  |  32 +---
 .../accumulo/shell/commands/CreateUserCommand.java |   2 +-
 .../accumulo/shell/commands/TraceCommand.java      |   2 +-
 .../org/apache/accumulo/shell/ShellConfigTest.java |  16 --
 .../accumulo/shell/ShellSetInstanceTest.java       | 161 ------------------
 .../accumulo/test/ArbitraryTablePropertiesIT.java  |   4 +-
 .../apache/accumulo/test/ConditionalWriterIT.java  |   5 +-
 .../org/apache/accumulo/test/NamespacesIT.java     |   2 +-
 .../java/org/apache/accumulo/test/SampleIT.java    |   6 +-
 .../accumulo/test/functional/ConnectorIT.java      |  13 ++
 .../accumulo/test/functional/CredentialsIT.java    |   8 +-
 .../accumulo/test/functional/MasterFailoverIT.java |   2 +
 .../accumulo/test/functional/PermissionsIT.java    |   4 +-
 .../apache/accumulo/test/functional/RestartIT.java |   2 +
 .../apache/accumulo/test/functional/SummaryIT.java |   5 +-
 .../test/functional/TableChangeStateIT.java        |   2 +-
 .../functional/TabletStateChangeIteratorIT.java    |   8 +-
 .../test/functional/ZookeeperRestartIT.java        |   2 +
 .../accumulo/test/master/SuspendedTabletsIT.java   |   2 +
 .../metadata/MetadataBatchScanTest.java            |   5 +-
 .../accumulo/test/proxy/ProxyDurabilityIT.java     |   2 +
 ...GarbageCollectorCommunicatesWithTServersIT.java |   2 +
 .../test/replication/KerberosReplicationIT.java    |   2 +
 .../replication/MultiInstanceReplicationIT.java    |   2 +
 .../UnorderedWorkAssignerReplicationIT.java        |   2 +
 59 files changed, 315 insertions(+), 534 deletions(-)

diff --git a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AbstractInputFormat.java b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AbstractInputFormat.java
index 31d57a4..1f849d4 100644
--- a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AbstractInputFormat.java
+++ b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AbstractInputFormat.java
@@ -48,7 +48,6 @@ import org.apache.accumulo.core.client.admin.DelegationTokenConfig;
 import org.apache.accumulo.core.client.admin.SecurityOperations;
 import org.apache.accumulo.core.client.impl.AuthenticationTokenIdentifier;
 import org.apache.accumulo.core.client.impl.ClientContext;
-import org.apache.accumulo.core.client.impl.Credentials;
 import org.apache.accumulo.core.client.impl.DelegationTokenImpl;
 import org.apache.accumulo.core.client.impl.OfflineScanner;
 import org.apache.accumulo.core.client.impl.ScannerImpl;
@@ -181,8 +180,8 @@ public abstract class AbstractInputFormat<K,V> implements InputFormat<K,V> {
     if (token instanceof KerberosToken) {
       log.info("Received KerberosToken, attempting to fetch DelegationToken");
       try {
-        Instance instance = getInstance(job);
-        Connector conn = instance.getConnector(principal, token);
+        Connector conn = Connector.builder().usingClientInfo(getClientInfo(job))
+            .usingToken(principal, token).build();
         token = conn.securityOperations().getDelegationToken(new DelegationTokenConfig());
       } catch (Exception e) {
         log.warn("Failed to automatically obtain DelegationToken, Mappers/Reducers will likely"
@@ -479,10 +478,13 @@ public abstract class AbstractInputFormat<K,V> implements InputFormat<K,V> {
       baseSplit = (org.apache.accumulo.core.client.mapreduce.RangeInputSplit) inSplit;
       log.debug("Initializing input split: " + baseSplit);
 
-      Instance instance = getInstance(job);
-
-      String principal = getPrincipal(job);
-      AuthenticationToken token = getAuthenticationToken(job);
+      ClientContext context = new ClientContext(getClientInfo(job));
+      Connector conn;
+      try {
+        conn = context.getConnector();
+      } catch (AccumuloException | AccumuloSecurityException e) {
+        throw new IllegalStateException(e);
+      }
       Authorizations authorizations = getScanAuthorizations(job);
       String classLoaderContext = getClassLoaderContext(job);
       String table = baseSplit.getTableName();
@@ -491,7 +493,7 @@ public abstract class AbstractInputFormat<K,V> implements InputFormat<K,V> {
       // configuration, but the scanner will use the table id resolved at job setup time
       InputTableConfig tableConfig = getInputTableConfig(job, baseSplit.getTableName());
 
-      log.debug("Creating connector with user: " + principal);
+      log.debug("Created connector with user: " + conn.whoami());
       log.debug("Creating scanner for table: " + table);
       log.debug("Authorizations are: " + authorizations);
 
@@ -503,8 +505,7 @@ public abstract class AbstractInputFormat<K,V> implements InputFormat<K,V> {
           // Note: BatchScanner will use at most one thread per tablet, currently BatchInputSplit
           // will not span tablets
           int scanThreads = 1;
-          scanner = instance.getConnector(principal, token)
-              .createBatchScanner(baseSplit.getTableName(), authorizations, scanThreads);
+          scanner = conn.createBatchScanner(baseSplit.getTableName(), authorizations, scanThreads);
           setupIterators(job, scanner, baseSplit.getTableName(), baseSplit);
           if (null != classLoaderContext) {
             scanner.setClassLoaderContext(classLoaderContext);
@@ -537,10 +538,9 @@ public abstract class AbstractInputFormat<K,V> implements InputFormat<K,V> {
 
         try {
           if (isOffline) {
-            scanner = new OfflineScanner(instance, new Credentials(principal, token),
-                Table.ID.of(baseSplit.getTableId()), authorizations);
+            scanner = new OfflineScanner(context, Table.ID.of(baseSplit.getTableId()),
+                authorizations);
           } else {
-            ClientContext context = new ClientContext(getClientInfo(job));
             scanner = new ScannerImpl(context, Table.ID.of(baseSplit.getTableId()), authorizations);
           }
           if (isIsolated) {
@@ -617,11 +617,8 @@ public abstract class AbstractInputFormat<K,V> implements InputFormat<K,V> {
   Map<String,Map<KeyExtent,List<Range>>> binOfflineTable(JobConf job, Table.ID tableId,
       List<Range> ranges)
       throws TableNotFoundException, AccumuloException, AccumuloSecurityException {
-
-    Instance instance = getInstance(job);
-    Connector conn = instance.getConnector(getPrincipal(job), getAuthenticationToken(job));
-
-    return InputConfigurator.binOffline(tableId, ranges, instance, conn);
+    ClientContext context = new ClientContext(getClientInfo(job));
+    return InputConfigurator.binOffline(tableId, ranges, context);
   }
 
   /**
diff --git a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AccumuloOutputFormat.java b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AccumuloOutputFormat.java
index 30710ec..67221b1 100644
--- a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AccumuloOutputFormat.java
+++ b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapred/AccumuloOutputFormat.java
@@ -43,7 +43,6 @@ import org.apache.accumulo.core.client.mapreduce.lib.impl.OutputConfigurator;
 import org.apache.accumulo.core.client.security.SecurityErrorCode;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 import org.apache.accumulo.core.client.security.tokens.DelegationToken;
-import org.apache.accumulo.core.client.security.tokens.KerberosToken;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
 import org.apache.accumulo.core.data.ColumnUpdate;
 import org.apache.accumulo.core.data.Mutation;
@@ -93,6 +92,17 @@ public class AccumuloOutputFormat implements OutputFormat<Text,Mutation> {
   }
 
   /**
+   * Get the connection information needed to communication with Accumulo
+   *
+   * @param job
+   *          Hadoop job to be configured
+   * @since 2.0.0
+   */
+  protected static ClientInfo getClientInfo(JobConf job) {
+    return OutputConfigurator.getClientInfo(CLASS, job);
+  }
+
+  /**
    * Set Accumulo client properties file used to connect to Accumulo
    *
    * @param job
@@ -130,17 +140,6 @@ public class AccumuloOutputFormat implements OutputFormat<Text,Mutation> {
   @Deprecated
   public static void setConnectorInfo(JobConf job, String principal, AuthenticationToken token)
       throws AccumuloSecurityException {
-    if (token instanceof KerberosToken) {
-      log.info("Received KerberosToken, attempting to fetch DelegationToken");
-      try {
-        Instance instance = getInstance(job);
-        Connector conn = instance.getConnector(principal, token);
-        token = conn.securityOperations().getDelegationToken(new DelegationTokenConfig());
-      } catch (Exception e) {
-        log.warn("Failed to automatically obtain DelegationToken, "
-            + "Mappers/Reducers will likely fail to communicate with Accumulo", e);
-      }
-    }
     // DelegationTokens can be passed securely from user to task without serializing insecurely in
     // the configuration
     if (token instanceof DelegationTokenImpl) {
@@ -426,7 +425,7 @@ public class AccumuloOutputFormat implements OutputFormat<Text,Mutation> {
       this.defaultTableName = (tname == null) ? null : new Text(tname);
 
       if (!simulate) {
-        this.conn = getInstance(job).getConnector(getPrincipal(job), getAuthenticationToken(job));
+        this.conn = Connector.builder().usingClientInfo(getClientInfo(job)).build();
         mtbw = conn.createMultiTableBatchWriter(getBatchWriterOptions(job));
       }
     }
@@ -563,9 +562,9 @@ public class AccumuloOutputFormat implements OutputFormat<Text,Mutation> {
       throw new IOException("Connector info has not been set.");
     try {
       // if the instance isn't configured, it will complain here
+      Connector c = Connector.builder().usingClientInfo(getClientInfo(job)).build();
       String principal = getPrincipal(job);
       AuthenticationToken token = getAuthenticationToken(job);
-      Connector c = getInstance(job).getConnector(principal, token);
       if (!c.securityOperations().authenticateUser(principal, token))
         throw new IOException("Unable to authenticate user");
     } catch (AccumuloException | AccumuloSecurityException e) {
diff --git a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AbstractInputFormat.java b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AbstractInputFormat.java
index 42e8637..91a6e49 100644
--- a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AbstractInputFormat.java
+++ b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AbstractInputFormat.java
@@ -48,7 +48,6 @@ import org.apache.accumulo.core.client.admin.DelegationTokenConfig;
 import org.apache.accumulo.core.client.admin.SecurityOperations;
 import org.apache.accumulo.core.client.impl.AuthenticationTokenIdentifier;
 import org.apache.accumulo.core.client.impl.ClientContext;
-import org.apache.accumulo.core.client.impl.Credentials;
 import org.apache.accumulo.core.client.impl.DelegationTokenImpl;
 import org.apache.accumulo.core.client.impl.OfflineScanner;
 import org.apache.accumulo.core.client.impl.ScannerImpl;
@@ -183,8 +182,8 @@ public abstract class AbstractInputFormat<K,V> extends InputFormat<K,V> {
     if (token instanceof KerberosToken) {
       log.info("Received KerberosToken, attempting to fetch DelegationToken");
       try {
-        Instance instance = getInstance(job);
-        Connector conn = instance.getConnector(principal, token);
+        Connector conn = Connector.builder().usingClientInfo(getClientInfo(job))
+            .usingToken(principal, token).build();
         token = conn.securityOperations().getDelegationToken(new DelegationTokenConfig());
       } catch (Exception e) {
         log.warn("Failed to automatically obtain DelegationToken, "
@@ -485,9 +484,14 @@ public abstract class AbstractInputFormat<K,V> extends InputFormat<K,V> {
       split = (RangeInputSplit) inSplit;
       log.debug("Initializing input split: " + split);
 
-      Instance instance = getInstance(attempt);
-      String principal = getPrincipal(attempt);
-      AuthenticationToken token = getAuthenticationToken(attempt);
+      ClientInfo info = getClientInfo(attempt);
+      ClientContext context = new ClientContext(info);
+      Connector conn;
+      try {
+        conn = context.getConnector();
+      } catch (AccumuloException | AccumuloSecurityException e) {
+        throw new IllegalStateException(e);
+      }
       Authorizations authorizations = getScanAuthorizations(attempt);
       String classLoaderContext = getClassLoaderContext(attempt);
       String table = split.getTableName();
@@ -497,7 +501,7 @@ public abstract class AbstractInputFormat<K,V> extends InputFormat<K,V> {
       // but the scanner will use the table id resolved at job setup time
       InputTableConfig tableConfig = getInputTableConfig(attempt, split.getTableName());
 
-      log.debug("Creating connector with user: " + principal);
+      log.debug("Creating connector with user: " + info.getPrincipal());
       log.debug("Creating scanner for table: " + table);
       log.debug("Authorizations are: " + authorizations);
 
@@ -509,8 +513,7 @@ public abstract class AbstractInputFormat<K,V> extends InputFormat<K,V> {
           // Note: BatchScanner will use at most one thread per tablet, currently BatchInputSplit
           // will not span tablets
           int scanThreads = 1;
-          scanner = instance.getConnector(principal, token).createBatchScanner(split.getTableName(),
-              authorizations, scanThreads);
+          scanner = conn.createBatchScanner(split.getTableName(), authorizations, scanThreads);
           setupIterators(attempt, scanner, split.getTableName(), split);
           if (null != classLoaderContext) {
             scanner.setClassLoaderContext(classLoaderContext);
@@ -542,10 +545,8 @@ public abstract class AbstractInputFormat<K,V> extends InputFormat<K,V> {
 
         try {
           if (isOffline) {
-            scanner = new OfflineScanner(instance, new Credentials(principal, token),
-                Table.ID.of(split.getTableId()), authorizations);
+            scanner = new OfflineScanner(context, Table.ID.of(split.getTableId()), authorizations);
           } else {
-            ClientContext context = new ClientContext(getClientInfo(attempt));
             // Not using public API to create scanner so that we can use table ID
             // Table ID is used in case of renames during M/R job
             scanner = new ScannerImpl(context, Table.ID.of(split.getTableId()), authorizations);
@@ -642,11 +643,8 @@ public abstract class AbstractInputFormat<K,V> extends InputFormat<K,V> {
   Map<String,Map<KeyExtent,List<Range>>> binOfflineTable(JobContext context, Table.ID tableId,
       List<Range> ranges)
       throws TableNotFoundException, AccumuloException, AccumuloSecurityException {
-
-    Instance instance = getInstance(context);
-    Connector conn = instance.getConnector(getPrincipal(context), getAuthenticationToken(context));
-
-    return InputConfigurator.binOffline(tableId, ranges, instance, conn);
+    ClientContext clientContext = new ClientContext(getClientInfo(context));
+    return InputConfigurator.binOffline(tableId, ranges, clientContext);
   }
 
   /**
diff --git a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AccumuloOutputFormat.java b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AccumuloOutputFormat.java
index eaa67c8..b878b03 100644
--- a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AccumuloOutputFormat.java
+++ b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/AccumuloOutputFormat.java
@@ -43,7 +43,6 @@ import org.apache.accumulo.core.client.mapreduce.lib.impl.OutputConfigurator;
 import org.apache.accumulo.core.client.security.SecurityErrorCode;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 import org.apache.accumulo.core.client.security.tokens.DelegationToken;
-import org.apache.accumulo.core.client.security.tokens.KerberosToken;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
 import org.apache.accumulo.core.data.ColumnUpdate;
 import org.apache.accumulo.core.data.Mutation;
@@ -93,6 +92,19 @@ public class AccumuloOutputFormat extends OutputFormat<Text,Mutation> {
   }
 
   /**
+   * Get connection information from this job
+   *
+   * @param context
+   *          Hadoop job context
+   * @return {@link ClientInfo}
+   *
+   * @since 2.0.0
+   */
+  protected static ClientInfo getClientInfo(JobContext context) {
+    return OutputConfigurator.getClientInfo(CLASS, context.getConfiguration());
+  }
+
+  /**
    * Set Accumulo client properties file used to connect to Accumulo
    *
    * @param job
@@ -130,17 +142,6 @@ public class AccumuloOutputFormat extends OutputFormat<Text,Mutation> {
   @Deprecated
   public static void setConnectorInfo(Job job, String principal, AuthenticationToken token)
       throws AccumuloSecurityException {
-    if (token instanceof KerberosToken) {
-      log.info("Received KerberosToken, attempting to fetch DelegationToken");
-      try {
-        Instance instance = getInstance(job);
-        Connector conn = instance.getConnector(principal, token);
-        token = conn.securityOperations().getDelegationToken(new DelegationTokenConfig());
-      } catch (Exception e) {
-        log.warn("Failed to automatically obtain DelegationToken, "
-            + "Mappers/Reducers will likely fail to communicate with Accumulo", e);
-      }
-    }
     // DelegationTokens can be passed securely from user to task without serializing insecurely in
     // the configuration
     if (token instanceof DelegationTokenImpl) {
@@ -427,8 +428,7 @@ public class AccumuloOutputFormat extends OutputFormat<Text,Mutation> {
       this.defaultTableName = (tname == null) ? null : new Text(tname);
 
       if (!simulate) {
-        this.conn = getInstance(context).getConnector(getPrincipal(context),
-            getAuthenticationToken(context));
+        this.conn = Connector.builder().usingClientInfo(getClientInfo(context)).build();
         mtbw = conn.createMultiTableBatchWriter(getBatchWriterOptions(context));
       }
     }
@@ -567,7 +567,7 @@ public class AccumuloOutputFormat extends OutputFormat<Text,Mutation> {
       // if the instance isn't configured, it will complain here
       String principal = getPrincipal(job);
       AuthenticationToken token = getAuthenticationToken(job);
-      Connector c = getInstance(job).getConnector(principal, token);
+      Connector c = Connector.builder().usingClientInfo(getClientInfo(job)).build();
       if (!c.securityOperations().authenticateUser(principal, token))
         throw new IOException("Unable to authenticate user");
     } catch (AccumuloException | AccumuloSecurityException e) {
diff --git a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/InputConfigurator.java b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/InputConfigurator.java
index 1d7967a..0253138 100644
--- a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/InputConfigurator.java
+++ b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/InputConfigurator.java
@@ -834,13 +834,13 @@ public class InputConfigurator extends ConfiguratorBase {
   }
 
   public static Map<String,Map<KeyExtent,List<Range>>> binOffline(Table.ID tableId,
-      List<Range> ranges, Instance instance, Connector conn)
-      throws AccumuloException, TableNotFoundException {
+      List<Range> ranges, ClientContext context)
+      throws AccumuloException, TableNotFoundException, AccumuloSecurityException {
     Map<String,Map<KeyExtent,List<Range>>> binnedRanges = new HashMap<>();
 
-    if (Tables.getTableState(instance, tableId) != TableState.OFFLINE) {
-      Tables.clearCache(instance);
-      if (Tables.getTableState(instance, tableId) != TableState.OFFLINE) {
+    if (Tables.getTableState(context, tableId) != TableState.OFFLINE) {
+      Tables.clearCache(context);
+      if (Tables.getTableState(context, tableId) != TableState.OFFLINE) {
         throw new AccumuloException(
             "Table is online tableId:" + tableId + " cannot scan table in offline mode ");
       }
@@ -856,7 +856,8 @@ public class InputConfigurator extends ConfiguratorBase {
 
       Range metadataRange = new Range(new KeyExtent(tableId, startRow, null).getMetadataEntry(),
           true, null, false);
-      Scanner scanner = conn.createScanner(MetadataTable.NAME, Authorizations.EMPTY);
+      Scanner scanner = context.getConnector().createScanner(MetadataTable.NAME,
+          Authorizations.EMPTY);
       MetadataSchema.TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.fetch(scanner);
       scanner.fetchColumnFamily(MetadataSchema.TabletsSection.LastLocationColumnFamily.NAME);
       scanner.fetchColumnFamily(MetadataSchema.TabletsSection.CurrentLocationColumnFamily.NAME);
diff --git a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/MapReduceClientOpts.java b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/MapReduceClientOpts.java
index b0de76e..84e7023 100644
--- a/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/MapReduceClientOpts.java
+++ b/client/mapreduce/src/main/java/org/apache/accumulo/core/client/mapreduce/lib/impl/MapReduceClientOpts.java
@@ -60,7 +60,8 @@ public class MapReduceClientOpts extends ClientOpts {
         log.info("Obtaining delegation token for {}", newPrincipal);
 
         setPrincipal(newPrincipal);
-        Connector conn = getInstance().getConnector(newPrincipal, krbToken);
+        Connector conn = Connector.builder().usingClientInfo(getClientInfo())
+            .usingToken(newPrincipal, krbToken).build();
 
         // Do the explicit check to see if the user has the permission to get a delegation token
         if (!conn.securityOperations().hasSystemPermission(conn.whoami(),
diff --git a/core/src/main/java/org/apache/accumulo/core/client/ClientInfo.java b/core/src/main/java/org/apache/accumulo/core/client/ClientInfo.java
index 933a101..d8612ae 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/ClientInfo.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/ClientInfo.java
@@ -18,6 +18,7 @@ package org.apache.accumulo.core.client;
 
 import java.util.Properties;
 
+import org.apache.accumulo.core.client.impl.ClientInfoImpl;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 
 /**
@@ -61,4 +62,18 @@ public interface ClientInfo {
    * @return All Accumulo client properties set for this connection
    */
   Properties getProperties();
+
+  /**
+   * @return ClientInfo given properties
+   */
+  static ClientInfo from(Properties properties) {
+    return new ClientInfoImpl(properties);
+  }
+
+  /**
+   * @return ClientInfo given properties and token
+   */
+  static ClientInfo from(Properties properties, AuthenticationToken token) {
+    return new ClientInfoImpl(properties, token);
+  }
 }
diff --git a/core/src/main/java/org/apache/accumulo/core/client/Connector.java b/core/src/main/java/org/apache/accumulo/core/client/Connector.java
index 673da77..2a7ee36 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/Connector.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/Connector.java
@@ -327,6 +327,19 @@ public abstract class Connector {
   public abstract ClientInfo info();
 
   /**
+   * Change user
+   *
+   * @param principal
+   *          Principal/username
+   * @param token
+   *          Authentication token
+   * @return {@link Connector} for new user
+   * @since 2.0.0
+   */
+  public abstract Connector changeUser(String principal, AuthenticationToken token)
+      throws AccumuloSecurityException, AccumuloException;
+
+  /**
    * Builds ClientInfo after all options have been specified
    *
    * @since 2.0.0
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
index 0401e07..928d2b0 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ConditionalWriterImpl.java
@@ -302,7 +302,7 @@ class ConditionalWriterImpl implements ConditionalWriter {
       if (failures.size() == mutations.size())
         if (!Tables.exists(context, tableId))
           throw new TableDeletedException(tableId.canonicalID());
-        else if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE)
+        else if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
           throw new TableOfflineException(Tables.getTableOfflineMsg(context, tableId));
 
     } catch (Exception e) {
@@ -628,7 +628,7 @@ class ConditionalWriterImpl implements ConditionalWriter {
     } catch (ThriftSecurityException tse) {
       AccumuloSecurityException ase = new AccumuloSecurityException(
           context.getCredentials().getPrincipal(), tse.getCode(),
-          Tables.getPrintableTableInfoFromId(context.getInstance(), tableId), tse);
+          Tables.getPrintableTableInfoFromId(context, tableId), tse);
       queueException(location, cmidToCm, ase);
     } catch (TTransportException e) {
       locator.invalidateCache(context.getInstance(), location.toString());
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
index bf1cac5..244f764 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ConnectorImpl.java
@@ -89,7 +89,7 @@ public class ConnectorImpl extends Connector {
 
   private Table.ID getTableId(String tableName) throws TableNotFoundException {
     Table.ID tableId = Tables.getTableId(context, tableName);
-    if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE)
+    if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
       throw new TableOfflineException(Tables.getTableOfflineMsg(context, tableId));
     return tableId;
   }
@@ -244,6 +244,12 @@ public class ConnectorImpl extends Connector {
     return this.context.getClientInfo();
   }
 
+  @Override
+  public Connector changeUser(String principal, AuthenticationToken token)
+      throws AccumuloSecurityException, AccumuloException {
+    return Connector.builder().usingClientInfo(info()).usingToken(principal, token).build();
+  }
+
   public static class ConnectorBuilderImpl
       implements InstanceArgs, PropertyOptions, ClientInfoOptions, AuthenticationArgs,
       ConnectionOptions, SslOptions, SaslOptions, ConnectorFactory, FromOptions {
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java
index efd12a4..15de019 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineIterator.java
@@ -30,7 +30,6 @@ import java.util.concurrent.TimeUnit;
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.RowIterator;
 import org.apache.accumulo.core.client.SampleNotPresentException;
 import org.apache.accumulo.core.client.Scanner;
@@ -150,15 +149,15 @@ class OfflineIterator implements Iterator<Entry<Key,Value>> {
   private Connector conn;
   private Table.ID tableId;
   private Authorizations authorizations;
-  private Instance instance;
+  private ClientContext context;
   private ScannerOptions options;
   private ArrayList<SortedKeyValueIterator<Key,Value>> readers;
   private AccumuloConfiguration config;
 
-  public OfflineIterator(ScannerOptions options, Instance instance, Credentials credentials,
+  public OfflineIterator(ScannerOptions options, ClientContext context,
       Authorizations authorizations, Text table, Range range) {
     this.options = new ScannerOptions(options);
-    this.instance = instance;
+    this.context = context;
     this.range = range;
 
     if (this.options.fetchedColumns.size() > 0) {
@@ -171,7 +170,7 @@ class OfflineIterator implements Iterator<Entry<Key,Value>> {
     this.readers = new ArrayList<>();
 
     try {
-      conn = instance.getConnector(credentials.getPrincipal(), credentials.getToken());
+      conn = context.getConnector();
       config = new ConfigurationCopy(conn.instanceOperations().getSiteConfiguration());
       nextTablet();
 
@@ -242,9 +241,9 @@ class OfflineIterator implements Iterator<Entry<Key,Value>> {
     Pair<KeyExtent,String> eloc = getTabletFiles(nextRange, relFiles);
 
     while (eloc.getSecond() != null) {
-      if (Tables.getTableState(instance, tableId) != TableState.OFFLINE) {
-        Tables.clearCache(instance);
-        if (Tables.getTableState(instance, tableId) != TableState.OFFLINE) {
+      if (Tables.getTableState(context, tableId) != TableState.OFFLINE) {
+        Tables.clearCache(context);
+        if (Tables.getTableState(context, tableId) != TableState.OFFLINE) {
           throw new AccumuloException("Table is online " + tableId
               + " cannot scan tablet in offline mode " + eloc.getFirst());
         }
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java
index f38e886..d3229d2 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/OfflineScanner.java
@@ -22,7 +22,6 @@ import java.util.Iterator;
 import java.util.Map.Entry;
 
 import org.apache.accumulo.core.Constants;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Range;
@@ -36,24 +35,18 @@ public class OfflineScanner extends ScannerOptions implements Scanner {
   private int timeOut;
   private Range range;
 
-  private Instance instance;
-  private Credentials credentials;
+  private ClientContext context;
   private Authorizations authorizations;
   private Text tableId;
 
-  public OfflineScanner(Instance instance, Credentials credentials, Table.ID tableId,
-      Authorizations authorizations) {
-    checkArgument(instance != null, "instance is null");
-    checkArgument(credentials != null, "credentials is null");
+  public OfflineScanner(ClientContext context, Table.ID tableId, Authorizations authorizations) {
+    checkArgument(context != null, "context is null");
     checkArgument(tableId != null, "tableId is null");
     checkArgument(authorizations != null, "authorizations is null");
-    this.instance = instance;
-    this.credentials = credentials;
+    this.context = context;
     this.tableId = new Text(tableId.getUtf8());
     this.range = new Range((Key) null, (Key) null);
-
     this.authorizations = authorizations;
-
     this.batchSize = Constants.SCAN_BATCH_SIZE;
     this.timeOut = Integer.MAX_VALUE;
   }
@@ -102,7 +95,7 @@ public class OfflineScanner extends ScannerOptions implements Scanner {
 
   @Override
   public Iterator<Entry<Key,Value>> iterator() {
-    return new OfflineIterator(this, instance, credentials, authorizations, tableId, range);
+    return new OfflineIterator(this, context, authorizations, tableId, range);
   }
 
   @Override
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java b/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
index 928dc8c..6ed44a8 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TableOperationsImpl.java
@@ -386,7 +386,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
     } catch (Exception e) {
       throw new AccumuloException(e.getMessage(), e);
     } finally {
-      Tables.clearCache(context.getInstance());
+      Tables.clearCache(context);
       // always finish table op, even when exception
       if (opid != null)
         try {
@@ -532,7 +532,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
         if (tl == null) {
           if (!Tables.exists(context, tableId))
             throw new TableNotFoundException(tableId.canonicalID(), tableName, null);
-          else if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE)
+          else if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
             throw new TableOfflineException(Tables.getTableOfflineMsg(context, tableId));
           continue;
         }
@@ -573,7 +573,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
           tabLocator.invalidateCache(context.getInstance(), tl.tablet_location);
           continue;
         } catch (ThriftSecurityException e) {
-          Tables.clearCache(context.getInstance());
+          Tables.clearCache(context);
           if (!Tables.exists(context, tableId))
             throw new TableNotFoundException(tableId.canonicalID(), tableName, null);
           throw new AccumuloSecurityException(e.user, e.code, e);
@@ -1089,7 +1089,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
     while (!tl.binRanges(context, Collections.singletonList(range), binnedRanges).isEmpty()) {
       if (!Tables.exists(context, tableId))
         throw new TableDeletedException(tableId.canonicalID());
-      if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE)
+      if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
         throw new TableOfflineException(Tables.getTableOfflineMsg(context, tableId));
 
       log.warn("Unable to locate bins for specified range. Retrying.");
@@ -1203,16 +1203,16 @@ public class TableOperationsImpl extends TableOperationsHelper {
 
     while (true) {
 
-      if (Tables.getTableState(context.getInstance(), tableId) != expectedState) {
-        Tables.clearCache(context.getInstance());
-        TableState currentState = Tables.getTableState(context.getInstance(), tableId);
+      if (Tables.getTableState(context, tableId) != expectedState) {
+        Tables.clearCache(context);
+        TableState currentState = Tables.getTableState(context, tableId);
         if (currentState != expectedState) {
           if (!Tables.exists(context, tableId))
             throw new TableDeletedException(tableId.canonicalID());
           if (currentState == TableState.DELETING)
             throw new TableNotFoundException(tableId.canonicalID(), "", "Table is being deleted.");
           throw new AccumuloException("Unexpected table state " + tableId + " "
-              + Tables.getTableState(context.getInstance(), tableId) + " != " + expectedState);
+              + Tables.getTableState(context, tableId) + " != " + expectedState);
         }
       }
 
@@ -1372,7 +1372,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
      * ACCUMULO-4574 if table is already online return without executing fate operation.
      */
 
-    TableState expectedState = Tables.getTableState(context.getInstance(), tableId, true);
+    TableState expectedState = Tables.getTableState(context, tableId, true);
     if (expectedState == TableState.ONLINE) {
       if (wait)
         waitForTableStateTransition(tableId, TableState.ONLINE);
@@ -1763,7 +1763,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
 
       if (!Tables.exists(context, tableId))
         throw new TableNotFoundException(tableId.canonicalID(), tableName, null);
-      if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE)
+      if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
         throw new TableOfflineException(Tables.getTableOfflineMsg(context, tableId));
 
       binnedRanges.clear();
@@ -1811,7 +1811,7 @@ public class TableOperationsImpl extends TableOperationsHelper {
       public List<Summary> retrieve()
           throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
         Table.ID tableId = Tables.getTableId(context, tableName);
-        if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE)
+        if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
           throw new TableOfflineException(Tables.getTableOfflineMsg(context, tableId));
 
         TRowRange range = new TRowRange(TextUtil.getByteBuffer(startRow),
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
index b1a58f3..63e9316 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/Tables.java
@@ -179,6 +179,10 @@ public class Tables {
     return tableIds.contains(tableId.canonicalID());
   }
 
+  public static void clearCache(ClientContext context) {
+    clearCache(context.getInstance());
+  }
+
   public static void clearCache(Instance instance) {
     getZooCache(instance).clear(ZooUtil.getRoot(instance) + Constants.ZTABLES);
     getZooCache(instance).clear(ZooUtil.getRoot(instance) + Constants.ZNAMESPACES);
@@ -199,6 +203,10 @@ public class Tables {
     instanceToMapCache.invalidate(instance.getInstanceID());
   }
 
+  public static String getPrintableTableInfoFromId(ClientContext context, Table.ID tableId) {
+    return getPrintableTableInfoFromId(context.getInstance(), tableId);
+  }
+
   public static String getPrintableTableInfoFromId(Instance instance, Table.ID tableId) {
     String tableName = null;
     try {
@@ -229,6 +237,11 @@ public class Tables {
     return getTableState(instance, tableId, false);
   }
 
+  public static TableState getTableState(ClientContext context, Table.ID tableId,
+      boolean clearCachedState) {
+    return getTableState(context.getInstance(), tableId, clearCachedState);
+  }
+
   /**
    * Get the current state of the table using the tableid. The boolean clearCache, if true will
    * clear the table state in zookeeper before fetching the state. Added with ACCUMULO-4574.
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchReaderIterator.java b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchReaderIterator.java
index fcb07be..c5c2a74 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchReaderIterator.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchReaderIterator.java
@@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.SampleNotPresentException;
 import org.apache.accumulo.core.client.TableDeletedException;
 import org.apache.accumulo.core.client.TableNotFoundException;
@@ -79,7 +78,6 @@ public class TabletServerBatchReaderIterator implements Iterator<Entry<Key,Value
   private static final Logger log = LoggerFactory.getLogger(TabletServerBatchReaderIterator.class);
 
   private final ClientContext context;
-  private final Instance instance;
   private final Table.ID tableId;
   private Authorizations authorizations = Authorizations.EMPTY;
   private final int numThreads;
@@ -111,7 +109,6 @@ public class TabletServerBatchReaderIterator implements Iterator<Entry<Key,Value
       ExecutorService queryThreadPool, ScannerOptions scannerOptions, long timeout) {
 
     this.context = context;
-    this.instance = context.getInstance();
     this.tableId = tableId;
     this.authorizations = authorizations;
     this.numThreads = numThreads;
@@ -251,7 +248,7 @@ public class TabletServerBatchReaderIterator implements Iterator<Entry<Key,Value
         if (failures.size() >= lastFailureSize)
           if (!Tables.exists(context, tableId))
             throw new TableDeletedException(tableId.canonicalID());
-          else if (Tables.getTableState(instance, tableId) == TableState.OFFLINE)
+          else if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
             throw new TableOfflineException(Tables.getTableOfflineMsg(context, tableId));
 
         lastFailureSize = failures.size();
@@ -323,7 +320,7 @@ public class TabletServerBatchReaderIterator implements Iterator<Entry<Key,Value
   }
 
   private String getTableInfo() {
-    return Tables.getPrintableTableInfoFromId(instance, tableId);
+    return Tables.getPrintableTableInfoFromId(context, tableId);
   }
 
   private class QueryTask implements Runnable {
@@ -386,7 +383,7 @@ public class TabletServerBatchReaderIterator implements Iterator<Entry<Key,Value
         e.setTableInfo(getTableInfo());
         log.debug("AccumuloSecurityException thrown", e);
 
-        Tables.clearCache(instance);
+        Tables.clearCache(context);
         if (!Tables.exists(context, tableId))
           fatalException = new TableDeletedException(tableId.canonicalID());
         else
@@ -768,7 +765,7 @@ public class TabletServerBatchReaderIterator implements Iterator<Entry<Key,Value
       String tableInfo = "?";
       if (e.getExtent() != null) {
         Table.ID tableId = new KeyExtent(e.getExtent()).getTableId();
-        tableInfo = Tables.getPrintableTableInfoFromId(context.getInstance(), tableId);
+        tableInfo = Tables.getPrintableTableInfoFromId(context, tableId);
       }
       String message = "Table " + tableInfo + " does not have sampling configured or built";
       throw new SampleNotPresentException(message, e);
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchWriter.java b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchWriter.java
index 61dc81b..989f343 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchWriter.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/TabletServerBatchWriter.java
@@ -510,7 +510,7 @@ public class TabletServerBatchWriter {
       for (KeyExtent ke : authorizationFailures.keySet())
         tableIds.add(ke.getTableId());
 
-      Tables.clearCache(context.getInstance());
+      Tables.clearCache(context);
       for (Table.ID tableId : tableIds)
         if (!Tables.exists(context, tableId))
           throw new TableDeletedException(tableId.canonicalID());
@@ -698,7 +698,7 @@ public class TabletServerBatchWriter {
               if (tableFailures.size() == tableMutations.size())
                 if (!Tables.exists(context, entry.getKey()))
                   throw new TableDeletedException(entry.getKey().canonicalID());
-                else if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFLINE)
+                else if (Tables.getTableState(context, tableId) == TableState.OFFLINE)
                   throw new TableOfflineException(
                       Tables.getTableOfflineMsg(context, entry.getKey()));
             }
diff --git a/core/src/main/java/org/apache/accumulo/core/client/impl/ThriftScanner.java b/core/src/main/java/org/apache/accumulo/core/client/impl/ThriftScanner.java
index 3d7d48f..ac21431 100644
--- a/core/src/main/java/org/apache/accumulo/core/client/impl/ThriftScanner.java
+++ b/core/src/main/java/org/apache/accumulo/core/client/impl/ThriftScanner.java
@@ -31,7 +31,6 @@ import java.util.concurrent.TimeUnit;
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.SampleNotPresentException;
 import org.apache.accumulo.core.client.TableDeletedException;
 import org.apache.accumulo.core.client.TableNotFoundException;
@@ -225,7 +224,6 @@ public class ThriftScanner {
       throws ScanTimedOutException, AccumuloException, AccumuloSecurityException,
       TableNotFoundException {
     TabletLocation loc = null;
-    Instance instance = context.getInstance();
     long startTime = System.currentTimeMillis();
     String lastError = null;
     String error = null;
@@ -257,9 +255,9 @@ public class ThriftScanner {
                 scanState.startRow, scanState.skipStartRow, false);
 
             if (loc == null) {
-              if (!Tables.exists(instance, scanState.tableId))
+              if (!Tables.exists(context, scanState.tableId))
                 throw new TableDeletedException(scanState.tableId.canonicalID());
-              else if (Tables.getTableState(instance, scanState.tableId) == TableState.OFFLINE)
+              else if (Tables.getTableState(context, scanState.tableId) == TableState.OFFLINE)
                 throw new TableOfflineException(
                     Tables.getTableOfflineMsg(context, scanState.tableId));
 
@@ -311,16 +309,15 @@ public class ThriftScanner {
         try {
           results = scan(loc, scanState, context);
         } catch (AccumuloSecurityException e) {
-          Tables.clearCache(instance);
-          if (!Tables.exists(instance, scanState.tableId))
+          Tables.clearCache(context);
+          if (!Tables.exists(context, scanState.tableId))
             throw new TableDeletedException(scanState.tableId.canonicalID());
-          e.setTableInfo(Tables.getPrintableTableInfoFromId(instance, scanState.tableId));
+          e.setTableInfo(Tables.getPrintableTableInfoFromId(context, scanState.tableId));
           throw e;
         } catch (TApplicationException tae) {
           throw new AccumuloServerException(loc.tablet_location, tae);
         } catch (TSampleNotPresentException tsnpe) {
-          String message = "Table "
-              + Tables.getPrintableTableInfoFromId(instance, scanState.tableId)
+          String message = "Table " + Tables.getPrintableTableInfoFromId(context, scanState.tableId)
               + " does not have sampling configured or built";
           throw new SampleNotPresentException(message, tsnpe);
         } catch (NotServingTabletException e) {
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/ClientProperty.java b/core/src/main/java/org/apache/accumulo/core/conf/ClientProperty.java
index 785296d..1ec1609 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/ClientProperty.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/ClientProperty.java
@@ -152,6 +152,12 @@ public enum ClientProperty {
     return value;
   }
 
+  public boolean isEmpty(Properties properties) {
+    Objects.requireNonNull(properties);
+    String value = properties.getProperty(getKey());
+    return (value == null || value.isEmpty());
+  }
+
   public Long getLong(Properties properties) {
     String value = getValue(properties);
     if (value.isEmpty()) {
diff --git a/core/src/test/java/org/apache/accumulo/core/client/impl/TableOperationsImplTest.java b/core/src/test/java/org/apache/accumulo/core/client/impl/TableOperationsImplTest.java
index fddffa2..c5b7e84 100644
--- a/core/src/test/java/org/apache/accumulo/core/client/impl/TableOperationsImplTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/client/impl/TableOperationsImplTest.java
@@ -51,8 +51,8 @@ public class TableOperationsImplTest {
     PasswordToken token = new PasswordToken("password");
 
     // Credentials expectations
-    EasyMock.expect(credentials.getPrincipal()).andReturn(user).atLeastOnce();
-    EasyMock.expect(credentials.getToken()).andReturn(token).atLeastOnce();
+    EasyMock.expect(credentials.getPrincipal()).andReturn(user);
+    EasyMock.expect(credentials.getToken()).andReturn(token);
 
     // Create the connector and scanner
     EasyMock.expect(instance.getConnector(user, token)).andReturn(connector);
diff --git a/server/master/src/main/java/org/apache/accumulo/master/Master.java b/server/master/src/main/java/org/apache/accumulo/master/Master.java
index 1ac98f8..bb188ce 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/Master.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/Master.java
@@ -626,7 +626,7 @@ public class Master extends AccumuloServerContext
 
   public void mustBeOnline(final Table.ID tableId) throws ThriftTableOperationException {
     Tables.clearCache(getInstance());
-    if (!Tables.getTableState(getInstance(), tableId).equals(TableState.ONLINE))
+    if (!Tables.getTableState(this, tableId).equals(TableState.ONLINE))
       throw new ThriftTableOperationException(tableId.canonicalID(), null, TableOperation.MERGE,
           TableOperationExceptionType.OFFLINE, "table is not online");
   }
diff --git a/server/master/src/main/java/org/apache/accumulo/master/metrics/Metrics2ReplicationMetrics.java b/server/master/src/main/java/org/apache/accumulo/master/metrics/Metrics2ReplicationMetrics.java
index db8db26..b4eeacd 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/metrics/Metrics2ReplicationMetrics.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/metrics/Metrics2ReplicationMetrics.java
@@ -79,7 +79,7 @@ public class Metrics2ReplicationMetrics implements Metrics, MetricsSource {
 
   protected void snapshot() {
     // Only add these metrics if the replication table is online and there are peers
-    if (TableState.ONLINE == Tables.getTableState(master.getInstance(), ReplicationTable.ID)
+    if (TableState.ONLINE == Tables.getTableState(master, ReplicationTable.ID)
         && !replicationUtil.getPeers().isEmpty()) {
       registry.add(PENDING_FILES, getNumFilesPendingReplication());
       addReplicationQueueTimeMetrics();
diff --git a/server/master/src/main/java/org/apache/accumulo/master/metrics/ReplicationMetrics.java b/server/master/src/main/java/org/apache/accumulo/master/metrics/ReplicationMetrics.java
index 5c55347..ded98ee 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/metrics/ReplicationMetrics.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/metrics/ReplicationMetrics.java
@@ -58,7 +58,7 @@ public class ReplicationMetrics extends AbstractMetricsImpl implements Replicati
   @Override
   public int getNumFilesPendingReplication() {
 
-    if (TableState.ONLINE != Tables.getTableState(master.getInstance(), ReplicationTable.ID)) {
+    if (TableState.ONLINE != Tables.getTableState(master, ReplicationTable.ID)) {
       return 0;
     }
 
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CompactionDriver.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CompactionDriver.java
index 5f1624c..eb73136 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/CompactionDriver.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/CompactionDriver.java
@@ -22,7 +22,6 @@ import java.util.Map.Entry;
 
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.IsolatedScanner;
 import org.apache.accumulo.core.client.RowIterator;
 import org.apache.accumulo.core.client.Scanner;
@@ -145,13 +144,12 @@ class CompactionDriver extends MasterRepo {
 
     long scanTime = System.currentTimeMillis() - t1;
 
-    Instance instance = master.getInstance();
-    Tables.clearCache(instance);
+    Tables.clearCache(master);
     if (tabletCount == 0 && !Tables.exists(master, tableId))
       throw new AcceptableThriftTableOperationException(tableId.canonicalID(), null,
           TableOperation.COMPACT, TableOperationExceptionType.NOTFOUND, null);
 
-    if (serversToFlush.size() == 0 && Tables.getTableState(instance, tableId) == TableState.OFFLINE)
+    if (serversToFlush.size() == 0 && Tables.getTableState(master, tableId) == TableState.OFFLINE)
       throw new AcceptableThriftTableOperationException(tableId.canonicalID(), null,
           TableOperation.COMPACT, TableOperationExceptionType.OFFLINE, null);
 
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java
index 1599ed2..6e2a3bd 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/RenameTable.java
@@ -98,7 +98,7 @@ public class RenameTable extends MasterRepo {
           return newName.getBytes(UTF_8);
         }
       });
-      Tables.clearCache(instance);
+      Tables.clearCache(master);
     } finally {
       Utils.tableNameLock.unlock();
       Utils.unreserveTable(tableId, tid, true);
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/WriteExportFiles.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/WriteExportFiles.java
index 8fcf1de..a590b49 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/WriteExportFiles.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/WriteExportFiles.java
@@ -36,6 +36,7 @@ import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.impl.AcceptableThriftTableOperationException;
+import org.apache.accumulo.core.client.impl.ClientContext;
 import org.apache.accumulo.core.client.impl.Table;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.impl.thrift.TableOperation;
@@ -69,10 +70,10 @@ class WriteExportFiles extends MasterRepo {
     this.tableInfo = tableInfo;
   }
 
-  private void checkOffline(Connector conn) throws Exception {
-    if (Tables.getTableState(conn.getInstance(), tableInfo.tableID) != TableState.OFFLINE) {
-      Tables.clearCache(conn.getInstance());
-      if (Tables.getTableState(conn.getInstance(), tableInfo.tableID) != TableState.OFFLINE) {
+  private void checkOffline(ClientContext context) throws Exception {
+    if (Tables.getTableState(context, tableInfo.tableID) != TableState.OFFLINE) {
+      Tables.clearCache(context);
+      if (Tables.getTableState(context, tableInfo.tableID) != TableState.OFFLINE) {
         throw new AcceptableThriftTableOperationException(tableInfo.tableID.canonicalID(),
             tableInfo.tableName, TableOperation.EXPORT, TableOperationExceptionType.OTHER,
             "Table is not offline");
@@ -91,7 +92,7 @@ class WriteExportFiles extends MasterRepo {
 
     Connector conn = master.getConnector();
 
-    checkOffline(conn);
+    checkOffline(master);
 
     Scanner metaScanner = conn.createScanner(MetadataTable.NAME, Authorizations.EMPTY);
     metaScanner.setRange(new KeyExtent(tableInfo.tableID, null, null).toMetadataRange());
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/BulkImport.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/BulkImport.java
index a645c1d..56bb93b 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/BulkImport.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/BulkImport.java
@@ -90,8 +90,8 @@ public class BulkImport extends MasterRepo {
     if (!Utils.getReadLock(tableId, tid).tryLock())
       return 100;
 
-    Tables.clearCache(master.getInstance());
-    if (Tables.getTableState(master.getInstance(), tableId) == TableState.ONLINE) {
+    Tables.clearCache(master);
+    if (Tables.getTableState(master, tableId) == TableState.ONLINE) {
       long reserve1, reserve2;
       reserve1 = reserve2 = Utils.reserveHdfsDirectory(sourceDir, tid);
       if (reserve1 == 0)
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/CopyFailed.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/CopyFailed.java
index 356e3d6..2d0748e 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/CopyFailed.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer1/CopyFailed.java
@@ -140,8 +140,8 @@ class CopyFailed extends MasterRepo {
     }
 
     if (loadedFailures.size() > 0) {
-      DistributedWorkQueue bifCopyQueue = new DistributedWorkQueue(Constants.ZROOT + "/"
-          + master.getInstance().getInstanceID() + Constants.ZBULK_FAILED_COPYQ,
+      DistributedWorkQueue bifCopyQueue = new DistributedWorkQueue(
+          Constants.ZROOT + "/" + master.getInstanceID() + Constants.ZBULK_FAILED_COPYQ,
           master.getConfiguration());
 
       HashSet<String> workIds = new HashSet<>();
diff --git a/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer2/PrepBulkImport.java b/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer2/PrepBulkImport.java
index b97426c..ceade85 100644
--- a/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer2/PrepBulkImport.java
+++ b/server/master/src/main/java/org/apache/accumulo/master/tableOps/bulkVer2/PrepBulkImport.java
@@ -87,7 +87,7 @@ public class PrepBulkImport extends MasterRepo {
 
     if (master.onlineTabletServers().size() == 0)
       return 500;
-    Tables.clearCache(master.getInstance());
+    Tables.clearCache(master);
 
     return Utils.reserveHdfsDirectory(bulkInfo.sourceDir, tid);
   }
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/Monitor.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/Monitor.java
index aaecf4e..d163740 100644
--- a/server/monitor/src/main/java/org/apache/accumulo/monitor/Monitor.java
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/Monitor.java
@@ -173,8 +173,6 @@ public class Monitor implements HighlyAvailableService {
   private static Exception problemException;
   private static GCStatus gcStatus;
 
-  private static Instance instance;
-
   private static ServerConfigurationFactory config;
   private static AccumuloServerContext context;
 
@@ -421,14 +419,14 @@ public class Monitor implements HighlyAvailableService {
     try {
       // Read the gc location from its lock
       ZooReaderWriter zk = ZooReaderWriter.getInstance();
-      String path = ZooUtil.getRoot(instance) + Constants.ZGC_LOCK;
+      String path = ZooUtil.getRoot(context.getInstanceID()) + Constants.ZGC_LOCK;
       List<String> locks = zk.getChildren(path, null);
       if (locks != null && locks.size() > 0) {
         Collections.sort(locks);
         address = new ServerServices(new String(zk.getData(path + "/" + locks.get(0), null), UTF_8))
             .getAddress(Service.GC_CLIENT);
         GCMonitorService.Client client = ThriftUtil.getClient(new GCMonitorService.Client.Factory(),
-            address, new AccumuloServerContext(instance, config));
+            address, context);
         try {
           result = client.getStatus(Tracer.traceInfo(), getContext().rpcCreds());
         } finally {
@@ -449,7 +447,7 @@ public class Monitor implements HighlyAvailableService {
     SecurityUtil.serverLogin(SiteConfiguration.getInstance());
 
     VolumeManager fs = VolumeManagerImpl.get();
-    instance = HdfsZooInstance.getInstance();
+    Instance instance = HdfsZooInstance.getInstance();
     config = new ServerConfigurationFactory(instance);
     context = new AccumuloServerContext(instance, config);
     log.info("Version " + Constants.VERSION);
@@ -512,8 +510,8 @@ public class Monitor implements HighlyAvailableService {
     try {
       String monitorAddress = HostAndPort.fromParts(advertiseHost, server.getPort()).toString();
       ZooReaderWriter.getInstance().putPersistentData(
-          ZooUtil.getRoot(instance) + Constants.ZMONITOR_HTTP_ADDR, monitorAddress.getBytes(UTF_8),
-          NodeExistsPolicy.OVERWRITE);
+          ZooUtil.getRoot(context.getInstanceID()) + Constants.ZMONITOR_HTTP_ADDR,
+          monitorAddress.getBytes(UTF_8), NodeExistsPolicy.OVERWRITE);
       log.info("Set monitor address in zookeeper to {}", monitorAddress);
     } catch (Exception ex) {
       log.error("Unable to set monitor HTTP address in zookeeper", ex);
@@ -617,7 +615,7 @@ public class Monitor implements HighlyAvailableService {
   }
 
   public static void fetchScans() throws Exception {
-    if (instance == null)
+    if (context == null)
       return;
     Connector c = context.getConnector();
     for (String server : c.instanceOperations().getTabletServers()) {
@@ -649,7 +647,7 @@ public class Monitor implements HighlyAvailableService {
    * Get the monitor lock in ZooKeeper
    */
   private void getMonitorLock() throws KeeperException, InterruptedException {
-    final String zRoot = ZooUtil.getRoot(instance);
+    final String zRoot = ZooUtil.getRoot(context.getInstanceID());
     final String monitorPath = zRoot + Constants.ZMONITOR;
     final String monitorLockPath = zRoot + Constants.ZMONITOR_LOCK;
 
diff --git a/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceServer.java b/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceServer.java
index 3521f31..01bd312 100644
--- a/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceServer.java
+++ b/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceServer.java
@@ -53,6 +53,7 @@ import org.apache.accumulo.core.iterators.user.AgeOffFilter;
 import org.apache.accumulo.fate.zookeeper.IZooReaderWriter;
 import org.apache.accumulo.fate.zookeeper.ZooUtil.NodeExistsPolicy;
 import org.apache.accumulo.server.Accumulo;
+import org.apache.accumulo.server.AccumuloServerContext;
 import org.apache.accumulo.server.ServerOpts;
 import org.apache.accumulo.server.client.HdfsZooInstance;
 import org.apache.accumulo.server.conf.ServerConfigurationFactory;
@@ -88,7 +89,7 @@ public class TraceServer implements Watcher {
 
   final private static Logger log = LoggerFactory.getLogger(TraceServer.class);
   final private ServerConfigurationFactory serverConfiguration;
-  final private Instance instance;
+  final private AccumuloServerContext context;
   final private TServer server;
   final private AtomicReference<BatchWriter> writer;
   final private Connector connector;
@@ -191,12 +192,11 @@ public class TraceServer implements Watcher {
 
   }
 
-  public TraceServer(Instance instance, ServerConfigurationFactory serverConfiguration,
-      String hostname) throws Exception {
-    this.serverConfiguration = serverConfiguration;
-    this.instance = instance;
+  public TraceServer(AccumuloServerContext context, String hostname) throws Exception {
+    this.context = context;
+    this.serverConfiguration = context.getServerConfigurationFactory();
     log.info("Version {}", Constants.VERSION);
-    log.info("Instance {}", instance.getInstanceID());
+    log.info("Instance {}", context.getInstanceID());
     AccumuloConfiguration conf = serverConfiguration.getSystemConfiguration();
     tableName = conf.get(Property.TRACE_TABLE);
     connector = ensureTraceTableExists(conf);
@@ -278,7 +278,8 @@ public class TraceServer implements Watcher {
           at = token;
         }
 
-        connector = instance.getConnector(principal, at);
+        connector = Connector.builder().usingClientInfo(context.getClientInfo())
+            .usingToken(principal, at).build();
         if (!connector.tableOperations().exists(tableName)) {
           connector.tableOperations().create(tableName);
           IteratorSetting setting = new IteratorSetting(10, "ageoff", AgeOffFilter.class.getName());
@@ -412,7 +413,8 @@ public class TraceServer implements Watcher {
     MetricsSystemHelper.configure(TraceServer.class.getSimpleName());
     Accumulo.init(fs, instance, conf, app);
     String hostname = opts.getAddress();
-    TraceServer server = new TraceServer(instance, conf, hostname);
+    AccumuloServerContext context = new AccumuloServerContext(instance, conf);
+    TraceServer server = new TraceServer(context, hostname);
     try {
       server.run();
     } finally {
diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/replication/AccumuloReplicaSystem.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/replication/AccumuloReplicaSystem.java
index 0eda5c7..a3f6368 100644
--- a/server/tserver/src/main/java/org/apache/accumulo/tserver/replication/AccumuloReplicaSystem.java
+++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/replication/AccumuloReplicaSystem.java
@@ -681,11 +681,8 @@ public class AccumuloReplicaSystem implements ReplicaSystem {
     requireNonNull(principal);
     requireNonNull(token);
 
-    return new ClientContext(getPeerInstance(target), new Credentials(principal, token), localConf);
-  }
-
-  protected Instance getPeerInstance(ReplicationTarget target) {
-    return new ZooKeeperInstance(instanceName, zookeepers);
+    return new ClientContext(new ZooKeeperInstance(instanceName, zookeepers),
+        new Credentials(principal, token), localConf);
   }
 
   protected RFileReplication getKeyValues(ReplicationTarget target, DataInputStream input, Path p,
diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/MinorCompactor.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/MinorCompactor.java
index 49e72aa..c6a7d1a 100644
--- a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/MinorCompactor.java
+++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/MinorCompactor.java
@@ -87,8 +87,7 @@ public class MinorCompactor extends Compactor {
 
   private boolean isTableDeleting() {
     try {
-      return Tables.getTableState(tabletServer.getInstance(),
-          extent.getTableId()) == TableState.DELETING;
+      return Tables.getTableState(tabletServer, extent.getTableId()) == TableState.DELETING;
     } catch (Exception e) {
       log.warn("Failed to determine if table " + extent.getTableId() + " was deleting ", e);
       return false; // can not get positive confirmation that its deleting.
diff --git a/shell/pom.xml b/shell/pom.xml
index 52806a2..c0e9ba1 100644
--- a/shell/pom.xml
+++ b/shell/pom.xml
@@ -120,11 +120,6 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.powermock</groupId>
-      <artifactId>powermock-module-junit4</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
       <scope>test</scope>
diff --git a/shell/src/main/java/org/apache/accumulo/shell/Shell.java b/shell/src/main/java/org/apache/accumulo/shell/Shell.java
index 98cd953..5374c25 100644
--- a/shell/src/main/java/org/apache/accumulo/shell/Shell.java
+++ b/shell/src/main/java/org/apache/accumulo/shell/Shell.java
@@ -37,6 +37,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 import java.util.TreeMap;
@@ -45,12 +46,13 @@ import java.util.concurrent.TimeUnit;
 import org.apache.accumulo.core.Constants;
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.ClientInfo;
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.IteratorSetting;
 import org.apache.accumulo.core.client.NamespaceNotFoundException;
 import org.apache.accumulo.core.client.TableNotFoundException;
-import org.apache.accumulo.core.client.ZooKeeperInstance;
+import org.apache.accumulo.core.client.impl.ClientContext;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
@@ -195,10 +197,9 @@ public class Shell extends ShellOptions implements KeywordExecutable {
 
   protected int exitCode = 0;
   private String tableName;
-  protected Instance instance;
   private Connector connector;
+  private ClientContext context;
   protected ConsoleReader reader;
-  private AuthenticationToken token;
   private final Class<? extends Formatter> defaultFormatterClass = DefaultFormatter.class;
   public Map<String,List<IteratorSetting>> scanIteratorOptions = new HashMap<>();
   public Map<String,List<IteratorSetting>> iteratorProfiles = new HashMap<>();
@@ -294,56 +295,58 @@ public class Shell extends ShellOptions implements KeywordExecutable {
       disableAuthTimeout = true;
     }
 
-    // get the options that were parsed
-    final String user;
-    try {
-      user = options.getUsername();
-    } catch (Exception e) {
-      logError(e.getMessage());
-      exitCode = 1;
-      return false;
-    }
-
     tabCompletion = !options.isTabCompletionDisabled();
+    this.setTableName("");
 
-    try {
-      setInstance(options);
-    } catch (Exception e) {
-      logError(e.getMessage());
-      exitCode = 1;
-      return false;
-    }
-
-    Properties props = options.getClientProperties();
-    String password = options.getPassword();
-    if (password == null && props.containsKey(ClientProperty.AUTH_TOKEN.getKey())
-        && user.equals(ClientProperty.AUTH_PRINCIPAL.getValue(props))) {
-      token = ClientProperty.getAuthenticationToken(props);
-    }
-    if (token == null) {
-      Runtime.getRuntime()
-          .addShutdownHook(new Thread(() -> reader.getTerminal().setEchoEnabled(true)));
-      // Read password if the user explicitly asked for it, or didn't specify anything at all
-      if ("stdin".equals(password) || password == null) {
-        password = reader.readLine("Password: ", '*');
+    if (connector == null) {
+      Properties props = options.getClientProperties();
+      if (ClientProperty.INSTANCE_ZOOKEEPERS.isEmpty(props)) {
+        throw new IllegalArgumentException("ZooKeepers must be set using -z or -zh on command line"
+            + " or in accumulo-client.properties");
       }
-      if (password == null) {
-        // User cancel, e.g. Ctrl-D pressed
-        throw new ParameterException("No password or token option supplied");
-      } else {
-        token = new PasswordToken(password);
+      if (ClientProperty.INSTANCE_NAME.isEmpty(props)) {
+        throw new IllegalArgumentException("Instance name must be set using -z or -zi on command "
+            + "line or in accumulo-client.properties");
+      }
+      final String principal;
+      try {
+        principal = options.getUsername();
+      } catch (Exception e) {
+        logError(e.getMessage());
+        exitCode = 1;
+        return false;
+      }
+      String password = options.getPassword();
+      AuthenticationToken token = null;
+      if (password == null && props.containsKey(ClientProperty.AUTH_TOKEN.getKey())
+          && principal.equals(ClientProperty.AUTH_PRINCIPAL.getValue(props))) {
+        token = ClientProperty.getAuthenticationToken(props);
+      }
+      if (token == null) {
+        Runtime.getRuntime()
+            .addShutdownHook(new Thread(() -> reader.getTerminal().setEchoEnabled(true)));
+        // Read password if the user explicitly asked for it, or didn't specify anything at all
+        if ("stdin".equals(password) || password == null) {
+          password = reader.readLine("Password: ", '*');
+        }
+        if (password == null) {
+          // User cancel, e.g. Ctrl-D pressed
+          throw new ParameterException("No password or token option supplied");
+        } else {
+          token = new PasswordToken(password);
+        }
+      }
+      ClientInfo info = ClientInfo.from(props);
+      try {
+        DistributedTrace.enable(InetAddress.getLocalHost().getHostName(), "shell", properties);
+        this.setTableName("");
+        connector = Connector.builder().usingClientInfo(info).usingToken(principal, token).build();
+        context = new ClientContext(connector.info());
+      } catch (Exception e) {
+        printException(e);
+        exitCode = 1;
+        return false;
       }
-    }
-
-    try {
-      DistributedTrace.enable(InetAddress.getLocalHost().getHostName(), "shell", properties);
-      this.setTableName("");
-      connector = instance.getConnector(user, token);
-
-    } catch (Exception e) {
-      printException(e);
-      exitCode = 1;
-      return false;
     }
 
     // decide whether to execute commands from a file and quit
@@ -416,82 +419,12 @@ public class Shell extends ShellOptions implements KeywordExecutable {
     return true;
   }
 
-  /**
-   * Sets the instance used by the shell based on the given options.
-   *
-   * @param options
-   *          shell options
-   */
-  protected void setInstance(ShellOptionsJC options) {
-    // should only be one set of instance options set
-    instance = null;
-    String instanceName, hosts;
-    if (options.getZooKeeperInstance().size() > 0) {
-      List<String> zkOpts = options.getZooKeeperInstance();
-      instanceName = zkOpts.get(0);
-      hosts = zkOpts.get(1);
-    } else {
-      instanceName = options.getZooKeeperInstanceName();
-      hosts = options.getZooKeeperHosts();
-    }
-    final Properties properties = options.getClientProperties();
-    instance = getZooInstance(instanceName, hosts, properties);
-  }
-
-  /**
-   * Get the ZooKeepers. Use the value passed in (if there was one), then fall back to value in
-   * accumulo-client.properties
-   *
-   * @param keepers
-   *          ZooKeepers passed to the shell
-   * @param properties
-   *          Client properties
-   * @return The ZooKeepers to connect to
-   */
-  static String getZooKeepers(String keepers, Properties properties) {
-    if (null != keepers) {
-      return keepers;
-    }
-    return properties.getProperty(ClientProperty.INSTANCE_ZOOKEEPERS.getKey());
-  }
-
-  /**
-   * Determines Instance using command line options and properties
-   *
-   * @param instanceName
-   *          Instance name set on CL
-   * @param keepersOption
-   *          ZooKeeper CL options
-   * @param properties
-   *          Config properties
-   * @return Instance
-   * @throws IllegalArgumentException
-   *           if no instance name or zookeeper can be determined
-   */
-  private static Instance getZooInstance(String instanceName, String keepersOption,
-      Properties properties) {
-    if (instanceName == null) {
-      instanceName = properties.getProperty(ClientProperty.INSTANCE_NAME.getKey());
-    }
-    String keepers = getZooKeepers(keepersOption, properties);
-
-    if (keepers == null) {
-      throw new IllegalArgumentException("ZooKeepers must be set using -z or"
-          + " -zh on command line or in accumulo-client.properties");
-    }
-    if (instanceName == null) {
-      throw new IllegalArgumentException("Instance name must be set using -z or"
-          + " -zi on command line or in accumulo-client.properties");
-    }
-    return new ZooKeeperInstance(instanceName, keepers);
-  }
-
   public Connector getConnector() {
     return connector;
   }
 
   public Instance getInstance() {
-    return instance;
+    return connector.getInstance();
   }
 
   public ClassLoader getClassLoader(final CommandLine cl, final Shell shellState)
@@ -722,6 +655,8 @@ public class Shell extends ShellOptions implements KeywordExecutable {
   }
 
   public String getDefaultPrompt() {
+    Objects.nonNull(connector);
+    Objects.nonNull(connector.info());
     return connector.whoami() + "@" + connector.info().getInstanceName()
         + (getTableName().isEmpty() ? "" : " ") + getTableName() + "> ";
   }
@@ -1226,16 +1161,12 @@ public class Shell extends ShellOptions implements KeywordExecutable {
 
   public void updateUser(String principal, AuthenticationToken token)
       throws AccumuloException, AccumuloSecurityException {
-    connector = instance.getConnector(principal, token);
-    this.token = token;
-  }
-
-  public String getPrincipal() {
-    return connector.whoami();
+    connector = connector.changeUser(principal, token);
+    context = new ClientContext(connector.info());
   }
 
-  public AuthenticationToken getToken() {
-    return token;
+  public ClientContext getContext() {
+    return context;
   }
 
   /**
diff --git a/shell/src/main/java/org/apache/accumulo/shell/ShellOptionsJC.java b/shell/src/main/java/org/apache/accumulo/shell/ShellOptionsJC.java
index 25aec13..1bd8afa 100644
--- a/shell/src/main/java/org/apache/accumulo/shell/ShellOptionsJC.java
+++ b/shell/src/main/java/org/apache/accumulo/shell/ShellOptionsJC.java
@@ -239,24 +239,12 @@ public class ShellOptionsJC {
     return execFileVerbose;
   }
 
-  public List<String> getZooKeeperInstance() {
-    return zooKeeperInstance;
-  }
-
-  public String getZooKeeperInstanceName() {
-    return zooKeeperInstanceName;
-  }
-
-  public String getZooKeeperHosts() {
-    return zooKeeperHosts;
-  }
-
   public int getAuthTimeout() {
     return authTimeout;
   }
 
   public boolean isAuthTimeoutDisabled() {
-    if (useSasl()) {
+    if (useSasl) {
       return true;
     }
     return authTimeoutDisabled;
@@ -266,10 +254,6 @@ public class ShellOptionsJC {
     return unrecognizedOptions;
   }
 
-  public boolean useSsl() {
-    return useSsl;
-  }
-
   public String getClientConfigFile() {
     if (clientConfigFile == null) {
       List<String> searchPaths = new LinkedList<>();
@@ -303,16 +287,15 @@ public class ShellOptionsJC {
     for (Map.Entry<String,String> entry : commandLineProperties.entrySet()) {
       props.setProperty(entry.getKey(), entry.getValue());
     }
-    if (useSsl()) {
+    if (useSsl) {
       props.setProperty(ClientProperty.SSL_ENABLED.getKey(), "true");
     }
-    if (useSasl()) {
+    if (useSasl) {
       props.setProperty(ClientProperty.SASL_ENABLED.getKey(), "true");
     }
-    if (!getZooKeeperInstance().isEmpty()) {
-      List<String> zkOpts = getZooKeeperInstance();
-      String instanceName = zkOpts.get(0);
-      String hosts = zkOpts.get(1);
+    if (!zooKeeperInstance.isEmpty()) {
+      String instanceName = zooKeeperInstance.get(0);
+      String hosts = zooKeeperInstance.get(1);
       props.setProperty(ClientProperty.INSTANCE_ZOOKEEPERS.getKey(), hosts);
       props.setProperty(ClientProperty.INSTANCE_NAME.getKey(), instanceName);
     }
@@ -326,7 +309,4 @@ public class ShellOptionsJC {
     return props;
   }
 
-  public boolean useSasl() {
-    return useSasl;
-  }
 }
diff --git a/shell/src/main/java/org/apache/accumulo/shell/commands/CreateUserCommand.java b/shell/src/main/java/org/apache/accumulo/shell/commands/CreateUserCommand.java
index 7655c28..991dbc6 100644
--- a/shell/src/main/java/org/apache/accumulo/shell/commands/CreateUserCommand.java
+++ b/shell/src/main/java/org/apache/accumulo/shell/commands/CreateUserCommand.java
@@ -37,7 +37,7 @@ public class CreateUserCommand extends Command {
       TableExistsException, IOException {
     final String user = cl.getArgs()[0];
 
-    AuthenticationToken userToken = shellState.getToken();
+    AuthenticationToken userToken = shellState.getConnector().info().getAuthenticationToken();
     PasswordToken passwordToken;
     if (userToken instanceof KerberosToken) {
       passwordToken = new PasswordToken();
diff --git a/shell/src/main/java/org/apache/accumulo/shell/commands/TraceCommand.java b/shell/src/main/java/org/apache/accumulo/shell/commands/TraceCommand.java
index 2ec9e1a..1b85530 100644
--- a/shell/src/main/java/org/apache/accumulo/shell/commands/TraceCommand.java
+++ b/shell/src/main/java/org/apache/accumulo/shell/commands/TraceCommand.java
@@ -41,7 +41,7 @@ public class TraceCommand extends DebugCommand {
       throws IOException {
     if (cl.getArgs().length == 1) {
       if (cl.getArgs()[0].equalsIgnoreCase("on")) {
-        Trace.on("shell:" + shellState.getPrincipal());
+        Trace.on("shell:" + shellState.getConnector().whoami());
       } else if (cl.getArgs()[0].equalsIgnoreCase("off")) {
         if (Trace.isTracing()) {
           final long trace = Trace.currentTraceId();
diff --git a/shell/src/test/java/org/apache/accumulo/shell/ShellConfigTest.java b/shell/src/test/java/org/apache/accumulo/shell/ShellConfigTest.java
index cc29383..76acb06 100644
--- a/shell/src/test/java/org/apache/accumulo/shell/ShellConfigTest.java
+++ b/shell/src/test/java/org/apache/accumulo/shell/ShellConfigTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.accumulo.shell;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -27,9 +26,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.nio.file.Files;
-import java.util.Properties;
 
-import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.log4j.Level;
 import org.junit.After;
 import org.junit.Before;
@@ -115,17 +112,4 @@ public class ShellConfigTest {
     assertTrue("Did not print usage", output.get().contains("Usage"));
   }
 
-  @Test
-  public void testZooKeeperHostFromClientProps() {
-    Properties props = new Properties();
-    props.setProperty(ClientProperty.INSTANCE_ZOOKEEPERS.getKey(), "cc_hostname");
-    assertEquals("cc_hostname", Shell.getZooKeepers(null, props));
-  }
-
-  @Test
-  public void testZooKeeperHostFromOption() {
-    Properties props = new Properties();
-    props.setProperty(ClientProperty.INSTANCE_ZOOKEEPERS.getKey(), "cc_hostname");
-    assertEquals("opt_hostname", Shell.getZooKeepers("opt_hostname", props));
-  }
 }
diff --git a/shell/src/test/java/org/apache/accumulo/shell/ShellSetInstanceTest.java b/shell/src/test/java/org/apache/accumulo/shell/ShellSetInstanceTest.java
deleted file mode 100644
index b0e48db..0000000
--- a/shell/src/test/java/org/apache/accumulo/shell/ShellSetInstanceTest.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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.shell;
-
-import static org.easymock.EasyMock.expect;
-import static org.powermock.api.easymock.PowerMock.createMock;
-import static org.powermock.api.easymock.PowerMock.expectLastCall;
-import static org.powermock.api.easymock.PowerMock.expectNew;
-import static org.powermock.api.easymock.PowerMock.replay;
-import static org.powermock.api.easymock.PowerMock.verify;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.accumulo.core.client.ZooKeeperInstance;
-import org.apache.accumulo.core.conf.ClientProperty;
-import org.apache.accumulo.core.conf.ConfigSanityCheck;
-import org.apache.accumulo.core.conf.Property;
-import org.apache.accumulo.core.conf.SiteConfiguration;
-import org.apache.accumulo.core.zookeeper.ZooUtil;
-import org.apache.log4j.Level;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import jline.console.ConsoleReader;
-
-@RunWith(PowerMockRunner.class)
-@PowerMockIgnore("javax.security.*")
-@PrepareForTest({Shell.class, ZooUtil.class, ConfigSanityCheck.class})
-public class ShellSetInstanceTest {
-  public static class TestOutputStream extends OutputStream {
-    StringBuilder sb = new StringBuilder();
-
-    @Override
-    public void write(int b) throws IOException {
-      sb.append((char) (0xff & b));
-    }
-
-    public String get() {
-      return sb.toString();
-    }
-
-    public void clear() {
-      sb.setLength(0);
-    }
-  }
-
-  /**
-   * Skip all tests if we have a known bad version of java; See ACCUMULO-3031
-   */
-  @BeforeClass
-  public static void checkJavaVersion() {
-    String javaVer = System.getProperty("java.version", "");
-    if (javaVer.matches("^1[.]7[.]0_(\\d+)$")) {
-      int v = Integer.parseInt(javaVer.substring(6));
-      Assume.assumeTrue("Skipping test due to incompatible Java version; See ACCUMULO-3031",
-          v <= 60 || v >= 72);
-    }
-  }
-
-  @BeforeClass
-  public static void setupClass() {
-    // This is necessary because PowerMock messes with Hadoop's ability to
-    // determine the current user (see security.UserGroupInformation).
-    System.setProperty("HADOOP_USER_NAME", "test");
-  }
-
-  @AfterClass
-  public static void teardownClass() {
-    System.clearProperty("HADOOP_USER_NAME");
-  }
-
-  private TestOutputStream output;
-  private Shell shell;
-
-  @Before
-  public void setup() throws IOException {
-    Shell.log.setLevel(Level.OFF);
-    output = new TestOutputStream();
-    shell = new Shell(new ConsoleReader(new FileInputStream(FileDescriptor.in), output));
-    shell.setLogErrorsToConsole();
-  }
-
-  @After
-  public void tearDown() {
-    shell.shutdown();
-    SiteConfiguration.clearInstance();
-  }
-
-  @Test
-  public void testSetInstance_ZKInstance_DashZ() throws Exception {
-    testSetInstance_ZKInstance(true);
-  }
-
-  @Test
-  public void testSetInstance_ZKInstance_DashZIandZH() throws Exception {
-    testSetInstance_ZKInstance(false);
-  }
-
-  private void testSetInstance_ZKInstance(boolean dashZ) throws Exception {
-    Properties props = createMock(Properties.class);
-    ShellOptionsJC opts = createMock(ShellOptionsJC.class);
-    expect(opts.getClientProperties()).andReturn(new Properties());
-    expect(props.getProperty(Property.GENERAL_SECURITY_CREDENTIAL_PROVIDER_PATHS.getKey()))
-        .andReturn(null);
-    if (dashZ) {
-      expect(props.getProperty(ClientProperty.INSTANCE_NAME.getKey())).andReturn("foo");
-      expect(props.getProperty(ClientProperty.INSTANCE_ZOOKEEPERS.getKey()))
-          .andReturn("host1,host2");
-      List<String> zl = new java.util.ArrayList<>();
-      zl.add("bar");
-      zl.add("host3,host4");
-      expect(opts.getZooKeeperInstance()).andReturn(zl);
-      expectLastCall().anyTimes();
-    } else {
-      expect(props.getProperty(ClientProperty.INSTANCE_NAME.getKey())).andReturn("bar");
-      expect(props.getProperty(ClientProperty.INSTANCE_ZOOKEEPERS.getKey()))
-          .andReturn("host3,host4");
-      expect(opts.getZooKeeperInstance()).andReturn(Collections.emptyList());
-      expect(opts.getZooKeeperInstanceName()).andReturn("bar");
-      expect(opts.getZooKeeperHosts()).andReturn("host3,host4");
-    }
-    replay(props);
-    replay(opts);
-
-    ZooKeeperInstance theInstance = createMock(ZooKeeperInstance.class);
-    expectNew(ZooKeeperInstance.class, new Class<?>[] {String.class, String.class}, "bar",
-        "host3,host4").andReturn(theInstance);
-    replay(theInstance, ZooKeeperInstance.class);
-
-    shell.setInstance(opts);
-    verify(theInstance, ZooKeeperInstance.class);
-  }
-}
diff --git a/test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java b/test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java
index b28422a..089da23 100644
--- a/test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java
@@ -130,7 +130,7 @@ public class ArbitraryTablePropertiesIT extends SharedMiniClusterBase {
     Assert.assertTrue(Property.isValidPropertyKey(propertyName));
 
     // Getting a fresh token will ensure we're logged in as this user (if necessary)
-    Connector testConn = c.getInstance().getConnector(testUser, user.getToken());
+    Connector testConn = c.changeUser(testUser, user.getToken());
     // Set the property to the desired value
     testConn.tableOperations().setProperty(tableName, propertyName, description1);
 
@@ -194,7 +194,7 @@ public class ArbitraryTablePropertiesIT extends SharedMiniClusterBase {
     Assert.assertTrue(Property.isValidPropertyKey(propertyName));
 
     // Getting a fresh token will ensure we're logged in as this user (if necessary)
-    Connector testConn = c.getInstance().getConnector(testUser, user.getToken());
+    Connector testConn = c.changeUser(testUser, user.getToken());
 
     // Try to set the property to the desired value.
     // If able to set it, the test fails, since permission was never granted
diff --git a/test/src/main/java/org/apache/accumulo/test/ConditionalWriterIT.java b/test/src/main/java/org/apache/accumulo/test/ConditionalWriterIT.java
index aef3ce3..4d18a20 100644
--- a/test/src/main/java/org/apache/accumulo/test/ConditionalWriterIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/ConditionalWriterIT.java
@@ -253,8 +253,7 @@ public class ConditionalWriterIT extends AccumuloClusterHarness {
     conn.securityOperations().changeUserAuthorizations(user, auths);
     conn.securityOperations().grantSystemPermission(user, SystemPermission.CREATE_TABLE);
 
-    conn = conn.getInstance().getConnector(user, user1.getToken());
-
+    conn = conn.changeUser(user, user1.getToken());
     conn.tableOperations().create(tableName);
 
     try (
@@ -1301,7 +1300,7 @@ public class ConditionalWriterIT extends AccumuloClusterHarness {
     conn.securityOperations().grantTablePermission(user, table3, TablePermission.WRITE);
 
     // Login as the user
-    Connector conn2 = conn.getInstance().getConnector(user, user1.getToken());
+    Connector conn2 = conn.changeUser(user, user1.getToken());
 
     ConditionalMutation cm1 = new ConditionalMutation("r1", new Condition("tx", "seq"));
     cm1.put("tx", "seq", "1");
diff --git a/test/src/main/java/org/apache/accumulo/test/NamespacesIT.java b/test/src/main/java/org/apache/accumulo/test/NamespacesIT.java
index 2f037b4..2460071 100644
--- a/test/src/main/java/org/apache/accumulo/test/NamespacesIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/NamespacesIT.java
@@ -677,7 +677,7 @@ public class NamespacesIT extends AccumuloClusterHarness {
     c.securityOperations().createLocalUser(u1, pass);
 
     loginAs(user1);
-    Connector user1Con = c.getInstance().getConnector(u1, user1.getToken());
+    Connector user1Con = c.changeUser(u1, user1.getToken());
 
     try {
       user1Con.tableOperations().create(t2);
diff --git a/test/src/main/java/org/apache/accumulo/test/SampleIT.java b/test/src/main/java/org/apache/accumulo/test/SampleIT.java
index 3056e81..a4387b6 100644
--- a/test/src/main/java/org/apache/accumulo/test/SampleIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/SampleIT.java
@@ -45,7 +45,7 @@ import org.apache.accumulo.core.client.ScannerBase;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.admin.CompactionConfig;
 import org.apache.accumulo.core.client.admin.NewTableConfiguration;
-import org.apache.accumulo.core.client.impl.Credentials;
+import org.apache.accumulo.core.client.impl.ClientContext;
 import org.apache.accumulo.core.client.impl.OfflineScanner;
 import org.apache.accumulo.core.client.impl.Table;
 import org.apache.accumulo.core.client.sample.RowSampler;
@@ -212,8 +212,8 @@ public class SampleIT extends AccumuloClusterHarness {
     conn.tableOperations().clone(tableName, clone, false, em, es);
     conn.tableOperations().offline(clone, true);
     Table.ID cloneID = Table.ID.of(conn.tableOperations().tableIdMap().get(clone));
-    OfflineScanner oScanner = new OfflineScanner(conn.getInstance(),
-        new Credentials(getAdminPrincipal(), getAdminToken()), cloneID, Authorizations.EMPTY);
+    ClientContext context = new ClientContext(conn.info());
+    OfflineScanner oScanner = new OfflineScanner(context, cloneID, Authorizations.EMPTY);
     if (sc != null) {
       oScanner.setSamplerConfiguration(sc);
     }
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/ConnectorIT.java b/test/src/main/java/org/apache/accumulo/test/functional/ConnectorIT.java
index 762fcff..490598f 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/ConnectorIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/ConnectorIT.java
@@ -78,5 +78,18 @@ public class ConnectorIT extends AccumuloClusterHarness {
     Assert.assertEquals(instanceName, info.getInstanceName());
     Assert.assertEquals(zookeepers, info.getZooKeepers());
     Assert.assertEquals(user2, info.getPrincipal());
+
+    final String user3 = "testuser3";
+    final String password3 = "testpassword3";
+    c.securityOperations().createLocalUser(user3, new PasswordToken(password3));
+
+    Connector conn3 = conn.changeUser(user3, new PasswordToken(password3));
+    Assert.assertEquals(instanceName, conn3.info().getInstanceName());
+    Assert.assertEquals(zookeepers, conn3.info().getZooKeepers());
+    Assert.assertEquals(user3, conn3.whoami());
+    info = conn3.info();
+    Assert.assertEquals(instanceName, info.getInstanceName());
+    Assert.assertEquals(zookeepers, info.getZooKeepers());
+    Assert.assertEquals(user3, info.getPrincipal());
   }
 }
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/CredentialsIT.java b/test/src/main/java/org/apache/accumulo/test/functional/CredentialsIT.java
index 3177a20..4388c45 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/CredentialsIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/CredentialsIT.java
@@ -29,7 +29,6 @@ import org.apache.accumulo.cluster.ClusterUser;
 import org.apache.accumulo.core.client.AccumuloException;
 import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.security.SecurityErrorCode;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
@@ -49,7 +48,6 @@ public class CredentialsIT extends AccumuloClusterHarness {
   private boolean saslEnabled;
   private String username;
   private String password;
-  private Instance inst;
 
   @Override
   public int defaultTimeoutSeconds() {
@@ -59,8 +57,6 @@ public class CredentialsIT extends AccumuloClusterHarness {
   @Before
   public void createLocalUser() throws AccumuloException, AccumuloSecurityException {
     Connector conn = getConnector();
-    inst = conn.getInstance();
-
     ClusterUser user = getUser(0);
     username = user.getPrincipal();
     saslEnabled = saslEnabled();
@@ -93,7 +89,7 @@ public class CredentialsIT extends AccumuloClusterHarness {
     token.destroy();
     assertTrue(token.isDestroyed());
     try {
-      inst.getConnector("non_existent_user", token);
+      getConnector().changeUser("non_existent_user", token);
       fail();
     } catch (AccumuloSecurityException e) {
       assertEquals(e.getSecurityErrorCode(), SecurityErrorCode.TOKEN_EXPIRED);
@@ -103,7 +99,7 @@ public class CredentialsIT extends AccumuloClusterHarness {
   @Test
   public void testDestroyTokenBeforeRPC() throws Exception {
     AuthenticationToken token = getUser(0).getToken();
-    Connector userConnector = inst.getConnector(username, token);
+    Connector userConnector = getConnector().changeUser(username, token);
     try (Scanner scanner = userConnector.createScanner(MetadataTable.NAME, Authorizations.EMPTY)) {
       assertFalse(token.isDestroyed());
       token.destroy();
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/MasterFailoverIT.java b/test/src/main/java/org/apache/accumulo/test/functional/MasterFailoverIT.java
index 28bc628..b84afa5 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/MasterFailoverIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/MasterFailoverIT.java
@@ -22,6 +22,7 @@ import org.apache.accumulo.cluster.ClusterControl;
 import org.apache.accumulo.core.cli.BatchWriterOpts;
 import org.apache.accumulo.core.cli.ScannerOpts;
 import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.harness.AccumuloClusterHarness;
 import org.apache.accumulo.minicluster.ServerType;
@@ -38,6 +39,7 @@ public class MasterFailoverIT extends AccumuloClusterHarness {
     Map<String,String> siteConfig = cfg.getSiteConfig();
     siteConfig.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "15s");
     cfg.setSiteConfig(siteConfig);
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
   }
 
   @Override
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/PermissionsIT.java b/test/src/main/java/org/apache/accumulo/test/functional/PermissionsIT.java
index 14f354d..0b60336 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/PermissionsIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/PermissionsIT.java
@@ -109,7 +109,7 @@ public class PermissionsIT extends AccumuloClusterHarness {
     loginAs(rootUser);
     c.securityOperations().createLocalUser(principal, passwordToken);
     loginAs(testUser);
-    Connector test_user_conn = c.getInstance().getConnector(principal, token);
+    Connector test_user_conn = c.changeUser(principal, token);
     loginAs(rootUser);
     verifyHasNoSystemPermissions(c, principal, SystemPermission.values());
 
@@ -565,7 +565,7 @@ public class PermissionsIT extends AccumuloClusterHarness {
     Connector c = getConnector();
     c.securityOperations().createLocalUser(principal, passwordToken);
     loginAs(testUser);
-    Connector test_user_conn = c.getInstance().getConnector(principal, token);
+    Connector test_user_conn = c.changeUser(principal, token);
 
     // check for read-only access to metadata table
     loginAs(rootUser);
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/RestartIT.java b/test/src/main/java/org/apache/accumulo/test/functional/RestartIT.java
index 5a1c598..cd889ca 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/RestartIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/RestartIT.java
@@ -36,6 +36,7 @@ import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 import org.apache.accumulo.core.client.security.tokens.KerberosToken;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.metadata.MetadataTable;
 import org.apache.accumulo.core.zookeeper.ZooUtil;
@@ -66,6 +67,7 @@ public class RestartIT extends AccumuloClusterHarness {
 
   @Override
   public void configureMiniCluster(MiniAccumuloConfigImpl cfg, Configuration hadoopCoreSite) {
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
     cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
     cfg.setProperty(Property.GC_CYCLE_DELAY, "1s");
     cfg.setProperty(Property.GC_CYCLE_START, "1s");
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/SummaryIT.java b/test/src/main/java/org/apache/accumulo/test/functional/SummaryIT.java
index 000c625..41fedbf 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/SummaryIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/SummaryIT.java
@@ -57,7 +57,6 @@ import org.apache.accumulo.core.client.MutationsRejectedException;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.TableOfflineException;
-import org.apache.accumulo.core.client.ZooKeeperInstance;
 import org.apache.accumulo.core.client.admin.CompactionConfig;
 import org.apache.accumulo.core.client.admin.CompactionStrategyConfig;
 import org.apache.accumulo.core.client.admin.NewTableConfiguration;
@@ -585,9 +584,7 @@ public class SummaryIT extends AccumuloClusterHarness {
     PasswordToken passTok = new PasswordToken("letmesee");
     c.securityOperations().createLocalUser("user1", passTok);
 
-    String instanceName = c.info().getInstanceName();
-    String zookeepers = c.info().getZooKeepers();
-    Connector c2 = new ZooKeeperInstance(instanceName, zookeepers).getConnector("user1", passTok);
+    Connector c2 = c.changeUser("user1", passTok);
     try {
       c2.tableOperations().summaries(table).retrieve();
       Assert
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/TableChangeStateIT.java b/test/src/main/java/org/apache/accumulo/test/functional/TableChangeStateIT.java
index 8e80230..533cc2a 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/TableChangeStateIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/TableChangeStateIT.java
@@ -270,7 +270,7 @@ public class TableChangeStateIT extends AccumuloClusterHarness {
 
     Table.ID tableId = Tables.getTableId(context, tableName);
 
-    TableState tstate = Tables.getTableState(connector.getInstance(), tableId);
+    TableState tstate = Tables.getTableState(context, tableId);
 
     log.trace("tableName: '{}': tableId {}, current state: {}", tableName, tableId, tstate);
 
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/TabletStateChangeIteratorIT.java b/test/src/main/java/org/apache/accumulo/test/functional/TabletStateChangeIteratorIT.java
index fcc670e..861b38b 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/TabletStateChangeIteratorIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/TabletStateChangeIteratorIT.java
@@ -38,6 +38,7 @@ import org.apache.accumulo.core.client.MutationsRejectedException;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.TableExistsException;
 import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.impl.ClientContext;
 import org.apache.accumulo.core.client.impl.Table;
 import org.apache.accumulo.core.client.impl.Tables;
 import org.apache.accumulo.core.data.Key;
@@ -242,9 +243,10 @@ public class TabletStateChangeIteratorIT extends AccumuloClusterHarness {
 
     @Override
     public Set<Table.ID> onlineTables() {
-      Set<Table.ID> onlineTables = Tables.getIdToNameMap(getConnector().getInstance()).keySet();
-      return Sets.filter(onlineTables, tableId -> Tables.getTableState(getConnector().getInstance(),
-          tableId) == TableState.ONLINE);
+      ClientContext context = new ClientContext(getClientInfo());
+      Set<Table.ID> onlineTables = Tables.getIdToNameMap(context.getInstance()).keySet();
+      return Sets.filter(onlineTables,
+          tableId -> Tables.getTableState(context, tableId) == TableState.ONLINE);
     }
 
     @Override
diff --git a/test/src/main/java/org/apache/accumulo/test/functional/ZookeeperRestartIT.java b/test/src/main/java/org/apache/accumulo/test/functional/ZookeeperRestartIT.java
index 7fecac7..fa6aea1 100644
--- a/test/src/main/java/org/apache/accumulo/test/functional/ZookeeperRestartIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/functional/ZookeeperRestartIT.java
@@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit;
 import org.apache.accumulo.core.client.BatchWriter;
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.Scanner;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Mutation;
@@ -48,6 +49,7 @@ public class ZookeeperRestartIT extends ConfigurableMacBase {
     Map<String,String> siteConfig = new HashMap<>();
     siteConfig.put(Property.INSTANCE_ZK_TIMEOUT.getKey(), "15s");
     cfg.setSiteConfig(siteConfig);
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
   }
 
   @Override
diff --git a/test/src/main/java/org/apache/accumulo/test/master/SuspendedTabletsIT.java b/test/src/main/java/org/apache/accumulo/test/master/SuspendedTabletsIT.java
index a5d1f74..037ebe9 100644
--- a/test/src/main/java/org/apache/accumulo/test/master/SuspendedTabletsIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/master/SuspendedTabletsIT.java
@@ -41,6 +41,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.impl.ClientContext;
 import org.apache.accumulo.core.client.impl.MasterClient;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.data.Range;
 import org.apache.accumulo.core.data.impl.KeyExtent;
@@ -77,6 +78,7 @@ public class SuspendedTabletsIT extends ConfigurableMacBase {
   @Override
   public void configure(MiniAccumuloConfigImpl cfg, Configuration fsConf) {
     cfg.setProperty(Property.TABLE_SUSPEND_DURATION, SUSPEND_DURATION + "ms");
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "5s");
     cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "5s");
     cfg.setNumTservers(TSERVERS);
   }
diff --git a/test/src/main/java/org/apache/accumulo/test/performance/metadata/MetadataBatchScanTest.java b/test/src/main/java/org/apache/accumulo/test/performance/metadata/MetadataBatchScanTest.java
index 15968a7..7bd8e32 100644
--- a/test/src/main/java/org/apache/accumulo/test/performance/metadata/MetadataBatchScanTest.java
+++ b/test/src/main/java/org/apache/accumulo/test/performance/metadata/MetadataBatchScanTest.java
@@ -30,9 +30,7 @@ import org.apache.accumulo.core.client.BatchScanner;
 import org.apache.accumulo.core.client.BatchWriter;
 import org.apache.accumulo.core.client.BatchWriterConfig;
 import org.apache.accumulo.core.client.Connector;
-import org.apache.accumulo.core.client.Instance;
 import org.apache.accumulo.core.client.Scanner;
-import org.apache.accumulo.core.client.ZooKeeperInstance;
 import org.apache.accumulo.core.client.impl.Table;
 import org.apache.accumulo.core.data.Mutation;
 import org.apache.accumulo.core.data.Range;
@@ -64,8 +62,7 @@ public class MetadataBatchScanTest {
 
     ClientOpts opts = new ClientOpts();
     opts.parseArgs(MetadataBatchScanTest.class.getName(), args);
-    Instance inst = new ZooKeeperInstance("acu14", "localhost");
-    final Connector connector = inst.getConnector(opts.getPrincipal(), opts.getToken());
+    final Connector connector = opts.getConnector();
 
     TreeSet<Long> splits = new TreeSet<>();
     Random r = new Random(42);
diff --git a/test/src/main/java/org/apache/accumulo/test/proxy/ProxyDurabilityIT.java b/test/src/main/java/org/apache/accumulo/test/proxy/ProxyDurabilityIT.java
index 5ba3c61..28aca3c 100644
--- a/test/src/main/java/org/apache/accumulo/test/proxy/ProxyDurabilityIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/proxy/ProxyDurabilityIT.java
@@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.security.Authorizations;
 import org.apache.accumulo.core.util.HostAndPort;
@@ -69,6 +70,7 @@ public class ProxyDurabilityIT extends ConfigurableMacBase {
   @Override
   public void configure(MiniAccumuloConfigImpl cfg, Configuration hadoopCoreSite) {
     hadoopCoreSite.set("fs.file.impl", RawLocalFileSystem.class.getName());
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
     cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
     cfg.setNumTservers(1);
   }
diff --git a/test/src/main/java/org/apache/accumulo/test/replication/GarbageCollectorCommunicatesWithTServersIT.java b/test/src/main/java/org/apache/accumulo/test/replication/GarbageCollectorCommunicatesWithTServersIT.java
index c5635ad..a1192c2 100644
--- a/test/src/main/java/org/apache/accumulo/test/replication/GarbageCollectorCommunicatesWithTServersIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/replication/GarbageCollectorCommunicatesWithTServersIT.java
@@ -30,6 +30,7 @@ import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.impl.ClientContext;
 import org.apache.accumulo.core.client.impl.MasterClient;
 import org.apache.accumulo.core.client.impl.Table;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Mutation;
@@ -79,6 +80,7 @@ public class GarbageCollectorCommunicatesWithTServersIT extends ConfigurableMacB
   @Override
   public void configure(MiniAccumuloConfigImpl cfg, Configuration coreSite) {
     cfg.setNumTservers(1);
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
     cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
     cfg.setProperty(Property.GC_CYCLE_DELAY, GC_PERIOD_SECONDS + "s");
     // Wait longer to try to let the replication table come online before a cycle runs
diff --git a/test/src/main/java/org/apache/accumulo/test/replication/KerberosReplicationIT.java b/test/src/main/java/org/apache/accumulo/test/replication/KerberosReplicationIT.java
index 0453036..85f72b3 100644
--- a/test/src/main/java/org/apache/accumulo/test/replication/KerberosReplicationIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/replication/KerberosReplicationIT.java
@@ -26,6 +26,7 @@ import org.apache.accumulo.core.client.BatchWriterConfig;
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.security.tokens.KerberosToken;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Mutation;
@@ -107,6 +108,7 @@ public class KerberosReplicationIT extends AccumuloITBase {
       @Override
       public void configureMiniCluster(MiniAccumuloConfigImpl cfg, Configuration coreSite) {
         cfg.setNumTservers(1);
+        cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
         cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
         cfg.setProperty(Property.TSERV_WALOG_MAX_SIZE, "2M");
         cfg.setProperty(Property.GC_CYCLE_START, "1s");
diff --git a/test/src/main/java/org/apache/accumulo/test/replication/MultiInstanceReplicationIT.java b/test/src/main/java/org/apache/accumulo/test/replication/MultiInstanceReplicationIT.java
index 2057d39..58c8b08 100644
--- a/test/src/main/java/org/apache/accumulo/test/replication/MultiInstanceReplicationIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/replication/MultiInstanceReplicationIT.java
@@ -34,6 +34,7 @@ import org.apache.accumulo.core.client.BatchWriterConfig;
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Mutation;
@@ -96,6 +97,7 @@ public class MultiInstanceReplicationIT extends ConfigurableMacBase {
   @Override
   public void configure(MiniAccumuloConfigImpl cfg, Configuration hadoopCoreSite) {
     cfg.setNumTservers(1);
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
     cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
     cfg.setProperty(Property.TSERV_WALOG_MAX_SIZE, "2M");
     cfg.setProperty(Property.GC_CYCLE_START, "1s");
diff --git a/test/src/main/java/org/apache/accumulo/test/replication/UnorderedWorkAssignerReplicationIT.java b/test/src/main/java/org/apache/accumulo/test/replication/UnorderedWorkAssignerReplicationIT.java
index f389fd9..b58c118 100644
--- a/test/src/main/java/org/apache/accumulo/test/replication/UnorderedWorkAssignerReplicationIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/replication/UnorderedWorkAssignerReplicationIT.java
@@ -34,6 +34,7 @@ import org.apache.accumulo.core.client.BatchWriterConfig;
 import org.apache.accumulo.core.client.Connector;
 import org.apache.accumulo.core.client.Scanner;
 import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.ClientProperty;
 import org.apache.accumulo.core.conf.Property;
 import org.apache.accumulo.core.data.Key;
 import org.apache.accumulo.core.data.Mutation;
@@ -103,6 +104,7 @@ public class UnorderedWorkAssignerReplicationIT extends ConfigurableMacBase {
   @Override
   public void configure(MiniAccumuloConfigImpl cfg, Configuration hadoopCoreSite) {
     cfg.setNumTservers(1);
+    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
     cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
     cfg.setProperty(Property.TSERV_WALOG_MAX_SIZE, "2M");
     cfg.setProperty(Property.GC_CYCLE_START, "1s");


Mime
View raw message