This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/main by this push:
     new 01a89f1220 Modified cluster.yaml to support num servers per group 
(#5037)
01a89f1220 is described below

commit 01a89f122017bcdefecb6a52b960b7bad4e8613c
Author: Dave Marion <dlmar...@apache.org>
AuthorDate: Sat Nov 9 09:41:47 2024 -0500

    Modified cluster.yaml to support num servers per group (#5037)
    
    Modified cluster.yaml to support specifying number servers
    per group for compactors, sservers, and tservers. This was
    supported previously, but the implementation was different
    and the information was not as tightly coupled in the yaml
    file.
    
    Closes #5032
---
 assemble/bin/accumulo-cluster                      | 172 ++++++--------
 .../core/conf/cluster/ClusterConfigParser.java     |  96 +++++---
 .../core/conf/cluster/ClusterConfigParserTest.java | 248 ++++++++++++---------
 .../cluster/{bad-cluster.yaml => 2_1_cluster.yaml} |  31 +--
 .../{bad-cluster.yaml => bad-group-name.yaml}      |  43 ++--
 .../{bad-cluster.yaml => bad-group-suffix.yaml}    |  39 ++--
 .../{bad-cluster.yaml => bad-server-name.yaml}     |   8 -
 ...s.yaml => cluster-missing-compactor-group.yaml} |  55 ++---
 ...ter.yaml => cluster-missing-tserver-group.yaml} |  33 +--
 .../apache/accumulo/core/conf/cluster/cluster.yaml |  64 +++---
 .../{bad-cluster.yaml => too-many-levels.yaml}     |  40 ++--
 11 files changed, 400 insertions(+), 429 deletions(-)

