@Test public void testInsert() throws Exception { makeUpgradeCluster(); Cluster c = clusters.getCluster("c1"); assertEquals(1, c.getConfigsByType("zoo.cfg").size()); c.setDesiredStackVersion(HDP_220_STACK); Config config = cf.createNew(c, "zoo.cfg", "version2", new HashMap<String, String>() { { put("key_to_append", "append"); put("key_to_prepend", "prepend"); } }, new HashMap<String, Map<String, String>>()); c.addDesiredConfig("user", Collections.singleton(config)); assertEquals(2, c.getConfigsByType("zoo.cfg").size()); Map<String, String> commandParams = new HashMap<>(); commandParams.put("upgrade_direction", "upgrade"); commandParams.put("version", HDP_2_2_0_1); commandParams.put("clusterName", "c1"); commandParams.put(ConfigureTask.PARAMETER_CONFIG_TYPE, "zoo.cfg"); final String prependValue = "This should be on a newline"; final String appendValue = " this will be after..."; List<Insert> insertions = new ArrayList<>(); Insert prepend = new Insert(); prepend.insertType = InsertType.PREPEND; prepend.key = "key_to_prepend"; prepend.value = prependValue; prepend.newlineBefore = false; prepend.newlineAfter = true; Insert append = new Insert(); append.insertType = InsertType.APPEND; append.key = "key_to_append"; append.value = appendValue; append.newlineBefore = false; append.newlineAfter = false; insertions.add(prepend); insertions.add(append); insertions.add(prepend); insertions.add(append); commandParams.put(ConfigureTask.PARAMETER_INSERTIONS, new Gson().toJson(insertions)); ExecutionCommand executionCommand = new ExecutionCommand(); executionCommand.setCommandParams(commandParams); executionCommand.setClusterName("c1"); executionCommand.setRoleParams(new HashMap<String, String>()); executionCommand.getRoleParams().put(ServerAction.ACTION_USER_NAME, "username"); HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null); hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand)); action.setExecutionCommand(executionCommand); action.setHostRoleCommand(hostRoleCommand); CommandReport report = action.execute(null); assertNotNull(report); assertEquals(3, c.getConfigsByType("zoo.cfg").size()); config = c.getDesiredConfigByType("zoo.cfg"); assertNotNull(config); assertFalse("version2".equals(config.getTag())); String expectedPrepend = prependValue + System.lineSeparator() + "prepend"; String expectedAppend = "append" + appendValue; assertEquals(expectedPrepend, config.getProperties().get("key_to_prepend")); assertEquals(expectedAppend, config.getProperties().get("key_to_append")); }
@Override public CommandReport execute( ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException { Map<String,String> commandParameters = getCommandParameters(); if( null == commandParameters || commandParameters.isEmpty() ){ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", "Unable to change configuration values without command parameters"); } String clusterName = commandParameters.get("clusterName"); Cluster cluster = m_clusters.getCluster(clusterName); String configType = commandParameters.get(ConfigureTask.PARAMETER_CONFIG_TYPE); List<ConfigurationKeyValue> keyValuePairs = Collections.emptyList(); String keyValuePairJson = commandParameters.get(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS); if (null != keyValuePairJson) { keyValuePairs = m_gson.fromJson( keyValuePairJson, new TypeToken<List<ConfigurationKeyValue>>(){}.getType()); keyValuePairs = getAllowedSets(cluster, configType, keyValuePairs); } List<Transfer> transfers = Collections.emptyList(); String transferJson = commandParameters.get(ConfigureTask.PARAMETER_TRANSFERS); if (null != transferJson) { transfers = m_gson.fromJson( transferJson, new TypeToken<List<Transfer>>(){}.getType()); transfers = getAllowedTransfers(cluster, configType, transfers); } List<Replace> replacements = Collections.emptyList(); String replaceJson = commandParameters.get(ConfigureTask.PARAMETER_REPLACEMENTS); if (null != replaceJson) { replacements = m_gson.fromJson( replaceJson, new TypeToken<List<Replace>>(){}.getType()); replacements = getAllowedReplacements(cluster, configType, replacements); } List<Insert> insertions = Collections.emptyList(); String insertJson = commandParameters.get(ConfigureTask.PARAMETER_INSERTIONS); if (null != insertJson) { insertions = m_gson.fromJson( insertJson, new TypeToken<List<Insert>>(){}.getType()); } if (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty()) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); StringBuilder buffer = new StringBuilder( "Skipping this configuration task since none of the conditions were met and there are no transfers, replacements, or insertions.").append("\n"); buffer.append(message); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", buffer.toString(), ""); } if (null == clusterName || null == configType || (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty())) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", message); } Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs(); DesiredConfig desiredConfig = desiredConfigs.get(configType); if (desiredConfig == null) { throw new AmbariException("Could not find desired config type with name " + configType); } Config config = cluster.getConfig(configType, desiredConfig.getTag()); if (config == null) { throw new AmbariException("Could not find config type with name " + configType); } StackId currentStack = cluster.getCurrentStackVersion(); StackId targetStack = cluster.getDesiredStackVersion(); StackId configStack = config.getStackId(); Map<String, String> base = config.getProperties(); Map<String, String> newValues = new HashMap<>(base); boolean changedValues = false; StringBuilder outputBuffer = new StringBuilder(250); for (Transfer transfer : transfers) { switch (transfer.operation) { case COPY: String valueToCopy = null; if( null == transfer.fromType ) { valueToCopy = base.get(transfer.fromKey); } else { Config other = cluster.getDesiredConfigByType(transfer.fromType); if (null != other){ Map<String, String> otherValues = other.getProperties(); if (otherValues.containsKey(transfer.fromKey)){ valueToCopy = otherValues.get(transfer.fromKey); } } } if (StringUtils.isBlank(valueToCopy) && !StringUtils.isBlank(transfer.defaultValue)) { valueToCopy = transfer.defaultValue; } if (StringUtils.isNotBlank(valueToCopy)) { if (transfer.coerceTo != null) { switch (transfer.coerceTo) { case YAML_ARRAY: { String[] splitValues = StringUtils.split(valueToCopy, ','); List<String> quotedValues = new ArrayList<>(splitValues.length); for (String splitValue : splitValues) { quotedValues.add("'" + StringUtils.trim(splitValue) + "'"); } valueToCopy = "[" + StringUtils.join(quotedValues, ',') + "]"; break; } default: break; } } changedValues = true; newValues.put(transfer.toKey, valueToCopy); updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} = \"{2}\"", configType, transfer.toKey, mask(transfer, valueToCopy))); } break; case MOVE: if (newValues.containsKey(transfer.fromKey)) { newValues.put(transfer.toKey, newValues.remove(transfer.fromKey)); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Renamed {0}/{1} to {2}/{3}", configType, transfer.fromKey, configType, transfer.toKey)); } else if (StringUtils.isNotBlank(transfer.defaultValue)) { newValues.put(transfer.toKey, transfer.defaultValue); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} with default value \"{2}\"", configType, transfer.toKey, mask(transfer, transfer.defaultValue))); } break; case DELETE: if ("*".equals(transfer.deleteKey)) { newValues.clear(); updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted all keys from {0}", configType)); for (String keeper : transfer.keepKeys) { if (base.containsKey(keeper) && base.get(keeper) != null) { newValues.put(keeper, base.get(keeper)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, keeper)); } } if (transfer.preserveEdits) { List<String> edited = findValuesToPreserve(clusterName, config); for (String changed : edited) { newValues.put(changed, base.get(changed)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, changed)); } } changedValues = true; } else { newValues.remove(transfer.deleteKey); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted {0}/{1}", configType, transfer.deleteKey)); } break; } } if (null != keyValuePairs && !keyValuePairs.isEmpty()) { for (ConfigurationKeyValue keyValuePair : keyValuePairs) { String key = keyValuePair.key; String value = keyValuePair.value; if (null != key) { String oldValue = base.get(key); if (null != oldValue && value.equals(oldValue)) { if (currentStack.equals(targetStack) && !changedValues) { updateBufferWithMessage(outputBuffer, MessageFormat.format( "{0}/{1} for cluster {2} would not change, skipping setting", configType, key, clusterName)); continue; } } newValues.put(key, value); final String message; if (StringUtils.isEmpty(value)) { message = MessageFormat.format("{0}/{1} changed to an empty value", configType, key); } else { message = MessageFormat.format("{0}/{1} changed to \"{2}\"", configType, key, mask(keyValuePair, value)); } updateBufferWithMessage(outputBuffer, message); } } } for (Replace replacement : replacements) { String toReplace = newValues.get(replacement.key); if (StringUtils.isNotBlank(toReplace)) { if (!toReplace.contains(replacement.find)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("String \"{0}\" was not found in {1}/{2}", replacement.find, configType, replacement.key)); } else { String replaced = StringUtils.replace(toReplace, replacement.find, replacement.replaceWith); newValues.put(replacement.key, replaced); updateBufferWithMessage(outputBuffer, MessageFormat.format("Replaced {0}/{1} containing \"{2}\" with \"{3}\"", configType, replacement.key, replacement.find, replacement.replaceWith)); } } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping replacement for {0}/{1} because it does not exist or is empty.", configType, replacement.key)); } } for (Insert insert : insertions) { String valueToInsertInto = newValues.get(insert.key); if (StringUtils.isNotBlank(valueToInsertInto)) { if (StringUtils.contains(valueToInsertInto, insert.value)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("Skipping insertion for {0}/{1} because it already contains {2}", configType, insert.key, insert.value)); continue; } String valueToInsert = insert.value; if (insert.newlineBefore) { valueToInsert = System.lineSeparator() + valueToInsert; } if (insert.newlineAfter) { valueToInsert = valueToInsert + System.lineSeparator(); } switch (insert.insertType) { case APPEND: valueToInsertInto = valueToInsertInto + valueToInsert; break; case PREPEND: valueToInsertInto = valueToInsert + valueToInsertInto; break; default: LOG.error("Unable to insert {0}/{1} with unknown insertion type of {2}", configType, insert.key, insert.insertType); break; } newValues.put(insert.key, valueToInsertInto); updateBufferWithMessage(outputBuffer, MessageFormat.format( "Updated {0}/{1} by inserting {2}", configType, insert.key, insert.value)); } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping insertion for {0}/{1} because it does not exist or is empty.", configType, insert.key)); } } if (!targetStack.equals(currentStack) && targetStack.equals(configStack)) { config.setProperties(newValues); config.save(); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outputBuffer.toString(), ""); } String serviceVersionNote = "Stack Upgrade"; String auditName = getExecutionCommand().getRoleParams().get(ServerAction.ACTION_USER_NAME); if (auditName == null) { auditName = m_configuration.getAnonymousAuditName(); } m_configHelper.createConfigType(cluster, m_controller, configType, newValues, auditName, serviceVersionNote); String message = "Finished updating configuration ''{0}''"; message = MessageFormat.format(message, configType); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", message, ""); }
ConfigureAction extends AbstractServerAction { @Override public CommandReport execute( ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException { Map<String,String> commandParameters = getCommandParameters(); if( null == commandParameters || commandParameters.isEmpty() ){ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", "Unable to change configuration values without command parameters"); } String clusterName = commandParameters.get("clusterName"); Cluster cluster = m_clusters.getCluster(clusterName); String configType = commandParameters.get(ConfigureTask.PARAMETER_CONFIG_TYPE); List<ConfigurationKeyValue> keyValuePairs = Collections.emptyList(); String keyValuePairJson = commandParameters.get(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS); if (null != keyValuePairJson) { keyValuePairs = m_gson.fromJson( keyValuePairJson, new TypeToken<List<ConfigurationKeyValue>>(){}.getType()); keyValuePairs = getAllowedSets(cluster, configType, keyValuePairs); } List<Transfer> transfers = Collections.emptyList(); String transferJson = commandParameters.get(ConfigureTask.PARAMETER_TRANSFERS); if (null != transferJson) { transfers = m_gson.fromJson( transferJson, new TypeToken<List<Transfer>>(){}.getType()); transfers = getAllowedTransfers(cluster, configType, transfers); } List<Replace> replacements = Collections.emptyList(); String replaceJson = commandParameters.get(ConfigureTask.PARAMETER_REPLACEMENTS); if (null != replaceJson) { replacements = m_gson.fromJson( replaceJson, new TypeToken<List<Replace>>(){}.getType()); replacements = getAllowedReplacements(cluster, configType, replacements); } List<Insert> insertions = Collections.emptyList(); String insertJson = commandParameters.get(ConfigureTask.PARAMETER_INSERTIONS); if (null != insertJson) { insertions = m_gson.fromJson( insertJson, new TypeToken<List<Insert>>(){}.getType()); } if (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty()) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); StringBuilder buffer = new StringBuilder( "Skipping this configuration task since none of the conditions were met and there are no transfers, replacements, or insertions.").append("\n"); buffer.append(message); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", buffer.toString(), ""); } if (null == clusterName || null == configType || (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty())) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", message); } Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs(); DesiredConfig desiredConfig = desiredConfigs.get(configType); if (desiredConfig == null) { throw new AmbariException("Could not find desired config type with name " + configType); } Config config = cluster.getConfig(configType, desiredConfig.getTag()); if (config == null) { throw new AmbariException("Could not find config type with name " + configType); } StackId currentStack = cluster.getCurrentStackVersion(); StackId targetStack = cluster.getDesiredStackVersion(); StackId configStack = config.getStackId(); Map<String, String> base = config.getProperties(); Map<String, String> newValues = new HashMap<>(base); boolean changedValues = false; StringBuilder outputBuffer = new StringBuilder(250); for (Transfer transfer : transfers) { switch (transfer.operation) { case COPY: String valueToCopy = null; if( null == transfer.fromType ) { valueToCopy = base.get(transfer.fromKey); } else { Config other = cluster.getDesiredConfigByType(transfer.fromType); if (null != other){ Map<String, String> otherValues = other.getProperties(); if (otherValues.containsKey(transfer.fromKey)){ valueToCopy = otherValues.get(transfer.fromKey); } } } if (StringUtils.isBlank(valueToCopy) && !StringUtils.isBlank(transfer.defaultValue)) { valueToCopy = transfer.defaultValue; } if (StringUtils.isNotBlank(valueToCopy)) { if (transfer.coerceTo != null) { switch (transfer.coerceTo) { case YAML_ARRAY: { String[] splitValues = StringUtils.split(valueToCopy, ','); List<String> quotedValues = new ArrayList<>(splitValues.length); for (String splitValue : splitValues) { quotedValues.add("'" + StringUtils.trim(splitValue) + "'"); } valueToCopy = "[" + StringUtils.join(quotedValues, ',') + "]"; break; } default: break; } } changedValues = true; newValues.put(transfer.toKey, valueToCopy); updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} = \"{2}\"", configType, transfer.toKey, mask(transfer, valueToCopy))); } break; case MOVE: if (newValues.containsKey(transfer.fromKey)) { newValues.put(transfer.toKey, newValues.remove(transfer.fromKey)); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Renamed {0}/{1} to {2}/{3}", configType, transfer.fromKey, configType, transfer.toKey)); } else if (StringUtils.isNotBlank(transfer.defaultValue)) { newValues.put(transfer.toKey, transfer.defaultValue); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} with default value \"{2}\"", configType, transfer.toKey, mask(transfer, transfer.defaultValue))); } break; case DELETE: if ("*".equals(transfer.deleteKey)) { newValues.clear(); updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted all keys from {0}", configType)); for (String keeper : transfer.keepKeys) { if (base.containsKey(keeper) && base.get(keeper) != null) { newValues.put(keeper, base.get(keeper)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, keeper)); } } if (transfer.preserveEdits) { List<String> edited = findValuesToPreserve(clusterName, config); for (String changed : edited) { newValues.put(changed, base.get(changed)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, changed)); } } changedValues = true; } else { newValues.remove(transfer.deleteKey); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted {0}/{1}", configType, transfer.deleteKey)); } break; } } if (null != keyValuePairs && !keyValuePairs.isEmpty()) { for (ConfigurationKeyValue keyValuePair : keyValuePairs) { String key = keyValuePair.key; String value = keyValuePair.value; if (null != key) { String oldValue = base.get(key); if (null != oldValue && value.equals(oldValue)) { if (currentStack.equals(targetStack) && !changedValues) { updateBufferWithMessage(outputBuffer, MessageFormat.format( "{0}/{1} for cluster {2} would not change, skipping setting", configType, key, clusterName)); continue; } } newValues.put(key, value); final String message; if (StringUtils.isEmpty(value)) { message = MessageFormat.format("{0}/{1} changed to an empty value", configType, key); } else { message = MessageFormat.format("{0}/{1} changed to \"{2}\"", configType, key, mask(keyValuePair, value)); } updateBufferWithMessage(outputBuffer, message); } } } for (Replace replacement : replacements) { String toReplace = newValues.get(replacement.key); if (StringUtils.isNotBlank(toReplace)) { if (!toReplace.contains(replacement.find)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("String \"{0}\" was not found in {1}/{2}", replacement.find, configType, replacement.key)); } else { String replaced = StringUtils.replace(toReplace, replacement.find, replacement.replaceWith); newValues.put(replacement.key, replaced); updateBufferWithMessage(outputBuffer, MessageFormat.format("Replaced {0}/{1} containing \"{2}\" with \"{3}\"", configType, replacement.key, replacement.find, replacement.replaceWith)); } } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping replacement for {0}/{1} because it does not exist or is empty.", configType, replacement.key)); } } for (Insert insert : insertions) { String valueToInsertInto = newValues.get(insert.key); if (StringUtils.isNotBlank(valueToInsertInto)) { if (StringUtils.contains(valueToInsertInto, insert.value)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("Skipping insertion for {0}/{1} because it already contains {2}", configType, insert.key, insert.value)); continue; } String valueToInsert = insert.value; if (insert.newlineBefore) { valueToInsert = System.lineSeparator() + valueToInsert; } if (insert.newlineAfter) { valueToInsert = valueToInsert + System.lineSeparator(); } switch (insert.insertType) { case APPEND: valueToInsertInto = valueToInsertInto + valueToInsert; break; case PREPEND: valueToInsertInto = valueToInsert + valueToInsertInto; break; default: LOG.error("Unable to insert {0}/{1} with unknown insertion type of {2}", configType, insert.key, insert.insertType); break; } newValues.put(insert.key, valueToInsertInto); updateBufferWithMessage(outputBuffer, MessageFormat.format( "Updated {0}/{1} by inserting {2}", configType, insert.key, insert.value)); } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping insertion for {0}/{1} because it does not exist or is empty.", configType, insert.key)); } } if (!targetStack.equals(currentStack) && targetStack.equals(configStack)) { config.setProperties(newValues); config.save(); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outputBuffer.toString(), ""); } String serviceVersionNote = "Stack Upgrade"; String auditName = getExecutionCommand().getRoleParams().get(ServerAction.ACTION_USER_NAME); if (auditName == null) { auditName = m_configuration.getAnonymousAuditName(); } m_configHelper.createConfigType(cluster, m_controller, configType, newValues, auditName, serviceVersionNote); String message = "Finished updating configuration ''{0}''"; message = MessageFormat.format(message, configType); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", message, ""); } }
ConfigureAction extends AbstractServerAction { @Override public CommandReport execute( ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException { Map<String,String> commandParameters = getCommandParameters(); if( null == commandParameters || commandParameters.isEmpty() ){ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", "Unable to change configuration values without command parameters"); } String clusterName = commandParameters.get("clusterName"); Cluster cluster = m_clusters.getCluster(clusterName); String configType = commandParameters.get(ConfigureTask.PARAMETER_CONFIG_TYPE); List<ConfigurationKeyValue> keyValuePairs = Collections.emptyList(); String keyValuePairJson = commandParameters.get(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS); if (null != keyValuePairJson) { keyValuePairs = m_gson.fromJson( keyValuePairJson, new TypeToken<List<ConfigurationKeyValue>>(){}.getType()); keyValuePairs = getAllowedSets(cluster, configType, keyValuePairs); } List<Transfer> transfers = Collections.emptyList(); String transferJson = commandParameters.get(ConfigureTask.PARAMETER_TRANSFERS); if (null != transferJson) { transfers = m_gson.fromJson( transferJson, new TypeToken<List<Transfer>>(){}.getType()); transfers = getAllowedTransfers(cluster, configType, transfers); } List<Replace> replacements = Collections.emptyList(); String replaceJson = commandParameters.get(ConfigureTask.PARAMETER_REPLACEMENTS); if (null != replaceJson) { replacements = m_gson.fromJson( replaceJson, new TypeToken<List<Replace>>(){}.getType()); replacements = getAllowedReplacements(cluster, configType, replacements); } List<Insert> insertions = Collections.emptyList(); String insertJson = commandParameters.get(ConfigureTask.PARAMETER_INSERTIONS); if (null != insertJson) { insertions = m_gson.fromJson( insertJson, new TypeToken<List<Insert>>(){}.getType()); } if (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty()) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); StringBuilder buffer = new StringBuilder( "Skipping this configuration task since none of the conditions were met and there are no transfers, replacements, or insertions.").append("\n"); buffer.append(message); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", buffer.toString(), ""); } if (null == clusterName || null == configType || (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty())) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", message); } Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs(); DesiredConfig desiredConfig = desiredConfigs.get(configType); if (desiredConfig == null) { throw new AmbariException("Could not find desired config type with name " + configType); } Config config = cluster.getConfig(configType, desiredConfig.getTag()); if (config == null) { throw new AmbariException("Could not find config type with name " + configType); } StackId currentStack = cluster.getCurrentStackVersion(); StackId targetStack = cluster.getDesiredStackVersion(); StackId configStack = config.getStackId(); Map<String, String> base = config.getProperties(); Map<String, String> newValues = new HashMap<>(base); boolean changedValues = false; StringBuilder outputBuffer = new StringBuilder(250); for (Transfer transfer : transfers) { switch (transfer.operation) { case COPY: String valueToCopy = null; if( null == transfer.fromType ) { valueToCopy = base.get(transfer.fromKey); } else { Config other = cluster.getDesiredConfigByType(transfer.fromType); if (null != other){ Map<String, String> otherValues = other.getProperties(); if (otherValues.containsKey(transfer.fromKey)){ valueToCopy = otherValues.get(transfer.fromKey); } } } if (StringUtils.isBlank(valueToCopy) && !StringUtils.isBlank(transfer.defaultValue)) { valueToCopy = transfer.defaultValue; } if (StringUtils.isNotBlank(valueToCopy)) { if (transfer.coerceTo != null) { switch (transfer.coerceTo) { case YAML_ARRAY: { String[] splitValues = StringUtils.split(valueToCopy, ','); List<String> quotedValues = new ArrayList<>(splitValues.length); for (String splitValue : splitValues) { quotedValues.add("'" + StringUtils.trim(splitValue) + "'"); } valueToCopy = "[" + StringUtils.join(quotedValues, ',') + "]"; break; } default: break; } } changedValues = true; newValues.put(transfer.toKey, valueToCopy); updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} = \"{2}\"", configType, transfer.toKey, mask(transfer, valueToCopy))); } break; case MOVE: if (newValues.containsKey(transfer.fromKey)) { newValues.put(transfer.toKey, newValues.remove(transfer.fromKey)); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Renamed {0}/{1} to {2}/{3}", configType, transfer.fromKey, configType, transfer.toKey)); } else if (StringUtils.isNotBlank(transfer.defaultValue)) { newValues.put(transfer.toKey, transfer.defaultValue); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} with default value \"{2}\"", configType, transfer.toKey, mask(transfer, transfer.defaultValue))); } break; case DELETE: if ("*".equals(transfer.deleteKey)) { newValues.clear(); updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted all keys from {0}", configType)); for (String keeper : transfer.keepKeys) { if (base.containsKey(keeper) && base.get(keeper) != null) { newValues.put(keeper, base.get(keeper)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, keeper)); } } if (transfer.preserveEdits) { List<String> edited = findValuesToPreserve(clusterName, config); for (String changed : edited) { newValues.put(changed, base.get(changed)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, changed)); } } changedValues = true; } else { newValues.remove(transfer.deleteKey); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted {0}/{1}", configType, transfer.deleteKey)); } break; } } if (null != keyValuePairs && !keyValuePairs.isEmpty()) { for (ConfigurationKeyValue keyValuePair : keyValuePairs) { String key = keyValuePair.key; String value = keyValuePair.value; if (null != key) { String oldValue = base.get(key); if (null != oldValue && value.equals(oldValue)) { if (currentStack.equals(targetStack) && !changedValues) { updateBufferWithMessage(outputBuffer, MessageFormat.format( "{0}/{1} for cluster {2} would not change, skipping setting", configType, key, clusterName)); continue; } } newValues.put(key, value); final String message; if (StringUtils.isEmpty(value)) { message = MessageFormat.format("{0}/{1} changed to an empty value", configType, key); } else { message = MessageFormat.format("{0}/{1} changed to \"{2}\"", configType, key, mask(keyValuePair, value)); } updateBufferWithMessage(outputBuffer, message); } } } for (Replace replacement : replacements) { String toReplace = newValues.get(replacement.key); if (StringUtils.isNotBlank(toReplace)) { if (!toReplace.contains(replacement.find)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("String \"{0}\" was not found in {1}/{2}", replacement.find, configType, replacement.key)); } else { String replaced = StringUtils.replace(toReplace, replacement.find, replacement.replaceWith); newValues.put(replacement.key, replaced); updateBufferWithMessage(outputBuffer, MessageFormat.format("Replaced {0}/{1} containing \"{2}\" with \"{3}\"", configType, replacement.key, replacement.find, replacement.replaceWith)); } } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping replacement for {0}/{1} because it does not exist or is empty.", configType, replacement.key)); } } for (Insert insert : insertions) { String valueToInsertInto = newValues.get(insert.key); if (StringUtils.isNotBlank(valueToInsertInto)) { if (StringUtils.contains(valueToInsertInto, insert.value)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("Skipping insertion for {0}/{1} because it already contains {2}", configType, insert.key, insert.value)); continue; } String valueToInsert = insert.value; if (insert.newlineBefore) { valueToInsert = System.lineSeparator() + valueToInsert; } if (insert.newlineAfter) { valueToInsert = valueToInsert + System.lineSeparator(); } switch (insert.insertType) { case APPEND: valueToInsertInto = valueToInsertInto + valueToInsert; break; case PREPEND: valueToInsertInto = valueToInsert + valueToInsertInto; break; default: LOG.error("Unable to insert {0}/{1} with unknown insertion type of {2}", configType, insert.key, insert.insertType); break; } newValues.put(insert.key, valueToInsertInto); updateBufferWithMessage(outputBuffer, MessageFormat.format( "Updated {0}/{1} by inserting {2}", configType, insert.key, insert.value)); } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping insertion for {0}/{1} because it does not exist or is empty.", configType, insert.key)); } } if (!targetStack.equals(currentStack) && targetStack.equals(configStack)) { config.setProperties(newValues); config.save(); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outputBuffer.toString(), ""); } String serviceVersionNote = "Stack Upgrade"; String auditName = getExecutionCommand().getRoleParams().get(ServerAction.ACTION_USER_NAME); if (auditName == null) { auditName = m_configuration.getAnonymousAuditName(); } m_configHelper.createConfigType(cluster, m_controller, configType, newValues, auditName, serviceVersionNote); String message = "Finished updating configuration ''{0}''"; message = MessageFormat.format(message, configType); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", message, ""); }  }
ConfigureAction extends AbstractServerAction { @Override public CommandReport execute( ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException { Map<String,String> commandParameters = getCommandParameters(); if( null == commandParameters || commandParameters.isEmpty() ){ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", "Unable to change configuration values without command parameters"); } String clusterName = commandParameters.get("clusterName"); Cluster cluster = m_clusters.getCluster(clusterName); String configType = commandParameters.get(ConfigureTask.PARAMETER_CONFIG_TYPE); List<ConfigurationKeyValue> keyValuePairs = Collections.emptyList(); String keyValuePairJson = commandParameters.get(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS); if (null != keyValuePairJson) { keyValuePairs = m_gson.fromJson( keyValuePairJson, new TypeToken<List<ConfigurationKeyValue>>(){}.getType()); keyValuePairs = getAllowedSets(cluster, configType, keyValuePairs); } List<Transfer> transfers = Collections.emptyList(); String transferJson = commandParameters.get(ConfigureTask.PARAMETER_TRANSFERS); if (null != transferJson) { transfers = m_gson.fromJson( transferJson, new TypeToken<List<Transfer>>(){}.getType()); transfers = getAllowedTransfers(cluster, configType, transfers); } List<Replace> replacements = Collections.emptyList(); String replaceJson = commandParameters.get(ConfigureTask.PARAMETER_REPLACEMENTS); if (null != replaceJson) { replacements = m_gson.fromJson( replaceJson, new TypeToken<List<Replace>>(){}.getType()); replacements = getAllowedReplacements(cluster, configType, replacements); } List<Insert> insertions = Collections.emptyList(); String insertJson = commandParameters.get(ConfigureTask.PARAMETER_INSERTIONS); if (null != insertJson) { insertions = m_gson.fromJson( insertJson, new TypeToken<List<Insert>>(){}.getType()); } if (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty()) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); StringBuilder buffer = new StringBuilder( "Skipping this configuration task since none of the conditions were met and there are no transfers, replacements, or insertions.").append("\n"); buffer.append(message); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", buffer.toString(), ""); } if (null == clusterName || null == configType || (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty())) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", message); } Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs(); DesiredConfig desiredConfig = desiredConfigs.get(configType); if (desiredConfig == null) { throw new AmbariException("Could not find desired config type with name " + configType); } Config config = cluster.getConfig(configType, desiredConfig.getTag()); if (config == null) { throw new AmbariException("Could not find config type with name " + configType); } StackId currentStack = cluster.getCurrentStackVersion(); StackId targetStack = cluster.getDesiredStackVersion(); StackId configStack = config.getStackId(); Map<String, String> base = config.getProperties(); Map<String, String> newValues = new HashMap<>(base); boolean changedValues = false; StringBuilder outputBuffer = new StringBuilder(250); for (Transfer transfer : transfers) { switch (transfer.operation) { case COPY: String valueToCopy = null; if( null == transfer.fromType ) { valueToCopy = base.get(transfer.fromKey); } else { Config other = cluster.getDesiredConfigByType(transfer.fromType); if (null != other){ Map<String, String> otherValues = other.getProperties(); if (otherValues.containsKey(transfer.fromKey)){ valueToCopy = otherValues.get(transfer.fromKey); } } } if (StringUtils.isBlank(valueToCopy) && !StringUtils.isBlank(transfer.defaultValue)) { valueToCopy = transfer.defaultValue; } if (StringUtils.isNotBlank(valueToCopy)) { if (transfer.coerceTo != null) { switch (transfer.coerceTo) { case YAML_ARRAY: { String[] splitValues = StringUtils.split(valueToCopy, ','); List<String> quotedValues = new ArrayList<>(splitValues.length); for (String splitValue : splitValues) { quotedValues.add("'" + StringUtils.trim(splitValue) + "'"); } valueToCopy = "[" + StringUtils.join(quotedValues, ',') + "]"; break; } default: break; } } changedValues = true; newValues.put(transfer.toKey, valueToCopy); updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} = \"{2}\"", configType, transfer.toKey, mask(transfer, valueToCopy))); } break; case MOVE: if (newValues.containsKey(transfer.fromKey)) { newValues.put(transfer.toKey, newValues.remove(transfer.fromKey)); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Renamed {0}/{1} to {2}/{3}", configType, transfer.fromKey, configType, transfer.toKey)); } else if (StringUtils.isNotBlank(transfer.defaultValue)) { newValues.put(transfer.toKey, transfer.defaultValue); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} with default value \"{2}\"", configType, transfer.toKey, mask(transfer, transfer.defaultValue))); } break; case DELETE: if ("*".equals(transfer.deleteKey)) { newValues.clear(); updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted all keys from {0}", configType)); for (String keeper : transfer.keepKeys) { if (base.containsKey(keeper) && base.get(keeper) != null) { newValues.put(keeper, base.get(keeper)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, keeper)); } } if (transfer.preserveEdits) { List<String> edited = findValuesToPreserve(clusterName, config); for (String changed : edited) { newValues.put(changed, base.get(changed)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, changed)); } } changedValues = true; } else { newValues.remove(transfer.deleteKey); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted {0}/{1}", configType, transfer.deleteKey)); } break; } } if (null != keyValuePairs && !keyValuePairs.isEmpty()) { for (ConfigurationKeyValue keyValuePair : keyValuePairs) { String key = keyValuePair.key; String value = keyValuePair.value; if (null != key) { String oldValue = base.get(key); if (null != oldValue && value.equals(oldValue)) { if (currentStack.equals(targetStack) && !changedValues) { updateBufferWithMessage(outputBuffer, MessageFormat.format( "{0}/{1} for cluster {2} would not change, skipping setting", configType, key, clusterName)); continue; } } newValues.put(key, value); final String message; if (StringUtils.isEmpty(value)) { message = MessageFormat.format("{0}/{1} changed to an empty value", configType, key); } else { message = MessageFormat.format("{0}/{1} changed to \"{2}\"", configType, key, mask(keyValuePair, value)); } updateBufferWithMessage(outputBuffer, message); } } } for (Replace replacement : replacements) { String toReplace = newValues.get(replacement.key); if (StringUtils.isNotBlank(toReplace)) { if (!toReplace.contains(replacement.find)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("String \"{0}\" was not found in {1}/{2}", replacement.find, configType, replacement.key)); } else { String replaced = StringUtils.replace(toReplace, replacement.find, replacement.replaceWith); newValues.put(replacement.key, replaced); updateBufferWithMessage(outputBuffer, MessageFormat.format("Replaced {0}/{1} containing \"{2}\" with \"{3}\"", configType, replacement.key, replacement.find, replacement.replaceWith)); } } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping replacement for {0}/{1} because it does not exist or is empty.", configType, replacement.key)); } } for (Insert insert : insertions) { String valueToInsertInto = newValues.get(insert.key); if (StringUtils.isNotBlank(valueToInsertInto)) { if (StringUtils.contains(valueToInsertInto, insert.value)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("Skipping insertion for {0}/{1} because it already contains {2}", configType, insert.key, insert.value)); continue; } String valueToInsert = insert.value; if (insert.newlineBefore) { valueToInsert = System.lineSeparator() + valueToInsert; } if (insert.newlineAfter) { valueToInsert = valueToInsert + System.lineSeparator(); } switch (insert.insertType) { case APPEND: valueToInsertInto = valueToInsertInto + valueToInsert; break; case PREPEND: valueToInsertInto = valueToInsert + valueToInsertInto; break; default: LOG.error("Unable to insert {0}/{1} with unknown insertion type of {2}", configType, insert.key, insert.insertType); break; } newValues.put(insert.key, valueToInsertInto); updateBufferWithMessage(outputBuffer, MessageFormat.format( "Updated {0}/{1} by inserting {2}", configType, insert.key, insert.value)); } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping insertion for {0}/{1} because it does not exist or is empty.", configType, insert.key)); } } if (!targetStack.equals(currentStack) && targetStack.equals(configStack)) { config.setProperties(newValues); config.save(); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outputBuffer.toString(), ""); } String serviceVersionNote = "Stack Upgrade"; String auditName = getExecutionCommand().getRoleParams().get(ServerAction.ACTION_USER_NAME); if (auditName == null) { auditName = m_configuration.getAnonymousAuditName(); } m_configHelper.createConfigType(cluster, m_controller, configType, newValues, auditName, serviceVersionNote); String message = "Finished updating configuration ''{0}''"; message = MessageFormat.format(message, configType); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", message, ""); }  @Override CommandReport execute(
      ConcurrentMap<String, Object> requestSharedDataContext); }
