dlmarion commented on code in PR #5749:
URL: https://github.com/apache/accumulo/pull/5749#discussion_r2242932093


##########
core/src/main/java/org/apache/accumulo/core/client/admin/ResourceGroupOperations.java:
##########
@@ -0,0 +1,217 @@
+/*
+ * 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
+ *
+ *   https://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.core.client.admin;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.ResourceGroupNotFoundException;
+import org.apache.accumulo.core.data.ResourceGroupId;
+
+/**
+ * A ResourceGroup is a grouping of Accumulo server processes that have some 
shared characteristic
+ * that is different than server processes in other resource groups. Examples 
could be homogeneous
+ * hardware configurations for the server processes in one resource group but 
different than other
+ * resource groups, or a resource group could be created for physical 
separation of processing for
+ * table(s).
+ *
+ * A default resource group exists in which all server processes are assigned. 
The Manager, Monitor,
+ * and GarbageCollector are assigned to the default resource group. Compactor, 
ScanServer and
+ * TabletServer processes are also assigned to the default resource group, 
unless their respective
+ * properties are set.
+ *
+ * This object is for defining, interacting, and removing resource group 
configurations. When the
+ * Accumulo server processes get the system configuration, they will receive a 
merged view of the
+ * system configuration and applicable resource group configuration, with any 
property defined in
+ * the resource group configuration given higher priority.
+ *
+ * @since 4.0.0
+ */
+public interface ResourceGroupOperations {
+
+  /**
+   * A method to check if a resource group configuration exists in Accumulo.
+   *
+   * @param group the name of the resource group
+   * @return true if the group exists
+   */
+  boolean exists(String group);
+
+  /**
+   * Retrieve a list of resource groups in Accumulo.
+   *
+   * @return Set of resource groups in accumulo
+   */
+  Set<ResourceGroupId> list();
+
+  /**
+   * Create a configuration node in zookeeper for a resource group. If not 
defined, then processes
+   * running in the resource group will use the values of the properties 
defined in the system
+   * configuration.
+   *
+   * @param group resource group
+   * @throws AccumuloException if a general error occurs
+   * @throws AccumuloSecurityException if the user does not have permission
+   */
+  void create(final ResourceGroupId group) throws AccumuloException, 
AccumuloSecurityException;
+
+  /**
+   * Returns the properties set for this resource group in zookeeper merged 
with the system
+   * configuration.
+   *
+   * @param group resource group
+   * @return Map of property keys/values
+   * @throws AccumuloException if a general error occurs
+   * @throws AccumuloSecurityException if the user does not have permission
+   * @throws ResourceGroupNotFoundException if the specified resource group 
doesn't exist
+   */
+  Map<String,String> getConfiguration(final ResourceGroupId group)
+      throws AccumuloException, AccumuloSecurityException, 
ResourceGroupNotFoundException;
+
+  /**
+   * Returns the un-merged properties set for this resource group in zookeeper.
+   *
+   * @param group resource group
+   * @return Map of property keys/values
+   * @throws AccumuloException if a general error occurs
+   * @throws AccumuloSecurityException if the user does not have permission
+   * @throws ResourceGroupNotFoundException if the specified resource group 
doesn't exist
+   */
+  Map<String,String> getProperties(final ResourceGroupId group)
+      throws AccumuloException, AccumuloSecurityException, 
ResourceGroupNotFoundException;
+
+  /**
+   * Sets a resource group property in zookeeper. Servers will pull this 
setting and override the
+   * equivalent setting in accumulo.properties. Changes can be seen using
+   * {@code #getProperties(ResourceGroupId)} or {@link 
InstanceOperations#getSystemConfiguration()}
+   * can be used to return a system-level merged view.
+   * <p>
+   * Only some properties can be changed by this method, an 
IllegalArgumentException will be thrown
+   * if there is an attempt to set a read-only property.
+   *
+   * @param group resource group
+   * @param property the name of a system property
+   * @param value the value to set a system property to
+   * @throws AccumuloException if a general error occurs
+   * @throws AccumuloSecurityException if the user does not have permission
+   * @throws ResourceGroupNotFoundException if the specified resource group 
doesn't exist
+   */
+  void setProperty(final ResourceGroupId group, final String property, final 
String value)
+      throws AccumuloException, AccumuloSecurityException, 
ResourceGroupNotFoundException;
+
+  /**
+   * Modify resource group properties using a Consumer that accepts a mutable 
map containing the
+   * current system property overrides stored in ZooKeeper. If the supplied 
Consumer alters the map
+   * without throwing an Exception, then the resulting map will atomically 
replace the current
+   * system property overrides in ZooKeeper. Only properties which can be 
stored in ZooKeeper will
+   * be accepted.
+   *
+   * <p>
+   * Accumulo has multiple layers of properties that for many APIs and SPIs 
are presented as a
+   * single merged view. This API does not offer that merged view, it only 
offers the properties set
+   * at the resource group layer to the mapMutator.
+   * </p>
+   *
+   * <p>
+   * Below is an example of using this API to conditionally set some instance 
properties. If while
+   * trying to set the compaction planner properties another process modifies 
the manager balancer
+   * properties, then it would automatically retry and call the lambda again 
with the latest
+   * snapshot of instance properties.
+   * </p>
+   *
+   * <pre>
+   *         {@code
+   *             AccumuloClient client = getClient();
+   *             Map<String,String> acceptedProps = 
client.resourceGroupOperations().modifyProperties(groupId, currProps -> {
+   *               var planner = 
currProps.get("compaction.service.default.planner");
+   *               //This code will only change the compaction planner if its 
currently set to default settings.
+   *               //The endsWith() function was used to make the example 
short, would be better to use equals().
+   *               if(planner != null && 
planner.endsWith("RatioBasedCompactionPlanner") {
+   *                 // tservers will eventually see these compaction planner 
changes and when they do they will see all of the changes at once
+   *                 currProps.keySet().removeIf(
+   *                    prop -> 
prop.startsWith("compaction.service.default.planner.opts."));
+   *                 
currProps.put("compaction.service.default.planner","MyPlannerClassName");
+   *                 
currProps.put("compaction.service.default.planner.opts.myOpt1","val1");
+   *                 
currProps.put("compaction.service.default.planner.opts.myOpt2","val2");
+   *                }
+   *             });
+   *
+   *             // Since three properties were set may want to check for the 
values of all
+   *             // three, just checking one in this example to keep it short.
+   *             
if("MyPlannerClassName".equals(acceptedProps.get("compaction.service.default.planner"))){
+   *                // the compaction planner change was accepted or already 
existed, so take action for that outcome
+   *             } else {
+   *                // the compaction planner change was not done, so take 
action for that outcome
+   *             }
+   *           }
+   *         }
+   * </pre>
+   *
+   * @param group resource group
+   * @param mapMutator This consumer should modify the passed snapshot of 
resource group properties
+   *        to contain the desired keys and values. It should be safe for 
Accumulo to call this
+   *        consumer multiple times, this may be done automatically when 
certain retryable errors
+   *        happen. The consumer should probably avoid accessing the Accumulo 
client as that could
+   *        lead to undefined behavior.
+   *
+   * @throws AccumuloException if a general error occurs
+   * @throws AccumuloSecurityException if the user does not have permission
+   * @throws IllegalArgumentException if the Consumer alters the map by adding 
properties that
+   *         cannot be stored in ZooKeeper
+   * @throws ResourceGroupNotFoundException if the specified resource group 
doesn't exist
+   *
+   * @return The map that became Accumulo's new properties for this resource 
group. This map is
+   *         immutable and contains the snapshot passed to mapMutator and the 
changes made by
+   *         mapMutator.
+   */
+  Map<String,String> modifyProperties(final ResourceGroupId group,
+      final Consumer<Map<String,String>> mapMutator) throws AccumuloException,
+      AccumuloSecurityException, IllegalArgumentException, 
ResourceGroupNotFoundException;
+
+  /**
+   * Removes a resource group property from zookeeper. Changes can be seen 
using
+   * {@code #getProperties(ResourceGroupId)} or {@link 
InstanceOperations#getSystemConfiguration()}
+   * can be used to return a system-level merged view.
+   *
+   * @param group resource group
+   * @param property the name of a system property
+   * @throws AccumuloException if a general error occurs
+   * @throws AccumuloSecurityException if the user does not have permission
+   * @throws ResourceGroupNotFoundException if the specified resource group 
doesn't exist
+   */
+  void removeProperty(final ResourceGroupId group, final String property)
+      throws AccumuloException, AccumuloSecurityException, 
ResourceGroupNotFoundException;
+
+  /**
+   * Removes a configuration node in zookeeper for a resource group. If not 
defined, then processes
+   * running in the resource group will use the values of the properties 
defined in the system
+   * configuration.
+   *
+   * @param group resource group
+   * @throws AccumuloException if a general error occurs
+   * @throws AccumuloSecurityException if the user does not have permission
+   * @throws ResourceGroupNotFoundException if the specified resource group 
doesn't exist
+   */
+  void remove(final ResourceGroupId group)

Review Comment:
   Fixed in bd50934



##########
server/base/src/main/java/org/apache/accumulo/server/conf/cluster/ClusterConfigParser.java:
##########
@@ -225,24 +243,42 @@ public static void 
outputShellVariables(Map<String,String> config, PrintStream o
   @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN",
       justification = "Path provided for output file is intentional")
   public static void main(String[] args) throws IOException {
-    if (args == null || args.length < 1 || args.length > 2) {
-      System.err.println("Usage: ClusterConfigParser <configFile> 
[<outputFile>]");
+    if (args == null || args.length < 1 || args.length > 3) {
+      System.err.println(
+          "Usage: ClusterConfigParser <createMissingResourceGroups> 
<configFile> [<outputFile>]");
       System.exit(1);
     }
 
-    try {
-      if (args.length == 2) {
-        // Write to a file instead of System.out if provided as an argument
-        try (OutputStream os = Files.newOutputStream(Path.of(args[1]));
-            PrintStream out = new PrintStream(os)) {
-          outputShellVariables(parseConfiguration(Path.of(args[0])), out);
+    if (siteConf == null) {
+      siteConf = SiteConfiguration.auto();
+    }
+    try (var context = new ServerContext(siteConf)) {
+      // Login as the server on secure HDFS
+      if (siteConf.getBoolean(Property.INSTANCE_RPC_SASL_ENABLED)) {
+        SecurityUtil.serverLogin(siteConf);
+      }
+      final Set<String> zkGroups = new HashSet<>();
+      context.resourceGroupOperations().list().forEach(rg -> 
zkGroups.add(rg.canonical()));
+      if (!zkGroups.contains(ResourceGroupId.DEFAULT.canonical())) {
+        throw new IllegalStateException("Default resource group not found in 
ZooKeeper");
+      }

Review Comment:
   Fixed in bd50934



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

To unsubscribe, e-mail: notifications-unsubscr...@accumulo.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to