diff --git a/assemble/bin/accumulo-cluster b/assemble/bin/accumulo-cluster
index 8899f48361..24154dfbbd 100755
--- a/assemble/bin/accumulo-cluster
+++ b/assemble/bin/accumulo-cluster
@@ -143,29 +143,13 @@ function parse_config {
     GC_HOSTS=$manager1
   fi
 
-  if [[ -z $NUM_TSERVERS ]]; then
-    echo "INFO: ${NUM_TSERVERS} tservers will be started per host"
-  fi
-
-  for group in $SSERVER_GROUPS; do
-    var_name="NUM_SSERVERS_${group}"
-    if [[ -n ${!var_name} ]]; then
-      echo "INFO: ${!var_name} scan servers will be started per host for group 
${group}"
-    fi
-  done
-
-  for group in $COMPACTOR_GROUPS; do
-    var_name="NUM_COMPACTORS_${group}"
-    if [[ -n ${!var_name} ]]; then
-      echo "INFO: ${!var_name} compactors will be started per host for group 
${group}"
-    fi
-  done
 }
 
 function control_service() {
   control_cmd="$1"
   host="$2"
   service="$3"
+  servers_per_host="$4"
 
   # Find the group parameter if any
   GROUP_PATTERN="^(compactor.group|sserver.group|tserver.group)=(.*)$"
@@ -177,10 +161,7 @@ function control_service() {
   done
 
   local last_instance_id
-  last_instance_id=1
-  [[ $service == "tserver" ]] && last_instance_id=${NUM_TSERVERS:-1}
-  [[ $service == "sserver" ]] && last_instance_id=${NUM_SSERVERS:-1}
-  [[ $service == "compactor" ]] && last_instance_id=${NUM_COMPACTORS:-1}
+  last_instance_id=${servers_per_host:-1}
 
   for ((inst_id = 1; inst_id <= last_instance_id; inst_id++)); do
     ACCUMULO_SERVICE_INSTANCE="_${group}_${inst_id}"
@@ -190,14 +171,14 @@ function control_service() {
       # The server processes take arguments using "-o". Always add the 
"general.process.bind.addr" argument
       # using the value of $host
       #
-      if [[ $# -gt 3 ]]; then
-        debugAndRun ACCUMULO_SERVICE_INSTANCE="${ACCUMULO_SERVICE_INSTANCE}" 
"${bin}/accumulo-service" "$service" "$control_cmd" "-o" 
"general.process.bind.addr=$host" "${@:4}"
+      if [[ $# -gt 4 ]]; then
+        debugAndRun ACCUMULO_SERVICE_INSTANCE="${ACCUMULO_SERVICE_INSTANCE}" 
"${bin}/accumulo-service" "$service" "$control_cmd" "-o" 
"general.process.bind.addr=$host" "${@:5}"
       else
         debugAndRun ACCUMULO_SERVICE_INSTANCE="${ACCUMULO_SERVICE_INSTANCE}" 
"${bin}/accumulo-service" "$service" "$control_cmd" "-o" 
"general.process.bind.addr=$host"
       fi
     else
-      if [[ $# -gt 3 ]]; then
-        EXTRA_ARGS="${*:4}"
+      if [[ $# -gt 4 ]]; then
+        EXTRA_ARGS="${*:5}"
         debugAndRun "$SSH" "$host" "bash -c 
'ACCUMULO_SERVICE_INSTANCE=${ACCUMULO_SERVICE_INSTANCE} ${bin}/accumulo-service 
\"$service\" \"$control_cmd\" \"-o\" \"general.process.bind.addr=$host\" 
$EXTRA_ARGS '"
       else
         debugAndRun "$SSH" "$host" "bash -c 
'ACCUMULO_SERVICE_INSTANCE=${ACCUMULO_SERVICE_INSTANCE} ${bin}/accumulo-service 
\"$service\" \"$control_cmd\" \"-o\" \"general.process.bind.addr=$host\"'"
@@ -221,12 +202,11 @@ function start_compactors() {
       echo "Only starting servers for group: ${groups}"
     fi
     for group in $groups; do
-      var_name="NUM_COMPACTORS_${group}"
-      [[ -n ${!var_name} ]] && NUM_COMPACTORS=${!var_name}
       Q="COMPACTOR_HOSTS_${group}"
+      S="COMPACTORS_PER_HOST_${group}"
       if [[ -n ${!Q} ]]; then
         for compactor in ${!Q}; do
-          start_service "$compactor" compactor "-o" "compactor.group=$group"
+          start_service "$compactor" compactor "${!S}" "-o" 
"compactor.group=$group"
         done
       else
         echo "${group} is not a valid compactor group ...exiting"
@@ -246,12 +226,11 @@ function stop_compactors() {
       echo "Only stopping servers for group: ${groups}"
     fi
     for group in $groups; do
-      var_name="NUM_COMPACTORS_${group}"
-      [[ -n ${!var_name} ]] && NUM_COMPACTORS=${!var_name}
       Q="COMPACTOR_HOSTS_${group}"
+      S="COMPACTORS_PER_HOST_${group}"
       if [[ -n ${!Q} ]]; then
         for compactor in ${!Q}; do
-          stop_service "$compactor" compactor "-o" "compactor.group=$group"
+          stop_service "$compactor" compactor "${!S}" "-o" 
"compactor.group=$group"
         done
       else
         echo "${group} is not a valid compaction group ...exiting"
@@ -271,12 +250,11 @@ function start_sservers() {
       echo "Only starting servers for group: ${groups}"
     fi
     for group in $groups; do
-      var_name="NUM_SSERVERS_${group}"
-      [[ -n ${!var_name} ]] && NUM_SSERVERS=${!var_name}
       G="SSERVER_HOSTS_${group}"
+      S="SSERVERS_PER_HOST_${group}"
       if [[ -n ${!G} ]]; then
         for sserver in ${!G}; do
-          start_service "$sserver" sserver "-o" "sserver.group=$group"
+          start_service "$sserver" sserver "${!S}" "-o" "sserver.group=$group"
         done
       else
         echo "${group} is not a valid resource group ...exiting"
@@ -296,12 +274,11 @@ function stop_sservers() {
       echo "Only stopping servers for group: ${groups}"
     fi
     for group in $groups; do
-      var_name="NUM_SSERVERS_${group}"
-      [[ -n ${!var_name} ]] && NUM_SSERVERS=${!var_name}
       G="SSERVER_HOSTS_${group}"
+      S="SSERVERS_PER_HOST_${group}"
       if [[ -n ${!G} ]]; then
         for sserver in ${!G}; do
-          stop_service "$sserver" sserver "-o" "sserver.group=$group"
+          stop_service "$sserver" sserver "${!S}" "-o" "sserver.group=$group"
         done
       else
         echo "${group} is not a valid resource group ...exiting"
@@ -316,9 +293,10 @@ function start_tservers() {
     echo "Starting tablet servers for group $group"
     count=1
     G="TSERVER_HOSTS_${group}"
+    S="TSERVERS_PER_HOST_${group}"
     for tserver in ${!G}; do
       echo -n "."
-      start_service "$tserver" tserver "-o" "tserver.group=$group"
+      start_service "$tserver" tserver "${!S}" "-o" "tserver.group=$group"
       if ((++count % 72 == 0)); then
         echo
         wait
@@ -336,34 +314,32 @@ function start_all() {
   fi
 
   for manager in $MANAGER_HOSTS; do
-    start_service "$manager" manager
+    start_service "$manager" manager "1"
   done
 
   for gc in $GC_HOSTS; do
-    start_service "$gc" gc
+    start_service "$gc" gc "1"
   done
 
   for monitor in $MONITOR_HOSTS; do
-    start_service "$monitor" monitor
+    start_service "$monitor" monitor "1"
   done
 
   for group in $SSERVER_GROUPS; do
     echo "Starting scan servers for group $group"
-    var_name="NUM_SSERVERS_${group}"
-    [[ -n ${!var_name} ]] && NUM_SSERVERS=${!var_name}
     G="SSERVER_HOSTS_${group}"
+    S="SSERVERS_PER_HOST_${group}"
     for sserver in ${!G}; do
-      start_service "$sserver" sserver "-o" "sserver.group=$group"
+      start_service "$sserver" sserver "${!S}" "-o" "sserver.group=$group"
     done
   done
 
   for group in $COMPACTOR_GROUPS; do
-    var_name="NUM_COMPACTORS_${group}"
-    [[ -n ${!var_name} ]] && NUM_COMPACTORS=${!var_name}
     echo "Starting compactors for group $group"
     Q="COMPACTOR_HOSTS_${group}"
+    S="COMPACTORS_PER_HOST_${group}"
     for compactor in ${!Q}; do
-      start_service "$compactor" compactor "-o" "compactor.group=$group"
+      start_service "$compactor" compactor "${!S}" "-o" 
"compactor.group=$group"
     done
   done
 
@@ -377,9 +353,10 @@ function start_here() {
     echo "Starting tablet servers for group $group"
     for host in $local_hosts; do
       G="TSERVER_HOSTS_${group}"
+      S="TSERVERS_PER_HOST_${group}"
       for tserver in ${!G}; do
         if echo "$tserver" | grep -q "^${host}\$"; then
-          start_service "$tserver" tserver "-o" "tserver.group=$group"
+          start_service "$tserver" tserver "${!S}" "-o" "tserver.group=$group"
         fi
       done
     done
@@ -388,7 +365,7 @@ function start_here() {
   for host in $local_hosts; do
     for manager in $MANAGER_HOSTS; do
       if echo "$manager" | grep -q "^${host}\$"; then
-        start_service "$host" manager
+        start_service "$host" manager "1"
         break
       fi
     done
@@ -397,7 +374,7 @@ function start_here() {
   for host in $local_hosts; do
     for gc in $GC_HOSTS; do
       if echo "$gc" | grep -q "^${host}\$"; then
-        start_service "$host" gc
+        start_service "$host" gc "1"
         break
       fi
     done
@@ -406,7 +383,7 @@ function start_here() {
   for host in $local_hosts; do
     for monitor in $MONITOR_HOSTS; do
       if echo "$monitor" | grep -q "^${host}\$"; then
-        start_service "$host" monitor
+        start_service "$host" monitor "1"
         break
       fi
     done
@@ -414,13 +391,12 @@ function start_here() {
 
   for group in $SSERVER_GROUPS; do
     echo "Starting scan servers for group $group"
-    var_name="NUM_SSERVERS_${group}"
-    [[ -n ${!var_name} ]] && NUM_SSERVERS=${!var_name}
     for host in $local_hosts; do
       G="SSERVER_HOSTS_${group}"
+      S="SSERVERS_PER_HOST_${group}"
       for sserver in ${!G}; do
         if echo "$sserver" | grep -q "^${host}\$"; then
-          start_service "$sserver" sserver "-o" "sserver.group=$group"
+          start_service "$sserver" sserver "${!S}" "-o" "sserver.group=$group"
         fi
       done
     done
@@ -429,12 +405,11 @@ function start_here() {
   for group in $COMPACTOR_GROUPS; do
     echo "Starting compactors for group $group"
     for host in $local_hosts; do
-      var_name="NUM_COMPACTORS_${group}"
-      [[ -n ${!var_name} ]] && NUM_COMPACTORS=${!var_name}
       Q="COMPACTOR_HOSTS_${group}"
+      S="COMPACTORS_PER_HOST_${group}"
       for compactor in ${!Q}; do
         if echo "$compactor" | grep -q "^${host}\$"; then
-          start_service "$compactor" compactor "-o" "compactor.group=$group"
+          start_service "$compactor" compactor "${!S}" "-o" 
"compactor.group=$group"
         fi
       done
     done
@@ -461,8 +436,9 @@ function stop_tservers() {
   for group in $TSERVER_GROUPS; do
     echo "Stopping tablet servers for group $group"
     G="TSERVER_HOSTS_${group}"
+    S="TSERVERS_PER_HOST_${group}"
     for tserver in ${!G}; do
-      stop_service "$tserver" tserver &
+      stop_service "$tserver" tserver "${!S}" "-o" "tserver.group=$group" &
     done
   done
 
@@ -471,8 +447,9 @@ function stop_tservers() {
   echo "Stopping unresponsive tablet servers hard (if any)..."
   for group in $TSERVER_GROUPS; do
     G="TSERVER_HOSTS_${group}"
+    S="TSERVERS_PER_HOST_${group}"
     for tserver in ${!G}; do
-      kill_service "$tserver" tserver &
+      kill_service "$tserver" tserver "${!S}" "-o" "tserver.group=$group" &
     done
   done
 
@@ -486,42 +463,41 @@ function kill_all() {
   echo "Killing Accumulo cluster..."
 
   for manager in $MANAGER_HOSTS; do
-    kill_service "$manager" manager
+    kill_service "$manager" manager "1"
   done
 
   for gc in $GC_HOSTS; do
-    kill_service "$gc" gc
+    kill_service "$gc" gc "1"
   done
 
   for monitor in $MONITOR_HOSTS; do
-    kill_service "$monitor" monitor
+    kill_service "$monitor" monitor "1"
   done
 
   for group in $SSERVER_GROUPS; do
     echo "Killing scan servers for group $group"
-    var_name="NUM_SSERVERS_${group}"
-    [[ -n ${!var_name} ]] && NUM_SSERVERS=${!var_name}
     G="SSERVER_HOSTS_${group}"
+    S="SSERVERS_PER_HOST_${group}"
     for sserver in ${!G}; do
-      kill_service "$sserver" sserver
+      kill_service "$sserver" sserver "${!S}" "-o" "sserver.group=$group"
     done
   done
 
   for group in $TSERVER_GROUPS; do
     echo "Killing tablet servers for group $group"
     G="TSERVER_HOSTS_${group}"
+    S="TSERVERS_PER_HOST_${group}"
     for tserver in ${!G}; do
-      kill_service "$tserver" tserver
+      kill_service "$tserver" tserver "${!S}" "-o" "tserver.group=$group"
     done
   done
 
   for group in $COMPACTOR_GROUPS; do
     echo "Killing compactors for group $group"
-    var_name="NUM_COMPACTORS_${group}"
-    [[ -n ${!var_name} ]] && NUM_COMPACTORS=${!var_name}
     Q="COMPACTOR_HOSTS_${group}"
+    S="COMPACTORS_PER_HOST_${group}"
     for compactor in ${!Q}; do
-      kill_service "$compactor" compactor
+      kill_service "$compactor" compactor "${!S}" "-o" "compactor.group=$group"
     done
   done
 
@@ -551,34 +527,32 @@ function stop_all() {
   for end_cmd in "stop" "kill"; do
 
     for manager in $MANAGER_HOSTS; do
-      end_service $end_cmd "$manager" manager
+      end_service $end_cmd "$manager" manager "1"
     done
 
     for gc in $GC_HOSTS; do
-      end_service $end_cmd "$gc" gc
+      end_service $end_cmd "$gc" gc "1"
     done
 
     for monitor in $MONITOR_HOSTS; do
-      end_service $end_cmd "$monitor" monitor
+      end_service $end_cmd "$monitor" monitor "1"
     done
 
     for group in $SSERVER_GROUPS; do
       echo "Stopping scan servers for group $group"
-      var_name="NUM_SSERVERS_${group}"
-      [[ -n ${!var_name} ]] && NUM_SSERVERS=${!var_name}
       G="SSERVER_HOSTS_${group}"
+      S="SSERVERS_PER_HOST_${group}"
       for sserver in ${!G}; do
-        end_service $end_cmd "$sserver" sserver
+        end_service $end_cmd "$sserver" sserver "${!S}" "-o" 
"sserver.group=$group"
       done
     done
 
     for group in $COMPACTOR_GROUPS; do
       echo "Stopping compactors for group $group"
-      var_name="NUM_COMPACTORS_${group}"
-      [[ -n ${!var_name} ]] && NUM_COMPACTORS=${!var_name}
       Q="COMPACTOR_HOSTS_${group}"
+      S="COMPACTORS_PER_HOST_${group}"
       for compactor in ${!Q}; do
-        end_service $end_cmd "$compactor" compactor
+        end_service $end_cmd "$compactor" compactor "${!S}" "-o" 
"compactor.group=$group"
       done
     done
 
@@ -623,28 +597,27 @@ function stop_here() {
   for host in "${hosts_to_check[@]}"; do
     for end_cmd in "stop" "kill"; do
       for svc in gc manager monitor; do
-        end_service $end_cmd "$host" $svc
+        end_service $end_cmd "$host" $svc "1"
       done
       for group in $TSERVER_GROUPS; do
         G="TSERVER_HOSTS_${group}"
+        S="TSERVERS_PER_HOST_${group}"
         for tserver in ${!G}; do
-          end_service $end_cmd "$tserver" tserver
+          end_service $end_cmd "$tserver" tserver "${!S}" "-o" 
"tserver.group=$group"
         done
       done
       for group in $SSERVER_GROUPS; do
-        var_name="NUM_SSERVERS_${group}"
-        [[ -n ${!var_name} ]] && NUM_SSERVERS=${!var_name}
         G="SSERVER_HOSTS_${group}"
+        S="SSERVERS_PER_HOST_${group}"
         for sserver in ${!G}; do
-          end_service $end_cmd "$sserver" sserver
+          end_service $end_cmd "$sserver" sserver "${!S}" "-o" 
"sserver.group=$group"
         done
       done
       for group in $COMPACTOR_GROUPS; do
-        var_name="NUM_COMPACTORS_${group}"
-        [[ -n ${!var_name} ]] && NUM_COMPACTORS=${!var_name}
         Q="COMPACTOR_HOSTS_${group}"
+        S="COMPACTORS_PER_HOST_${group}"
         for compactor in ${!Q}; do
-          end_service $end_cmd "$host" compactor
+          end_service $end_cmd "$host" compactor "${!S}" "-o" 
"compactor.group=$group"
         done
       done
     done
@@ -704,30 +677,21 @@ gc:
 
 tserver:
   default:
-    - localhost
+    servers_per_host: 1
+    hosts:
+      - localhost
 
 compactor:
   default:
-    - localhost
+    servers_per_host: 1
+    hosts:
+      - localhost
 
 sserver:
   default:
-    - localhost
-
-#
-# The following are used by the accumulo-cluster script to determine how many 
servers
-# to start on each host. If the following variables are not set, then they 
default to 1.
-# If the environment variable NUM_TSERVERS is set when running accumulo_cluster
-# then its value will override what is set in this file for tservers_per_host. 
Likewise if
-# NUM_SSERVERS or NUM_COMPACTORS are set then it will override 
sservers_per_host and
-# compactors_per_host.
-#
-tservers_per_host: 1
-#sservers_per_host: 
-# - default: 1
-#compactors_per_host:
-# - q1: 1
-# - q2: 1 
+    servers_per_host: 1
+    hosts:
+      - localhost
 
 EOF
       ;;
diff --git 
a/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java
 
b/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java
index 016d5daa80..ae6042aaee 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParser.java
@@ -29,12 +29,16 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Predicate;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.StringUtils;
 import org.yaml.snakeyaml.Yaml;
 
+import com.google.common.base.Preconditions;
+
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 public class ClusterConfigParser {
@@ -52,23 +56,22 @@ public class ClusterConfigParser {
 
   private static final String PROPERTY_FORMAT = "%s=\"%s\"%n";
   private static final String COMPACTOR_PREFIX = "compactor.";
-  private static final String COMPACTORS_PER_HOST_PREFIX = 
"compactors_per_host.";
   private static final String GC_KEY = "gc";
   private static final String MANAGER_KEY = "manager";
   private static final String MONITOR_KEY = "monitor";
   private static final String SSERVER_PREFIX = "sserver.";
-  private static final String SSERVERS_PER_HOST_PREFIX = "sservers_per_host.";
   private static final String TSERVER_PREFIX = "tserver.";
-  private static final String TSERVERS_PER_HOST_KEY = "tservers_per_host";
+
+  private static final String HOSTS_SUFFIX = ".hosts";
+  private static final String SERVERS_PER_HOST_SUFFIX = ".servers_per_host";
 
   private static final String[] UNGROUPED_SECTIONS =
       new String[] {MANAGER_KEY, MONITOR_KEY, GC_KEY};
 
-  private static final Set<String> VALID_CONFIG_KEYS =
-      Set.of(MANAGER_KEY, MONITOR_KEY, GC_KEY, TSERVERS_PER_HOST_KEY);
+  private static final Set<String> VALID_CONFIG_KEYS = Set.of(MANAGER_KEY, 
MONITOR_KEY, GC_KEY);
 
-  private static final Set<String> VALID_CONFIG_PREFIXES = 
Set.of(COMPACTOR_PREFIX, SSERVER_PREFIX,
-      TSERVER_PREFIX, SSERVERS_PER_HOST_PREFIX, COMPACTORS_PER_HOST_PREFIX);
+  private static final Set<String> VALID_CONFIG_PREFIXES =
+      Set.of(COMPACTOR_PREFIX, SSERVER_PREFIX, TSERVER_PREFIX);
 
   private static final Predicate<String> VALID_CONFIG_SECTIONS =
       section -> VALID_CONFIG_KEYS.contains(section)
@@ -117,6 +120,30 @@ public class ClusterConfigParser {
     }
   }
 
+  private static List<String> parseGroup(Map<String,String> config, String 
prefix) {
+    Preconditions.checkArgument(prefix.equals(COMPACTOR_PREFIX) || 
prefix.equals(SSERVER_PREFIX)
+        || prefix.equals(TSERVER_PREFIX));
+    List<String> groups = config.keySet().stream().filter(k -> 
k.startsWith(prefix)).map(k -> {
+      int periods = StringUtils.countMatches(k, '.');
+      if (periods == 1) {
+        return k.substring(prefix.length());
+      } else if (periods == 2) {
+        if (k.endsWith(HOSTS_SUFFIX)) {
+          return k.substring(prefix.length(), k.indexOf(HOSTS_SUFFIX));
+        } else if (k.endsWith(SERVERS_PER_HOST_SUFFIX)) {
+          return k.substring(prefix.length(), 
k.indexOf(SERVERS_PER_HOST_SUFFIX));
+        } else {
+          throw new IllegalArgumentException("Unknown group suffix for: " + k 
+ ". Only "
+              + HOSTS_SUFFIX + " or " + SERVERS_PER_HOST_SUFFIX + " are 
allowed.");
+        }
+      } else {
+        throw new IllegalArgumentException("Malformed configuration, has too 
many levels: " + k);
+      }
+    }).sorted().distinct().collect(Collectors.toList());
+    validateGroupNames(groups);
+    return groups;
+  }
+
   public static void outputShellVariables(Map<String,String> config, 
PrintStream out) {
 
     // find invalid config sections and point the user to the first one
@@ -136,50 +163,55 @@ public class ClusterConfigParser {
       }
     }
 
-    List<String> compactorGroups =
-        config.keySet().stream().filter(k -> k.startsWith(COMPACTOR_PREFIX))
-            .map(k -> 
k.substring(COMPACTOR_PREFIX.length())).sorted().collect(Collectors.toList());
-    validateGroupNames(compactorGroups);
-
+    List<String> compactorGroups = parseGroup(config, COMPACTOR_PREFIX);
+    if (compactorGroups.isEmpty()) {
+      throw new IllegalArgumentException(
+          "No compactor groups found, at least one compactor group is required 
to compact the system tables.");
+    }
     if (!compactorGroups.isEmpty()) {
       out.printf(PROPERTY_FORMAT, "COMPACTOR_GROUPS",
           compactorGroups.stream().collect(Collectors.joining(" ")));
       for (String group : compactorGroups) {
         out.printf(PROPERTY_FORMAT, "COMPACTOR_HOSTS_" + group,
-            config.get(COMPACTOR_PREFIX + group));
-        String numCompactors = config.getOrDefault("compactors_per_host." + 
group, "1");
-        out.printf(PROPERTY_FORMAT, "NUM_COMPACTORS_" + group, numCompactors);
+            config.get(COMPACTOR_PREFIX + group + HOSTS_SUFFIX));
+        String numCompactors =
+            config.getOrDefault(COMPACTOR_PREFIX + group + 
SERVERS_PER_HOST_SUFFIX, "1");
+        out.printf(PROPERTY_FORMAT, "COMPACTORS_PER_HOST_" + group, 
numCompactors);
       }
     }
 
-    List<String> sserverGroups = config.keySet().stream().filter(k -> 
k.startsWith(SSERVER_PREFIX))
-        .map(k -> 
k.substring(SSERVER_PREFIX.length())).sorted().collect(Collectors.toList());
-    validateGroupNames(sserverGroups);
-
+    List<String> sserverGroups = parseGroup(config, SSERVER_PREFIX);
     if (!sserverGroups.isEmpty()) {
       out.printf(PROPERTY_FORMAT, "SSERVER_GROUPS",
           sserverGroups.stream().collect(Collectors.joining(" ")));
       sserverGroups.forEach(ssg -> out.printf(PROPERTY_FORMAT, 
"SSERVER_HOSTS_" + ssg,
-          config.get(SSERVER_PREFIX + ssg)));
-      sserverGroups.forEach(ssg -> out.printf(PROPERTY_FORMAT, "NUM_SSERVERS_" 
+ ssg,
-          config.getOrDefault("sservers_per_host." + ssg, "1")));
-
+          config.get(SSERVER_PREFIX + ssg + HOSTS_SUFFIX)));
+      sserverGroups.forEach(ssg -> out.printf(PROPERTY_FORMAT, 
"SSERVERS_PER_HOST_" + ssg,
+          config.getOrDefault(SSERVER_PREFIX + ssg + SERVERS_PER_HOST_SUFFIX, 
"1")));
     }
 
-    List<String> tserverGroups = config.keySet().stream().filter(k -> 
k.startsWith(TSERVER_PREFIX))
-        .map(k -> 
k.substring(TSERVER_PREFIX.length())).sorted().collect(Collectors.toList());
-    validateGroupNames(tserverGroups);
-
+    List<String> tserverGroups = parseGroup(config, TSERVER_PREFIX);
+    if (tserverGroups.isEmpty()) {
+      throw new IllegalArgumentException(
+          "No tserver groups found, at least one tserver group is required to 
host the system tables.");
+    }
+    AtomicBoolean foundTServer = new AtomicBoolean(false);
     if (!tserverGroups.isEmpty()) {
       out.printf(PROPERTY_FORMAT, "TSERVER_GROUPS",
           tserverGroups.stream().collect(Collectors.joining(" ")));
-      tserverGroups.forEach(tsg -> out.printf(PROPERTY_FORMAT, 
"TSERVER_HOSTS_" + tsg,
-          config.get(TSERVER_PREFIX + tsg)));
+      tserverGroups.forEach(tsg -> {
+        String hosts = config.get(TSERVER_PREFIX + tsg + HOSTS_SUFFIX);
+        foundTServer.compareAndSet(false, hosts != null && !hosts.isEmpty());
+        out.printf(PROPERTY_FORMAT, "TSERVER_HOSTS_" + tsg, hosts);
+      });
+      tserverGroups.forEach(tsg -> out.printf(PROPERTY_FORMAT, 
"TSERVERS_PER_HOST_" + tsg,
+          config.getOrDefault(TSERVER_PREFIX + tsg + SERVERS_PER_HOST_SUFFIX, 
"1")));
     }
 
-    String numTservers = config.getOrDefault("tservers_per_host", "1");
-    out.print("NUM_TSERVERS=\"${NUM_TSERVERS:=" + numTservers + "}\"\n");
-
+    if (!foundTServer.get()) {
+      throw new IllegalArgumentException(
+          "Tablet Server group found, but no hosts. Check the format of your 
cluster.yaml file.");
+    }
     out.flush();
   }
 
diff --git 
a/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java
 
b/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java
index 4793201355..5ba3c47678 100644
--- 
a/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java
+++ 
b/core/src/test/java/org/apache/accumulo/core/conf/cluster/ClusterConfigParserTest.java
@@ -33,9 +33,9 @@ import java.io.PrintStream;
 import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 import java.util.function.Function;
 
 import org.junit.jupiter.api.Test;
@@ -57,73 +57,54 @@ public class ClusterConfigParserTest {
 
     Map<String,String> contents =
         ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
-    assertEquals(4, contents.size());
+    assertEquals(14, contents.size());
     assertTrue(contents.containsKey("manager"));
     assertEquals("localhost1 localhost2", contents.get("manager"));
     assertTrue(contents.containsKey("monitor"));
     assertEquals("localhost1 localhost2", contents.get("monitor"));
     assertTrue(contents.containsKey("gc"));
     assertEquals("localhost", contents.get("gc"));
-    assertFalse(contents.containsKey("tserver"));
-    assertTrue(contents.containsKey("tserver.default"));
-    assertEquals("localhost1 localhost2 localhost3 localhost4", 
contents.get("tserver.default"));
+
     assertFalse(contents.containsKey("compactor"));
-    assertFalse(contents.containsKey("compactor.queue"));
     assertFalse(contents.containsKey("compactor.q1"));
     assertFalse(contents.containsKey("compactor.q2"));
-    assertFalse(contents.containsKey("tservers_per_host"));
-    assertFalse(contents.containsKey("sservers_per_host"));
-    assertFalse(contents.containsKey("compactors_per_host"));
-  }
-
-  @Test
-  public void testParseWithOptionalComponents() throws Exception {
-    URL configFile = ClusterConfigParserTest.class
-        
.getResource("/org/apache/accumulo/core/conf/cluster/cluster-with-optional-services.yaml");
-    assertNotNull(configFile);
-
-    Map<String,String> contents =
-        ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
-
-    assertEquals(17, contents.size());
+    assertFalse(contents.containsKey("compactor.q1.servers_per_host"));
+    assertTrue(contents.containsKey("compactor.q1.hosts"));
+    assertEquals("localhost1 localhost2", contents.get("compactor.q1.hosts"));
+    assertTrue(contents.containsKey("compactor.q2.servers_per_host"));
+    assertEquals("4", contents.get("compactor.q2.servers_per_host"));
+    assertTrue(contents.containsKey("compactor.q2.hosts"));
+    assertEquals("localhost3 localhost4", contents.get("compactor.q2.hosts"));
 
-    assertTrue(contents.containsKey("manager"));
-    assertEquals("localhost1 localhost2", contents.get("manager"));
-    assertTrue(contents.containsKey("monitor"));
-    assertEquals("localhost1 localhost2", contents.get("monitor"));
-    assertTrue(contents.containsKey("gc"));
-    assertEquals("localhost", contents.get("gc"));
-    assertFalse(contents.containsKey("compactor"));
-    assertTrue(contents.containsKey("compactor.q1"));
-    assertEquals("localhost1 localhost2", contents.get("compactor.q1"));
-    assertTrue(contents.containsKey("compactor.q2"));
-    assertEquals("localhost3 localhost4", contents.get("compactor.q2"));
     assertFalse(contents.containsKey("sserver"));
-    assertTrue(contents.containsKey("sserver.default"));
-    assertEquals("localhost1 localhost2", contents.get("sserver.default"));
-    assertTrue(contents.containsKey("sserver.highmem"));
-    assertEquals("hmvm1 hmvm2 hmvm3", contents.get("sserver.highmem"));
-    assertTrue(contents.containsKey("sserver.cheap"));
-    assertEquals("burstyvm1 burstyvm2", contents.get("sserver.cheap"));
+    assertFalse(contents.containsKey("sserver.default"));
+    assertTrue(contents.containsKey("sserver.default.servers_per_host"));
+    assertEquals("2", contents.get("sserver.default.servers_per_host"));
+    assertTrue(contents.containsKey("sserver.default.hosts"));
+    assertEquals("localhost1 localhost2", 
contents.get("sserver.default.hosts"));
+    assertFalse(contents.containsKey("sserver.highmem"));
+    assertTrue(contents.containsKey("sserver.highmem.servers_per_host"));
+    assertEquals("1", contents.get("sserver.highmem.servers_per_host"));
+    assertTrue(contents.containsKey("sserver.highmem.hosts"));
+    assertEquals("hmvm1 hmvm2 hmvm3", contents.get("sserver.highmem.hosts"));
+    assertFalse(contents.containsKey("sserver.cheap"));
+    assertTrue(contents.containsKey("sserver.cheap.servers_per_host"));
+    assertEquals("3", contents.get("sserver.cheap.servers_per_host"));
+    assertTrue(contents.containsKey("sserver.cheap.hosts"));
+    assertEquals("burstyvm1 burstyvm2", contents.get("sserver.cheap.hosts"));
+
     assertFalse(contents.containsKey("tserver"));
-    assertTrue(contents.containsKey("tserver.default"));
-    assertEquals("localhost1 localhost2", contents.get("tserver.default"));
-    assertTrue(contents.containsKey("tserver.highmem"));
-    assertEquals("localhost3 localhost4", contents.get("tserver.highmem"));
-    assertTrue(contents.containsKey("tserver.cheap"));
-    assertEquals("localhost5 localhost6", contents.get("tserver.cheap"));
-    assertTrue(contents.containsKey("tservers_per_host"));
-    assertEquals("2", contents.get("tservers_per_host"));
-    assertTrue(contents.containsKey("sservers_per_host.default"));
-    assertEquals("1", contents.get("sservers_per_host.default"));
-    assertTrue(contents.containsKey("sservers_per_host.highmem"));
-    assertEquals("2", contents.get("sservers_per_host.highmem"));
-    assertTrue(contents.containsKey("sservers_per_host.cheap"));
-    assertEquals("3", contents.get("sservers_per_host.cheap"));
-    assertTrue(contents.containsKey("compactors_per_host.q1"));
-    assertEquals("3", contents.get("compactors_per_host.q1"));
-    assertTrue(contents.containsKey("compactors_per_host.q2"));
-    assertEquals("1", contents.get("compactors_per_host.q2"));
+    assertFalse(contents.containsKey("tserver.default"));
+    assertTrue(contents.containsKey("tserver.default.servers_per_host"));
+    assertEquals("2", contents.get("tserver.default.servers_per_host"));
+    assertTrue(contents.containsKey("tserver.default.hosts"));
+    assertEquals("localhost1 localhost2 localhost3 localhost4",
+        contents.get("tserver.default.hosts"));
+    assertFalse(contents.containsKey("compactor"));
+    assertFalse(contents.containsKey("compactor.queue"));
+    assertFalse(contents.containsKey("tservers_per_host"));
+    assertFalse(contents.containsKey("sservers_per_host"));
+    assertFalse(contents.containsKey("compactors_per_host"));
   }
 
   @Test
@@ -175,17 +156,32 @@ public class ClusterConfigParserTest {
 
     final File f = outputConfigFunction.apply(configFile);
 
-    Map<String,String> expected = new HashMap<>();
+    Map<String,String> expected = new TreeMap<>();
     expected.put("MANAGER_HOSTS", "localhost1 localhost2");
     expected.put("MONITOR_HOSTS", "localhost1 localhost2");
     expected.put("GC_HOSTS", "localhost");
+
+    expected.put("COMPACTOR_GROUPS", "q1 q2");
+    expected.put("COMPACTORS_PER_HOST_q1", "1");
+    expected.put("COMPACTOR_HOSTS_q1", "localhost1 localhost2");
+    expected.put("COMPACTORS_PER_HOST_q2", "4");
+    expected.put("COMPACTOR_HOSTS_q2", "localhost3 localhost4");
+
+    expected.put("SSERVER_GROUPS", "cheap default highmem");
+    expected.put("SSERVERS_PER_HOST_default", "2");
+    expected.put("SSERVER_HOSTS_default", "localhost1 localhost2");
+    expected.put("SSERVERS_PER_HOST_highmem", "1");
+    expected.put("SSERVER_HOSTS_highmem", "hmvm1 hmvm2 hmvm3");
+    expected.put("SSERVERS_PER_HOST_cheap", "3");
+    expected.put("SSERVER_HOSTS_cheap", "burstyvm1 burstyvm2");
+
     expected.put("TSERVER_GROUPS", "default");
+    expected.put("TSERVERS_PER_HOST_default", "2");
     expected.put("TSERVER_HOSTS_default", "localhost1 localhost2 localhost3 
localhost4");
-    expected.put("NUM_TSERVERS", "${NUM_TSERVERS:=1}");
 
     expected.replaceAll((k, v) -> '"' + v + '"');
 
-    Map<String,String> actual = new HashMap<>();
+    Map<String,String> actual = new TreeMap<>();
     try (BufferedReader rdr = Files.newBufferedReader(Paths.get(f.toURI()))) {
       rdr.lines().forEach(l -> {
         String[] props = l.split("=", 2);
@@ -197,75 +193,105 @@ public class ClusterConfigParserTest {
   }
 
   @Test
-  public void testShellOutputWithOptionalComponents() throws Exception {
-
-    String userDir = System.getProperty("user.dir");
-    String targetDir = "target";
-    File dir = new File(userDir, targetDir);
-    if (!dir.exists()) {
-      if (!dir.mkdirs()) {
-        fail("Unable to make directory ${user.dir}/target");
-      }
+  public void testFileWithUnknownSections() throws Exception {
+    URL configFile = ClusterConfigParserTest.class
+        
.getResource("/org/apache/accumulo/core/conf/cluster/bad-server-name.yaml");
+    assertNotNull(configFile);
+
+    Map<String,String> contents =
+        ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
+
+    try (var baos = new ByteArrayOutputStream(); var ps = new 
PrintStream(baos)) {
+      var exception = assertThrows(IllegalArgumentException.class,
+          () -> ClusterConfigParser.outputShellVariables(contents, ps));
+      assertTrue(exception.getMessage().contains("vserver"));
     }
-    File f = new File(dir, 
"ClusterConfigParserTest_testShellOutputWithOptionalComponents");
-    if (!f.createNewFile()) {
-      fail("Unable to create file in ${user.dir}/target");
+  }
+
+  @Test
+  public void testFileWithInvalidGroupName() throws Exception {
+    URL configFile = ClusterConfigParserTest.class
+        
.getResource("/org/apache/accumulo/core/conf/cluster/bad-group-name.yaml");
+    assertNotNull(configFile);
+
+    Map<String,String> contents =
+        ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
+
+    try (var baos = new ByteArrayOutputStream(); var ps = new 
PrintStream(baos)) {
+      var exception = assertThrows(RuntimeException.class,
+          () -> ClusterConfigParser.outputShellVariables(contents, ps));
+      assertTrue(exception.getMessage().contains("bad-group-name"));
     }
-    f.deleteOnExit();
+  }
+
+  @Test
+  public void testFileWithInvalidSuffix() throws Exception {
+    URL configFile = ClusterConfigParserTest.class
+        
.getResource("/org/apache/accumulo/core/conf/cluster/bad-group-suffix.yaml");
+    assertNotNull(configFile);
 
-    PrintStream ps = new PrintStream(f);
+    Map<String,String> contents =
+        ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
 
+    try (var baos = new ByteArrayOutputStream(); var ps = new 
PrintStream(baos)) {
+      var exception = assertThrows(IllegalArgumentException.class,
+          () -> ClusterConfigParser.outputShellVariables(contents, ps));
+      assertTrue(exception.getMessage().contains("servers_per_hosts"));
+    }
+  }
+
+  @Test
+  public void testFileWithTooManyLevels() throws Exception {
     URL configFile = ClusterConfigParserTest.class
-        
.getResource("/org/apache/accumulo/core/conf/cluster/cluster-with-optional-services.yaml");
+        
.getResource("/org/apache/accumulo/core/conf/cluster/too-many-levels.yaml");
     assertNotNull(configFile);
 
     Map<String,String> contents =
         ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
 
-    ClusterConfigParser.outputShellVariables(contents, ps);
-    ps.close();
+    try (var baos = new ByteArrayOutputStream(); var ps = new 
PrintStream(baos)) {
+      var exception = assertThrows(IllegalArgumentException.class,
+          () -> ClusterConfigParser.outputShellVariables(contents, ps));
+      assertTrue(exception.getMessage().contains("too many levels"));
+    }
+  }
 
-    Map<String,String> expected = new HashMap<>();
-    expected.put("MANAGER_HOSTS", "localhost1 localhost2");
-    expected.put("MONITOR_HOSTS", "localhost1 localhost2");
-    expected.put("GC_HOSTS", "localhost");
-    expected.put("COMPACTOR_GROUPS", "q1 q2");
-    expected.put("COMPACTOR_HOSTS_q1", "localhost1 localhost2");
-    expected.put("COMPACTOR_HOSTS_q2", "localhost3 localhost4");
-    expected.put("SSERVER_GROUPS", "cheap default highmem");
-    expected.put("SSERVER_HOSTS_cheap", "burstyvm1 burstyvm2");
-    expected.put("SSERVER_HOSTS_default", "localhost1 localhost2");
-    expected.put("SSERVER_HOSTS_highmem", "hmvm1 hmvm2 hmvm3");
-    expected.put("TSERVER_GROUPS", "cheap default highmem");
-    expected.put("TSERVER_HOSTS_cheap", "localhost5 localhost6");
-    expected.put("TSERVER_HOSTS_default", "localhost1 localhost2");
-    expected.put("TSERVER_HOSTS_highmem", "localhost3 localhost4");
-    expected.put("NUM_TSERVERS", "${NUM_TSERVERS:=2}");
-    expected.put("NUM_COMPACTORS_q1", "3");
-    expected.put("NUM_COMPACTORS_q2", "1");
-    expected.put("NUM_SSERVERS_default", "1");
-    expected.put("NUM_SSERVERS_highmem", "2");
-    expected.put("NUM_SSERVERS_cheap", "3");
-
-    expected.replaceAll((k, v) -> {
-      return '"' + v + '"';
-    });
+  @Test
+  public void testFileMissingCompactor() throws Exception {
+    URL configFile = ClusterConfigParserTest.class
+        
.getResource("/org/apache/accumulo/core/conf/cluster/cluster-missing-compactor-group.yaml");
+    assertNotNull(configFile);
 
-    Map<String,String> actual = new HashMap<>();
-    try (BufferedReader rdr = Files.newBufferedReader(Paths.get(f.toURI()))) {
-      rdr.lines().forEach(l -> {
-        String[] props = l.split("=", 2);
-        actual.put(props[0], props[1]);
-      });
+    Map<String,String> contents =
+        ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
+
+    try (var baos = new ByteArrayOutputStream(); var ps = new 
PrintStream(baos)) {
+      var exception = assertThrows(IllegalArgumentException.class,
+          () -> ClusterConfigParser.outputShellVariables(contents, ps));
+      assertTrue(exception.getMessage().contains("No compactor groups found"));
     }
+  }
 
-    assertEquals(expected, actual);
+  @Test
+  public void testFileMissingTabletServer() throws Exception {
+    URL configFile = ClusterConfigParserTest.class
+        
.getResource("/org/apache/accumulo/core/conf/cluster/cluster-missing-tserver-group.yaml");
+    assertNotNull(configFile);
+
+    Map<String,String> contents =
+        ClusterConfigParser.parseConfiguration(new 
File(configFile.toURI()).getAbsolutePath());
+
+    try (var baos = new ByteArrayOutputStream(); var ps = new 
PrintStream(baos)) {
+      var exception = assertThrows(IllegalArgumentException.class,
+          () -> ClusterConfigParser.outputShellVariables(contents, ps));
+      assertTrue(exception.getMessage().contains("No tserver groups found"));
+    }
   }
 
   @Test
-  public void testFileWithUnknownSections() throws Exception {
+  public void testFileOlderVersion() throws Exception {
     URL configFile = ClusterConfigParserTest.class
-        
.getResource("/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml");
+        
.getResource("/org/apache/accumulo/core/conf/cluster/2_1_cluster.yaml");
     assertNotNull(configFile);
 
     Map<String,String> contents =
@@ -274,7 +300,7 @@ public class ClusterConfigParserTest {
     try (var baos = new ByteArrayOutputStream(); var ps = new 
PrintStream(baos)) {
       var exception = assertThrows(IllegalArgumentException.class,
           () -> ClusterConfigParser.outputShellVariables(contents, ps));
-      assertTrue(exception.getMessage().contains("vserver"));
+      assertTrue(exception.getMessage().contains("Check the format"));
     }
   }
 
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/2_1_cluster.yaml
similarity index 67%
copy from 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
copy to 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/2_1_cluster.yaml
index 01f506dd0c..dd490e3e01 100644
--- 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
+++ 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/2_1_cluster.yaml
@@ -18,35 +18,22 @@
 #
 
 manager:
-  - localhost1
-  - localhost2
+  - localhost
 
 monitor:
-  - localhost1
-  - localhost2
+  - localhost
 
 gc:
   - localhost
 
 tserver:
   default:
-    - localhost1
-    - localhost2
-    - localhost3
-    - localhost4
+    - localhost
 
-# The following section name is not valid and should cause an error.
-vserver:
-  - localhost5
-  - localhost6
-  - localhost7
-  - localhost8
+compactor:
+  default:
+    - localhost
 
-#compaction:
-#  compactor:
-#    - q1:
-#        - localhost1
-#        - localhost2
-#    - q2:
-#        - localhost1
-#        - localhost2
+sserver:
+  default:
+    - localhost
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-group-name.yaml
similarity index 67%
copy from 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
copy to 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-group-name.yaml
index 01f506dd0c..3fb979d040 100644
--- 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
+++ 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-group-name.yaml
@@ -18,35 +18,32 @@
 #
 
 manager:
-  - localhost1
-  - localhost2
+  - localhost
 
 monitor:
-  - localhost1
-  - localhost2
+  - localhost
 
 gc:
   - localhost
 
-tserver:
+compactor:
   default:
-    - localhost1
-    - localhost2
-    - localhost3
-    - localhost4
+    servers_per_host: 1
+    hosts:
+      - localhost
 
-# The following section name is not valid and should cause an error.
-vserver:
-  - localhost5
-  - localhost6
-  - localhost7
-  - localhost8
+sserver:
+  default:
+    servers_per_host: 1
+    hosts:
+      - localhost
+  bad-group-name:
+    servers_per_host: 1        
+    hosts:
+      - localhost
 
-#compaction:
-#  compactor:
-#    - q1:
-#        - localhost1
-#        - localhost2
-#    - q2:
-#        - localhost1
-#        - localhost2
+tserver:
+  default:
+    servers_per_host: 1
+    hosts:
+      - localhost
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-group-suffix.yaml
similarity index 67%
copy from 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
copy to 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-group-suffix.yaml
index 01f506dd0c..20bd98d65f 100644
--- 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
+++ 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-group-suffix.yaml
@@ -18,35 +18,28 @@
 #
 
 manager:
-  - localhost1
-  - localhost2
+  - localhost
 
 monitor:
-  - localhost1
-  - localhost2
+  - localhost
 
 gc:
   - localhost
 
-tserver:
+compactor:
   default:
-    - localhost1
-    - localhost2
-    - localhost3
-    - localhost4
+    servers_per_host: 1
+    hosts:
+      - localhost
 
-# The following section name is not valid and should cause an error.
-vserver:
-  - localhost5
-  - localhost6
-  - localhost7
-  - localhost8
+sserver:
+  default:
+    servers_per_hosts: 1
+    hosts:
+      - localhost
 
-#compaction:
-#  compactor:
-#    - q1:
-#        - localhost1
-#        - localhost2
-#    - q2:
-#        - localhost1
-#        - localhost2
+tserver:
+  default:
+    servers_per_host: 1
+    hosts:
+      - localhost
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-server-name.yaml
similarity index 89%
copy from 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
copy to 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-server-name.yaml
index 01f506dd0c..c805df7393 100644
--- 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
+++ 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-server-name.yaml
@@ -42,11 +42,3 @@ vserver:
   - localhost7
   - localhost8
 
-#compaction:
-#  compactor:
-#    - q1:
-#        - localhost1
-#        - localhost2
-#    - q2:
-#        - localhost1
-#        - localhost2
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-with-optional-services.yaml
 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-missing-compactor-group.yaml
similarity index 68%
rename from 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-with-optional-services.yaml
rename to 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-missing-compactor-group.yaml
index 06b8e6f81c..a64c6a517c 100644
--- 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-with-optional-services.yaml
+++ 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-missing-compactor-group.yaml
@@ -28,42 +28,29 @@ monitor:
 gc:
   - localhost
 
-tserver:
-  default:
-    - localhost1
-    - localhost2
-  highmem:
-    - localhost3
-    - localhost4
-  cheap:
-    - localhost5
-    - localhost6
-
 sserver:
   default:
-    - localhost1
-    - localhost2
+    servers_per_host: 2
+    hosts:
+      - localhost1
+      - localhost2
   highmem:
-    - hmvm1
-    - hmvm2
-    - hmvm3
+    servers_per_host: 1        
+    hosts:
+      - hmvm1
+      - hmvm2
+      - hmvm3
   cheap:
-    - burstyvm1
-    - burstyvm2
-
-compactor:
-  q1:
-    - localhost1
-    - localhost2
-  q2:
-    - localhost3
-    - localhost4
+    servers_per_host: 3        
+    hosts:
+      - burstyvm1
+      - burstyvm2
 
-tservers_per_host: 2
-sservers_per_host:
-  - default : 1
-  - highmem : 2
-  - cheap : 3
-compactors_per_host:
-  - q1 : 3
-  - q2 : 1
+tserver:
+  default:
+    servers_per_host: 2
+    hosts:
+      - localhost1
+      - localhost2
+      - localhost3
+      - localhost4
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-missing-tserver-group.yaml
similarity index 71%
copy from 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
copy to 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-missing-tserver-group.yaml
index 01f506dd0c..12e5bce913 100644
--- 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
+++ 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster-missing-tserver-group.yaml
@@ -28,25 +28,16 @@ monitor:
 gc:
   - localhost
 
-tserver:
-  default:
-    - localhost1
-    - localhost2
-    - localhost3
-    - localhost4
-
-# The following section name is not valid and should cause an error.
-vserver:
-  - localhost5
-  - localhost6
-  - localhost7
-  - localhost8
+compactor:
+  q1:
+    # servers not specified, defaults to 1
+    hosts:
+      - localhost1
+      - localhost2
 
-#compaction:
-#  compactor:
-#    - q1:
-#        - localhost1
-#        - localhost2
-#    - q2:
-#        - localhost1
-#        - localhost2
+sserver:
+  default:
+    servers_per_host: 2
+    hosts:
+      - localhost1
+      - localhost2
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster.yaml 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster.yaml
index 9262cd094b..21eafe7627 100644
--- a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster.yaml
+++ b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/cluster.yaml
@@ -28,33 +28,41 @@ monitor:
 gc:
   - localhost
 
-tserver:
+compactor:
+  q1:
+    # servers not specified, defaults to 1
+    hosts:
+      - localhost1
+      - localhost2
+  q2:
+    servers_per_host: 4
+    hosts:
+      - localhost3
+      - localhost4
+
+sserver:
   default:
-    - localhost1
-    - localhost2
-    - localhost3
-    - localhost4
+    servers_per_host: 2
+    hosts:
+      - localhost1
+      - localhost2
+  highmem:
+    servers_per_host: 1        
+    hosts:
+      - hmvm1
+      - hmvm2
+      - hmvm3
+  cheap:
+    servers_per_host: 3        
+    hosts:
+      - burstyvm1
+      - burstyvm2
 
-#sserver:
-#  default:
-#    - localhost1
-#    - localhost2
-#  highmem:
-#    - hmvm1
-#    - hmvm2
-#    - hmvm3
-#  cheap:
-#    - burstyvm1
-#    - burstyvm2
-#
-#compactor:
-#  q1:
-#    - localhost1
-#    - localhost2
-#  q2:
-#    - localhost3
-#    - localhost4
-#
-#tservers_per_host: 2
-#sservers_per_host: 1
-    
\ No newline at end of file
+tserver:
+  default:
+    servers_per_host: 2
+    hosts:
+      - localhost1
+      - localhost2
+      - localhost3
+      - localhost4
diff --git 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/too-many-levels.yaml
similarity index 67%
rename from 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
rename to 
core/src/test/resources/org/apache/accumulo/core/conf/cluster/too-many-levels.yaml
index 01f506dd0c..30270e1011 100644
--- 
a/core/src/test/resources/org/apache/accumulo/core/conf/cluster/bad-cluster.yaml
+++ 
b/core/src/test/resources/org/apache/accumulo/core/conf/cluster/too-many-levels.yaml
@@ -18,35 +18,29 @@
 #
 
 manager:
-  - localhost1
-  - localhost2
+  - localhost
 
 monitor:
-  - localhost1
-  - localhost2
+  - localhost
 
 gc:
   - localhost
 
-tserver:
+compactor:
   default:
-    - localhost1
-    - localhost2
-    - localhost3
-    - localhost4
+    servers_per_host: 1
+    hosts:
+      - localhost
 
-# The following section name is not valid and should cause an error.
-vserver:
-  - localhost5
-  - localhost6
-  - localhost7
-  - localhost8
+sserver:
+  default:
+    config:
+      servers_per_host: 1
+      hosts:
+      - localhost
 
-#compaction:
-#  compactor:
-#    - q1:
-#        - localhost1
-#        - localhost2
-#    - q2:
-#        - localhost1
-#        - localhost2
+tserver:
+  default:
+    servers_per_host: 1
+    hosts:
+      - localhost

Reply via email to