ConfigureAction extends AbstractServerAction { @Override public CommandReport execute( ConcurrentMap<String, Object> requestSharedDataContext) throws AmbariException, InterruptedException { Map<String,String> commandParameters = getCommandParameters(); if( null == commandParameters || commandParameters.isEmpty() ){ return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", "Unable to change configuration values without command parameters"); } String clusterName = commandParameters.get("clusterName"); Cluster cluster = m_clusters.getCluster(clusterName); String configType = commandParameters.get(ConfigureTask.PARAMETER_CONFIG_TYPE); List<ConfigurationKeyValue> keyValuePairs = Collections.emptyList(); String keyValuePairJson = commandParameters.get(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS); if (null != keyValuePairJson) { keyValuePairs = m_gson.fromJson( keyValuePairJson, new TypeToken<List<ConfigurationKeyValue>>(){}.getType()); keyValuePairs = getAllowedSets(cluster, configType, keyValuePairs); } List<Transfer> transfers = Collections.emptyList(); String transferJson = commandParameters.get(ConfigureTask.PARAMETER_TRANSFERS); if (null != transferJson) { transfers = m_gson.fromJson( transferJson, new TypeToken<List<Transfer>>(){}.getType()); transfers = getAllowedTransfers(cluster, configType, transfers); } List<Replace> replacements = Collections.emptyList(); String replaceJson = commandParameters.get(ConfigureTask.PARAMETER_REPLACEMENTS); if (null != replaceJson) { replacements = m_gson.fromJson( replaceJson, new TypeToken<List<Replace>>(){}.getType()); replacements = getAllowedReplacements(cluster, configType, replacements); } List<Insert> insertions = Collections.emptyList(); String insertJson = commandParameters.get(ConfigureTask.PARAMETER_INSERTIONS); if (null != insertJson) { insertions = m_gson.fromJson( insertJson, new TypeToken<List<Insert>>(){}.getType()); } if (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty()) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); StringBuilder buffer = new StringBuilder( "Skipping this configuration task since none of the conditions were met and there are no transfers, replacements, or insertions.").append("\n"); buffer.append(message); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", buffer.toString(), ""); } if (null == clusterName || null == configType || (keyValuePairs.isEmpty() && transfers.isEmpty() && replacements.isEmpty() && insertions.isEmpty())) { String message = "cluster={0}, type={1}, transfers={2}, replacements={3}, insertions={4}, configurations={5}"; message = MessageFormat.format(message, clusterName, configType, transfers, replacements, insertions, keyValuePairs); return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", message); } Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs(); DesiredConfig desiredConfig = desiredConfigs.get(configType); if (desiredConfig == null) { throw new AmbariException("Could not find desired config type with name " + configType); } Config config = cluster.getConfig(configType, desiredConfig.getTag()); if (config == null) { throw new AmbariException("Could not find config type with name " + configType); } StackId currentStack = cluster.getCurrentStackVersion(); StackId targetStack = cluster.getDesiredStackVersion(); StackId configStack = config.getStackId(); Map<String, String> base = config.getProperties(); Map<String, String> newValues = new HashMap<>(base); boolean changedValues = false; StringBuilder outputBuffer = new StringBuilder(250); for (Transfer transfer : transfers) { switch (transfer.operation) { case COPY: String valueToCopy = null; if( null == transfer.fromType ) { valueToCopy = base.get(transfer.fromKey); } else { Config other = cluster.getDesiredConfigByType(transfer.fromType); if (null != other){ Map<String, String> otherValues = other.getProperties(); if (otherValues.containsKey(transfer.fromKey)){ valueToCopy = otherValues.get(transfer.fromKey); } } } if (StringUtils.isBlank(valueToCopy) && !StringUtils.isBlank(transfer.defaultValue)) { valueToCopy = transfer.defaultValue; } if (StringUtils.isNotBlank(valueToCopy)) { if (transfer.coerceTo != null) { switch (transfer.coerceTo) { case YAML_ARRAY: { String[] splitValues = StringUtils.split(valueToCopy, ','); List<String> quotedValues = new ArrayList<>(splitValues.length); for (String splitValue : splitValues) { quotedValues.add("'" + StringUtils.trim(splitValue) + "'"); } valueToCopy = "[" + StringUtils.join(quotedValues, ',') + "]"; break; } default: break; } } changedValues = true; newValues.put(transfer.toKey, valueToCopy); updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} = \"{2}\"", configType, transfer.toKey, mask(transfer, valueToCopy))); } break; case MOVE: if (newValues.containsKey(transfer.fromKey)) { newValues.put(transfer.toKey, newValues.remove(transfer.fromKey)); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Renamed {0}/{1} to {2}/{3}", configType, transfer.fromKey, configType, transfer.toKey)); } else if (StringUtils.isNotBlank(transfer.defaultValue)) { newValues.put(transfer.toKey, transfer.defaultValue); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Created {0}/{1} with default value \"{2}\"", configType, transfer.toKey, mask(transfer, transfer.defaultValue))); } break; case DELETE: if ("*".equals(transfer.deleteKey)) { newValues.clear(); updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted all keys from {0}", configType)); for (String keeper : transfer.keepKeys) { if (base.containsKey(keeper) && base.get(keeper) != null) { newValues.put(keeper, base.get(keeper)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, keeper)); } } if (transfer.preserveEdits) { List<String> edited = findValuesToPreserve(clusterName, config); for (String changed : edited) { newValues.put(changed, base.get(changed)); updateBufferWithMessage(outputBuffer, MessageFormat.format("Preserved {0}/{1} after delete", configType, changed)); } } changedValues = true; } else { newValues.remove(transfer.deleteKey); changedValues = true; updateBufferWithMessage(outputBuffer, MessageFormat.format("Deleted {0}/{1}", configType, transfer.deleteKey)); } break; } } if (null != keyValuePairs && !keyValuePairs.isEmpty()) { for (ConfigurationKeyValue keyValuePair : keyValuePairs) { String key = keyValuePair.key; String value = keyValuePair.value; if (null != key) { String oldValue = base.get(key); if (null != oldValue && value.equals(oldValue)) { if (currentStack.equals(targetStack) && !changedValues) { updateBufferWithMessage(outputBuffer, MessageFormat.format( "{0}/{1} for cluster {2} would not change, skipping setting", configType, key, clusterName)); continue; } } newValues.put(key, value); final String message; if (StringUtils.isEmpty(value)) { message = MessageFormat.format("{0}/{1} changed to an empty value", configType, key); } else { message = MessageFormat.format("{0}/{1} changed to \"{2}\"", configType, key, mask(keyValuePair, value)); } updateBufferWithMessage(outputBuffer, message); } } } for (Replace replacement : replacements) { String toReplace = newValues.get(replacement.key); if (StringUtils.isNotBlank(toReplace)) { if (!toReplace.contains(replacement.find)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("String \"{0}\" was not found in {1}/{2}", replacement.find, configType, replacement.key)); } else { String replaced = StringUtils.replace(toReplace, replacement.find, replacement.replaceWith); newValues.put(replacement.key, replaced); updateBufferWithMessage(outputBuffer, MessageFormat.format("Replaced {0}/{1} containing \"{2}\" with \"{3}\"", configType, replacement.key, replacement.find, replacement.replaceWith)); } } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping replacement for {0}/{1} because it does not exist or is empty.", configType, replacement.key)); } } for (Insert insert : insertions) { String valueToInsertInto = newValues.get(insert.key); if (StringUtils.isNotBlank(valueToInsertInto)) { if (StringUtils.contains(valueToInsertInto, insert.value)) { updateBufferWithMessage(outputBuffer, MessageFormat.format("Skipping insertion for {0}/{1} because it already contains {2}", configType, insert.key, insert.value)); continue; } String valueToInsert = insert.value; if (insert.newlineBefore) { valueToInsert = System.lineSeparator() + valueToInsert; } if (insert.newlineAfter) { valueToInsert = valueToInsert + System.lineSeparator(); } switch (insert.insertType) { case APPEND: valueToInsertInto = valueToInsertInto + valueToInsert; break; case PREPEND: valueToInsertInto = valueToInsert + valueToInsertInto; break; default: LOG.error("Unable to insert {0}/{1} with unknown insertion type of {2}", configType, insert.key, insert.insertType); break; } newValues.put(insert.key, valueToInsertInto); updateBufferWithMessage(outputBuffer, MessageFormat.format( "Updated {0}/{1} by inserting {2}", configType, insert.key, insert.value)); } else { updateBufferWithMessage(outputBuffer, MessageFormat.format( "Skipping insertion for {0}/{1} because it does not exist or is empty.", configType, insert.key)); } } if (!targetStack.equals(currentStack) && targetStack.equals(configStack)) { config.setProperties(newValues); config.save(); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outputBuffer.toString(), ""); } String serviceVersionNote = "Stack Upgrade"; String auditName = getExecutionCommand().getRoleParams().get(ServerAction.ACTION_USER_NAME); if (auditName == null) { auditName = m_configuration.getAnonymousAuditName(); } m_configHelper.createConfigType(cluster, m_controller, configType, newValues, auditName, serviceVersionNote); String message = "Finished updating configuration ''{0}''"; message = MessageFormat.format(message, configType); return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", message, ""); }  @Override CommandReport execute(
      ConcurrentMap<String, Object> requestSharedDataContext);  }