accumulo-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] mikewalch closed pull request #532: More work to remove usage of Instance
Date Tue, 26 Jun 2018 17:39:54 GMT
mikewalch closed pull request #532: More work to remove usage of Instance
URL: https://github.com/apache/accumulo/pull/532
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

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 31d57a4dc7..1f849d4272 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.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 static void setConnectorInfo(JobConf job, String principal, Authenticatio
     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 void initialize(InputSplit inSplit, JobConf job) throws IOException {
       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 void initialize(InputSplit inSplit, JobConf job) throws IOException {
       // 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 void initialize(InputSplit inSplit, JobConf job) throws IOException {
           // 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 void initialize(InputSplit inSplit, JobConf job) throws IOException {
 
         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 float getProgress() throws IOException {
   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 30710ec1e0..67221b115b 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.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;
@@ -92,6 +91,17 @@ public static void setClientInfo(JobConf job, ClientInfo info) {
     OutputConfigurator.setClientInfo(CLASS, job, outInfo);
   }
 
+  /**
+   * 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
    *
@@ -130,17 +140,6 @@ public static void setClientPropertiesFile(JobConf job, String clientPropsFile)
   @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 @@ protected AccumuloRecordWriter(JobConf job)
       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 void checkOutputSpecs(FileSystem ignored, JobConf job) throws IOException
       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 42e86378a8..91a6e4995a 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.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 static void setConnectorInfo(Job job, String principal, AuthenticationTok
     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 void initialize(InputSplit inSplit, TaskAttemptContext attempt) throws IO
       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 void initialize(InputSplit inSplit, TaskAttemptContext attempt) throws IO
       // 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 void initialize(InputSplit inSplit, TaskAttemptContext attempt) throws IO
           // 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 void initialize(InputSplit inSplit, TaskAttemptContext attempt) throws IO
 
         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 V getCurrentValue() throws IOException, InterruptedException {
   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 eaa67c89c6..b878b039c6 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.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;
@@ -92,6 +91,19 @@ public static void setClientInfo(Job job, ClientInfo info) {
     OutputConfigurator.setClientInfo(CLASS, job.getConfiguration(), info);
   }
 
+  /**
+   * 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
    *
@@ -130,17 +142,6 @@ public static void setClientPropertiesFile(Job job, String clientPropsFile) {
   @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 @@ protected AccumuloRecordWriter(TaskAttemptContext context)
       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 void checkOutputSpecs(JobContext job) throws IOException {
       // 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 1d7967ab56..0253138b18 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 static void validatePermissions(Class<?> implementingClass, Configuration
   }
 
   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 static void validatePermissions(Class<?> implementingClass, Configuration
 
       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 b0de76e4fe..84e7023238 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 AuthenticationToken getToken() {
         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 933a101ac6..d8612ae168 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 @@
 
 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 @@
    * @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 673da77fd4..2a7ee36e79 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
@@ -326,6 +326,19 @@ public abstract ConditionalWriter createConditionalWriter(String tableName,
    */
   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
    *
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 0401e07cc6..928d2b07f0 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 @@ private void queue(List<QCMutation> mutations) {
       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 @@ private void sendToServer(HostAndPort location, TabletServerMutations<QCMutation
     } 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 bf1cac53d2..244f764092 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 ConnectorImpl(final ClientContext context)
 
   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 ClientInfo info() {
     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 efd12a4f4f..15de01985f 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 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 @@ public IteratorEnvironment cloneWithSamplingEnabled() {
   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 @@ public OfflineIterator(ScannerOptions options, Instance instance, Credentials cr
     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 @@ private void nextTablet() throws TableNotFoundException, AccumuloException, IOEx
     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 f38e8868ea..d3229d2778 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.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 @@
   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 void disableIsolation() {
 
   @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 928dc8c173..6ed44a8638 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 @@ String doFateOperation(FateOperation op, List<ByteBuffer> args, Map<String,Strin
     } 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 @@ private void addSplits(String tableName, SortedSet<Text> partitionKeys, Table.ID
         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 @@ else if (Tables.getTableState(context.getInstance(), tableId) == TableState.OFFL
           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 void setLocalityGroups(String tableName, Map<String,Set<Text>> groups)
     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 @@ private void waitForTableStateTransition(Table.ID tableId, TableState expectedSt
 
     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 void online(String tableName, boolean wait)
      * 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 Locations locate(String tableName, Collection<Range> ranges)
 
       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 SummaryRetriever startRow(CharSequence startRow) {
       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 b1a58f30a5..63e9316d25 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 static boolean exists(Instance instance, Table.ID tableId) {
     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 static void clearCacheByPath(Instance instance, final String zooPath) {
     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 static TableState getTableState(Instance instance, Table.ID tableId) {
     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 fcb07beb78..c5c2a74a5c 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 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 @@
   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 TabletServerBatchReaderIterator(ClientContext context, Table.ID tableId,
       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 @@ private void binRanges(TabletLocator tabletLocator, List<Range> ranges,
         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 @@ private void processFailures(Map<KeyExtent,List<Range>> failures, ResultReceiver
   }
 
   private String getTableInfo() {
-    return Tables.getPrintableTableInfoFromId(instance, tableId);
+    return Tables.getPrintableTableInfoFromId(context, tableId);
   }
 
   private class QueryTask implements Runnable {
@@ -386,7 +383,7 @@ public void run() {
         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 @@ static void doLookup(ClientContext context, String server, Map<KeyExtent,List<Ra
       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 61dc81bee4..989f343f57 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 @@ private void updateAuthorizationFailures(Map<KeyExtent,SecurityErrorCode> author
       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 @@ private void binMutations(MutationSet mutationsToProcess,
               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 3d7d48fa2d..ac2143112d 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 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 @@ static long pause(long millis, long maxSleep) throws InterruptedException {
       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 @@ static long pause(long millis, long maxSleep) throws InterruptedException {
                 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 @@ else if (log.isTraceEnabled())
         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 785296db1b..1ec160976c 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 String getValue(Properties properties) {
     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 fddffa2807..c5b7e84bc4 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 void waitForStoreTransitionScannerConfiguredCorrectly() throws Exception
     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 1ac98f8f64..bb188ce5a5 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 @@ int displayUnassigned() {
 
   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 db8db264e1..b4eeacd20d 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 @@
 
   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 5c55347844..ded98eee6c 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 @@
   @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 5f1624c02c..eb73136e87 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 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 @@ public long isReady(long tid, Master master) throws Exception {
 
     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 1599ed293c..6e2a3bd039 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 RenameTable(Namespace.ID namespaceId, Table.ID tableId, String oldTableNa
           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 8fcf1dedf3..a590b497a3 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.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 @@
     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 @@ public long isReady(long tid, Master master) throws Exception {
 
     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 a645c1dfdc..56bb93bdc3 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 long isReady(long tid, Master master) throws Exception {
     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 356e3d698b..2d0748ead4 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 @@ public long isReady(long tid, Master master) throws Exception {
     }
 
     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 b97426ce6c..ceade85852 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 long isReady(long tid, Master master) throws Exception {
 
     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 aaecf4e6fd..d163740ff2 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 boolean add(Pair<Long,T> obj) {
   private static Exception problemException;
   private static GCStatus gcStatus;
 
-  private static Instance instance;
-
   private static ServerConfigurationFactory config;
   private static AccumuloServerContext context;
 
@@ -421,14 +419,14 @@ private static GCStatus fetchGcStatus() {
     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 static void main(String[] args) throws Exception {
     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 void run(String hostname) {
     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 @@ private ServletHolder getRestServlet() {
   }
 
   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 static void fetchScans() throws Exception {
    * 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 3521f314aa..01bd312f41 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.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 @@
 
   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 void span(RemoteSpan s) throws TException {
 
   }
 
-  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 @@ private Connector ensureTraceTableExists(final AccumuloConfiguration conf)
           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 static void main(String[] args) throws Exception {
     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 0eda5c7e5b..a3f636874b 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 @@ protected ClientContext getContextForPeer(AccumuloConfiguration localConf,
     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 49e72aaa93..c6a7d1a27f 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 RateLimiter getWriteLimiter() {
 
   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 52806a2bee..c0e9ba1e6b 100644
--- a/shell/pom.xml
+++ b/shell/pom.xml
@@ -119,11 +119,6 @@
       <artifactId>powermock-api-easymock</artifactId>
       <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>
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 98cd953805..5374c255ad 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.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 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 @@
 
   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 boolean config(String... args) throws IOException {
       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 boolean config(String... args) throws IOException {
     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 void printVerboseInfo() throws IOException {
   }
 
   public String getDefaultPrompt() {
+    Objects.nonNull(connector);
+    Objects.nonNull(connector.info());
     return connector.whoami() + "@" + connector.info().getInstanceName()
         + (getTableName().isEmpty() ? "" : " ") + getTableName() + "> ";
   }
@@ -1226,16 +1161,12 @@ public ConsoleReader getReader() {
 
   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 25aec13e85..1bd8afa4e1 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 File getExecFileVerbose() {
     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 boolean isAuthTimeoutDisabled() {
     return unrecognizedOptions;
   }
 
-  public boolean useSsl() {
-    return useSsl;
-  }
-
   public String getClientConfigFile() {
     if (clientConfigFile == null) {
       List<String> searchPaths = new LinkedList<>();
@@ -303,16 +287,15 @@ public Properties getClientProperties() {
     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 Properties getClientProperties() {
     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 7655c28f26..991dbc63e6 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 int execute(final String fullCommand, final CommandLine cl, final Shell s
       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 2ec9e1a6bb..1b85530698 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 int execute(final String fullCommand, final CommandLine cl, final Shell s
       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 cc29383afa..76acb06b6f 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.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 void testBadArg() throws IOException {
     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 b0e48db9a2..0000000000
--- 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 b28422a93b..089da23b9d 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 void userSetGetRemoveTablePropertyWithPermission() throws Exception {
     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 void userSetGetTablePropertyWithoutPermission() throws Exception {
     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 aef3ce3706..4d18a20e25 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 void testFields() throws Exception {
     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 void testSecurity() throws Exception {
     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 2f037b4be2..246007164a 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 void testPermissions() throws Exception {
     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 3056e81221..a4387b69b6 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.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 @@ private Scanner newOfflineScanner(Connector conn, String tableName, String clone
     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 762fcffdc4..490598f7b7 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 void testConnectorBuilder() throws Exception {
     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 3177a20916..4388c4504e 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.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 @@
   private boolean saslEnabled;
   private String username;
   private String password;
-  private Instance inst;
 
   @Override
   public int defaultTimeoutSeconds() {
@@ -59,8 +57,6 @@ public int defaultTimeoutSeconds() {
   @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 void testConnectorWithDestroyedToken() throws Exception {
     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 void testConnectorWithDestroyedToken() throws Exception {
   @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 28bc628d6d..b84afa5865 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.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 void configureMiniCluster(MiniAccumuloConfigImpl cfg, Configuration hadoo
     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 14f354dddb..0b6033691b 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 void systemPermissionsTest() throws Exception {
     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 void tablePermissionTest() throws Exception {
     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 5a1c598e9e..cd889ca0a7 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.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 int defaultTimeoutSeconds() {
 
   @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 000c62508d..41fedbff27 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.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 void testPermissions() throws Exception {
     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 8e80230a69..533cc2a621 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 @@ private TableState getTableState(String tableName) throws TableNotFoundException
 
     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 fcc670e899..861b38bd51 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.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 @@ private void dropTables(String... tables)
 
     @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 7fecac7d31..fa6aea12bd 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 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 void configure(MiniAccumuloConfigImpl cfg, Configuration hadoopCoreSite)
     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 a5d1f74d57..037ebe9380 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 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 @@
   @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 15968a7ded..7bd8e32d29 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.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 static void main(String[] args) throws Exception {
 
     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 5ba3c618a8..28aca3ca2f 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 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 @@ protected int defaultTimeoutSeconds() {
   @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 c5635ad6f0..a1192c2c2b 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.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 int defaultTimeoutSeconds() {
   @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 045303686f..85f72b36b5 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.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 @@ private MiniClusterConfigurationCallback getConfigCallback(final String name) {
       @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 2057d39015..58c8b08fa4 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.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 void stopExecutor() {
   @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 f389fd9270..b58c11854a 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.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 int defaultTimeoutSeconds() {
   @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");


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message