You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by di...@apache.org on 2016/02/29 14:51:07 UTC

ambari git commit: AMBARI-15132: in upgrade.xml to support set/replace/transfer (dili)

Repository: ambari
Updated Branches:
  refs/heads/trunk c4e5cdf5c -> 771deecd2


AMBARI-15132: <condition> in upgrade.xml to support set/replace/transfer (dili)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/771deecd
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/771deecd
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/771deecd

Branch: refs/heads/trunk
Commit: 771deecd2a2f7d04e354f211ca64f3b2f41e6043
Parents: c4e5cdf
Author: Di Li <di...@apache.org>
Authored: Mon Feb 29 08:49:38 2016 -0500
Committer: Di Li <di...@apache.org>
Committed: Mon Feb 29 08:49:38 2016 -0500

----------------------------------------------------------------------
 .../serveraction/upgrades/ConfigureAction.java  |  143 ++-
 .../upgrade/ConfigUpgradeChangeDefinition.java  |   68 +-
 .../state/stack/upgrade/ConfigureTask.java      |  146 +--
 .../upgrades/ConfigureActionTest.java           | 1004 ++++++++++++++++++
 .../ambari/server/state/UpgradeHelperTest.java  |  182 +++-
 .../HDP/2.1.1/upgrades/config-upgrade.xml       |  113 +-
 .../stacks/HDP/2.1.1/upgrades/upgrade_test.xml  |    2 +
 7 files changed, 1534 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/771deecd/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
index e77cf36..f7de8a9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
@@ -44,7 +44,11 @@ import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinitio
 import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Replace;
 import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Transfer;
 import org.apache.ambari.server.state.stack.upgrade.ConfigureTask;
+import org.apache.ambari.server.state.stack.upgrade.PropertyKeyState;
+import org.apache.ambari.server.state.stack.upgrade.TransferOperation;
 import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -78,6 +82,8 @@ import java.util.concurrent.ConcurrentMap;
  */
 public class ConfigureAction extends AbstractServerAction {
 
+  private static Logger LOG = LoggerFactory.getLogger(ConfigureAction.class);
+
   /**
    * Used to lookup the cluster.
    */
@@ -173,6 +179,7 @@ public class ConfigureAction extends AbstractServerAction {
     }
 
     String clusterName = commandParameters.get("clusterName");
+    Cluster cluster = m_clusters.getCluster(clusterName);
 
     // such as hdfs-site or hbase-env
     String configType = commandParameters.get(ConfigureTask.PARAMETER_CONFIG_TYPE);
@@ -183,6 +190,7 @@ public class ConfigureAction extends AbstractServerAction {
     if (null != keyValuePairJson) {
       keyValuePairs = m_gson.fromJson(
           keyValuePairJson, new TypeToken<List<ConfigurationKeyValue>>(){}.getType());
+      keyValuePairs = getAllowedSets(cluster, configType, keyValuePairs);
     }
 
     // extract transfers
@@ -191,6 +199,7 @@ public class ConfigureAction extends AbstractServerAction {
     if (null != transferJson) {
       transfers = m_gson.fromJson(
         transferJson, new TypeToken<List<Transfer>>(){}.getType());
+      transfers = getAllowedTransfers(cluster, configType, transfers);
     }
 
     // extract replacements
@@ -199,6 +208,7 @@ public class ConfigureAction extends AbstractServerAction {
     if (null != replaceJson) {
       replacements = m_gson.fromJson(
           replaceJson, new TypeToken<List<Replace>>(){}.getType());
+      replacements = getAllowedReplacements(cluster, configType, replacements);
     }
 
     // if there is nothing to do, then skip the task
@@ -224,8 +234,6 @@ public class ConfigureAction extends AbstractServerAction {
       return createCommandReport(0, HostRoleStatus.FAILED, "{}", "", message);
     }
 
-    Cluster cluster = m_clusters.getCluster(clusterName);
-
     Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
     DesiredConfig desiredConfig = desiredConfigs.get(configType);
     Config config = cluster.getConfig(configType, desiredConfig.getTag());
@@ -550,4 +558,135 @@ public class ConfigureAction extends AbstractServerAction {
     return value;
   }
 
+  private List<Replace> getAllowedReplacements(Cluster cluster, String configType, List<Replace> replacements){
+    List<Replace> allowedReplacements= new ArrayList<>();
+
+    for(Replace replacement: replacements){
+      if(isOperationAllowed(cluster, configType, replacement.key,
+          replacement.ifKey, replacement.ifType, replacement.ifValue, replacement.ifKeyState))
+        allowedReplacements.add(replacement);
+    }
+
+    return allowedReplacements;
+  }
+
+  private List<ConfigurationKeyValue> getAllowedSets(Cluster cluster, String configType, List<ConfigurationKeyValue> sets){
+    List<ConfigurationKeyValue> allowedSets = new ArrayList<>();
+
+    for(ConfigurationKeyValue configurationKeyValue: sets){
+      if(isOperationAllowed(cluster, configType, configurationKeyValue.key,
+          configurationKeyValue.ifKey, configurationKeyValue.ifType, configurationKeyValue.ifValue, configurationKeyValue.ifKeyState))
+        allowedSets.add(configurationKeyValue);
+    }
+
+    return allowedSets;
+  }
+
+  private List<Transfer> getAllowedTransfers(Cluster cluster, String configType, List<Transfer> transfers){
+    List<Transfer> allowedTransfers = new ArrayList<>();
+    for (Transfer transfer : transfers) {
+      String key = "";
+      if(transfer.operation == TransferOperation.DELETE)
+        key = transfer.deleteKey;
+      else
+        key = transfer.fromKey;
+
+      if(isOperationAllowed(cluster, configType, key,
+          transfer.ifKey, transfer.ifType, transfer.ifValue, transfer.ifKeyState))
+        allowedTransfers.add(transfer);
+    }
+
+    return allowedTransfers;
+  }
+
+  private boolean isOperationAllowed(Cluster cluster, String configType, String targetPropertyKey,
+      String ifKey, String ifType, String ifValue, PropertyKeyState ifKeyState){
+    boolean isAllowed = true;
+
+    boolean ifKeyIsNotBlank = StringUtils.isNotBlank(ifKey);
+    boolean ifTypeIsNotBlank = StringUtils.isNotBlank(ifType);
+
+    if (ifKeyIsNotBlank && ifTypeIsNotBlank && ifKeyState == PropertyKeyState.ABSENT) {
+      boolean keyPresent = getDesiredConfigurationKeyPresence(cluster, ifType, ifKey);
+      if (keyPresent) {
+        LOG.info("Skipping property operation for {}/{} as the key {} for {} is present",
+          configType, targetPropertyKey, ifKey, ifType);
+        isAllowed = false;
+      }
+    } else if (ifKeyIsNotBlank && ifTypeIsNotBlank && ifValue == null &&
+      ifKeyState == PropertyKeyState.PRESENT) {
+      boolean keyPresent = getDesiredConfigurationKeyPresence(cluster, ifType, ifKey);
+      if (!keyPresent) {
+        LOG.info("Skipping property operation for {}/{} as the key {} for {} is not present",
+          configType, targetPropertyKey, ifKey, ifType);
+        isAllowed = false;
+      }
+    } else if (ifKeyIsNotBlank && ifTypeIsNotBlank && ifValue != null) {
+
+      String ifConfigType = ifType;
+      String checkValue = getDesiredConfigurationValue(cluster, ifConfigType, ifKey);
+      if (!ifValue.toLowerCase().equals(StringUtils.lowerCase(checkValue))) {
+        // skip adding
+        LOG.info("Skipping property operation for {}/{} as the value {} for {}/{} is not equal to {}",
+                 configType, targetPropertyKey, checkValue, ifConfigType, ifKey, ifValue);
+        isAllowed = false;
+      }
+    }
+
+    return isAllowed;
+  }
+
+  /**
+   * Gets the property presence state
+   * @param cluster
+   *          the cluster (not {@code null}).
+   * @param configType
+   *          the configuration type (ie hdfs-site) (not {@code null}).
+   * @param propertyKey
+   *          the key to retrieve (not {@code null}).
+   * @return {@code true} if property key exists or {@code false} if not.
+   */
+  private boolean getDesiredConfigurationKeyPresence(Cluster cluster,
+      String configType, String propertyKey) {
+
+    Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
+    DesiredConfig desiredConfig = desiredConfigs.get(configType);
+    if (null == desiredConfig) {
+      return false;
+    }
+
+    Config config = cluster.getConfig(configType, desiredConfig.getTag());
+    if (null == config) {
+      return false;
+    }
+    return config.getProperties().containsKey(propertyKey);
+  }
+
+  /**
+   * Gets the value of the specified cluster property.
+   *
+   * @param cluster
+   *          the cluster (not {@code null}).
+   * @param configType
+   *          the configuration type (ie hdfs-site) (not {@code null}).
+   * @param propertyKey
+   *          the key to retrieve (not {@code null}).
+   * @return the value or {@code null} if it does not exist.
+   */
+  private String getDesiredConfigurationValue(Cluster cluster,
+      String configType, String propertyKey) {
+
+    Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
+    DesiredConfig desiredConfig = desiredConfigs.get(configType);
+    if (null == desiredConfig) {
+      return null;
+    }
+
+    Config config = cluster.getConfig(configType, desiredConfig.getTag());
+    if (null == config) {
+      return null;
+    }
+
+    return config.getProperties().get(propertyKey);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/771deecd/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java
index a4dff2e..54431eb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigUpgradeChangeDefinition.java
@@ -214,6 +214,30 @@ public class ConfigUpgradeChangeDefinition {
   public static class Masked {
     @XmlAttribute(name = "mask")
     public boolean mask = false;
+
+    /**
+     * The key to read for the if condition.
+     */
+    @XmlAttribute(name = "if-key")
+    public String ifKey;
+
+    /**
+     * The config type to read for the if condition.
+     */
+    @XmlAttribute(name = "if-type")
+    public String ifType;
+
+    /**
+     * The property value to compare against for the if condition.
+     */
+    @XmlAttribute(name = "if-value")
+    public String ifValue;
+
+    /**
+     * The property key state for the if condition
+     */
+    @XmlAttribute(name = "if-key-state")
+    public PropertyKeyState ifKeyState;
   }
 
 
@@ -228,6 +252,18 @@ public class ConfigUpgradeChangeDefinition {
 
     @XmlAttribute(name = "value")
     public String value;
+
+    @Override
+    public String toString() {
+      return "Set{" +
+              ", key='" + key + '\'' +
+              ", value='" + value + '\'' +
+              ", ifKey='" + ifKey + '\'' +
+              ", ifType='" + ifType + '\'' +
+              ", ifValue='" + ifValue + '\'' +
+              ", ifKeyState='" + ifKeyState + '\'' +
+              '}';
+    }
   }
 
   /**
@@ -337,33 +373,6 @@ public class ConfigUpgradeChangeDefinition {
     @XmlAttribute(name = "coerce-to")
     public TransferCoercionType coerceTo;
 
-    // if the condition is true apply the transfer action
-    // only supported conditional action is DELETE
-    // if-type/if-key == if-value
-    /**
-     * The key to read for the if condition.
-     */
-    @XmlAttribute(name = "if-key")
-    public String ifKey;
-
-    /**
-     * The config type to read for the if condition.
-     */
-    @XmlAttribute(name = "if-type")
-    public String ifType;
-
-    /**
-     * The property value to compare against for the if condition.
-     */
-    @XmlAttribute(name = "if-value")
-    public String ifValue;
-
-    /**
-     * The property key state for the if condition
-     */
-    @XmlAttribute(name = "if-key-state")
-    public PropertyKeyState ifKeyState;
-
     /**
      * The keys to keep when the action is {@link TransferOperation#DELETE}.
      */
@@ -422,8 +431,11 @@ public class ConfigUpgradeChangeDefinition {
               "key='" + key + '\'' +
               ", find='" + find + '\'' +
               ", replaceWith='" + replaceWith + '\'' +
+              ", ifKey='" + ifKey + '\'' +
+              ", ifType='" + ifType + '\'' +
+              ", ifValue='" + ifValue + '\'' +
+              ", ifKeyState='" + ifKeyState + '\'' +
               '}';
     }
   }
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/771deecd/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java
index 6b22f58..343c484 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/ConfigureTask.java
@@ -233,69 +233,96 @@ public class ConfigureTask extends ServerSideActionTask {
 
     // for every <set key=foo value=bar/> add it to this list
     if (null != definition.getKeyValuePairs() && !definition.getKeyValuePairs().isEmpty()) {
+      List<ConfigurationKeyValue> allowedSets = getValidSets(cluster, definition.getConfigType(), definition.getKeyValuePairs());
       configParameters.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS,
-          m_gson.toJson(definition.getKeyValuePairs()));
+          m_gson.toJson(allowedSets));
     }
 
     // transfers
     List<Transfer> transfers = definition.getTransfers();
     if (null != transfers && !transfers.isEmpty()) {
-
-      List<Transfer> allowedTransfers = new ArrayList<>();
-      for (Transfer transfer : transfers) {
-        if (transfer.operation == TransferOperation.DELETE) {
-          boolean ifKeyIsNotBlank = StringUtils.isNotBlank(transfer.ifKey);
-          boolean ifTypeIsNotBlank = StringUtils.isNotBlank(transfer.ifType);
-
-          //  value doesn't required for Key Check
-          if (ifKeyIsNotBlank && ifTypeIsNotBlank && transfer.ifKeyState == PropertyKeyState.ABSENT) {
-            boolean keyPresent = getDesiredConfigurationKeyPresence(cluster, transfer.ifType, transfer.ifKey);
-            if (keyPresent) {
-              LOG.info("Skipping property delete for {}/{} as the key {} for {} is present",
-                definition.getConfigType(), transfer.deleteKey, transfer.ifKey, transfer.ifType);
-              continue;
-            }
-          }
-
-          if (ifKeyIsNotBlank && ifTypeIsNotBlank && transfer.ifValue == null &&
-            transfer.ifKeyState == PropertyKeyState.PRESENT) {
-            boolean keyPresent = getDesiredConfigurationKeyPresence(cluster, transfer.ifType, transfer.ifKey);
-            if (!keyPresent) {
-              LOG.info("Skipping property delete for {}/{} as the key {} for {} is not present",
-                definition.getConfigType(), transfer.deleteKey, transfer.ifKey, transfer.ifType);
-              continue;
-            }
-          }
-
-          if (ifKeyIsNotBlank && ifTypeIsNotBlank && transfer.ifValue != null) {
-
-            String ifConfigType = transfer.ifType;
-            String ifKey = transfer.ifKey;
-            String ifValue = transfer.ifValue;
-
-            String checkValue = getDesiredConfigurationValue(cluster, ifConfigType, ifKey);
-            if (!ifValue.toLowerCase().equals(StringUtils.lowerCase(checkValue))) {
-              // skip adding
-              LOG.info("Skipping property delete for {}/{} as the value {} for {}/{} is not equal to {}",
-                       definition.getConfigType(), transfer.deleteKey, checkValue, ifConfigType, ifKey, ifValue);
-              continue;
-            }
-          }
-        }
-        allowedTransfers.add(transfer);
-      }
+      List<Transfer> allowedTransfers = getValidTransfers(cluster, definition.getConfigType(), definition.getTransfers());
       configParameters.put(ConfigureTask.PARAMETER_TRANSFERS, m_gson.toJson(allowedTransfers));
     }
 
     // replacements
     List<Replace> replacements = definition.getReplacements();
     if( null != replacements && !replacements.isEmpty() ){
-      configParameters.put(ConfigureTask.PARAMETER_REPLACEMENTS, m_gson.toJson(replacements));
+      List<Replace> allowedReplacements = getValidReplacements(cluster, definition.getConfigType(), replacements);
+      configParameters.put(ConfigureTask.PARAMETER_REPLACEMENTS, m_gson.toJson(allowedReplacements));
     }
 
     return configParameters;
   }
 
+  private List<Replace> getValidReplacements(Cluster cluster, String configType, List<Replace> replacements){
+    List<Replace> allowedReplacements= new ArrayList<>();
+
+    for(Replace replacement: replacements){
+      if(isValidConditionSettings(cluster, configType, replacement.key,
+          replacement.ifKey, replacement.ifType, replacement.ifValue, replacement.ifKeyState))
+        allowedReplacements.add(replacement);
+    }
+
+    return allowedReplacements;
+  }
+
+  private List<ConfigurationKeyValue> getValidSets(Cluster cluster, String configType, List<ConfigurationKeyValue> sets){
+    List<ConfigurationKeyValue> allowedSets = new ArrayList<>();
+
+    for(ConfigurationKeyValue configurationKeyValue: sets){
+      if(isValidConditionSettings(cluster, configType, configurationKeyValue.key,
+          configurationKeyValue.ifKey, configurationKeyValue.ifType, configurationKeyValue.ifValue, configurationKeyValue.ifKeyState))
+        allowedSets.add(configurationKeyValue);
+    }
+
+    return allowedSets;
+  }
+
+  private List<Transfer> getValidTransfers(Cluster cluster, String configType, List<Transfer> transfers){
+    List<Transfer> allowedTransfers = new ArrayList<>();
+    for (Transfer transfer : transfers) {
+      String key = "";
+      if(transfer.operation == TransferOperation.DELETE)
+        key = transfer.deleteKey;
+      else
+        key = transfer.fromKey;
+
+      if(isValidConditionSettings(cluster, configType, key,
+          transfer.ifKey, transfer.ifType, transfer.ifValue, transfer.ifKeyState))
+        allowedTransfers.add(transfer);
+    }
+
+    return allowedTransfers;
+  }
+
+  /**
+   * Sanity check for invalid attribute settings on if-key, if-value, if-key-state, if-site
+   * Regardless whether it's set, transfrer, or replace, the condition attributres are the same
+   * So the same logic can be used to determine if the operation is allowed or not.
+   * */
+  private boolean isValidConditionSettings(Cluster cluster, String configType, String targetPropertyKey,
+      String ifKey, String ifType, String ifValue, PropertyKeyState ifKeyState){
+
+    //Operation is always valid if there are no conditions specified
+    boolean isValid = false;
+
+    boolean ifKeyIsNotBlank = StringUtils.isNotBlank(ifKey);
+    boolean ifTypeIsNotBlank = StringUtils.isNotBlank(ifType);
+    boolean ifValueIsNotNull = (null != ifValue);
+    boolean ifKeyStateIsValid = (PropertyKeyState.PRESENT == ifKeyState || PropertyKeyState.ABSENT == ifKeyState);
+
+    if(ifKeyIsNotBlank && ifTypeIsNotBlank && (ifValueIsNotNull || ifKeyStateIsValid)) {
+      // allow if the condition has ifKey, ifType and either ifValue or ifKeyState
+      isValid = true;
+    } else if (!ifKeyIsNotBlank && !ifTypeIsNotBlank && !ifValueIsNotNull &&  !ifKeyStateIsValid) {
+      //no condition, allow
+      isValid = true;
+    }
+
+    return isValid;
+  }
+
   /**
    * Gets the value of the specified cluster property.
    *
@@ -323,31 +350,4 @@ public class ConfigureTask extends ServerSideActionTask {
 
     return config.getProperties().get(propertyKey);
   }
-
-  /**
-   * Gets the property presence state
-   * @param cluster
-   *          the cluster (not {@code null}).
-   * @param configType
-   *          the configuration type (ie hdfs-site) (not {@code null}).
-   * @param propertyKey
-   *          the key to retrieve (not {@code null}).
-   * @return {@code true} if property key exists or {@code false} if not.
-   */
-  private boolean getDesiredConfigurationKeyPresence(Cluster cluster,
-      String configType, String propertyKey) {
-
-    Map<String, DesiredConfig> desiredConfigs = cluster.getDesiredConfigs();
-    DesiredConfig desiredConfig = desiredConfigs.get(configType);
-    if (null == desiredConfig) {
-      return false;
-    }
-
-    Config config = cluster.getConfig(configType, desiredConfig.getTag());
-    if (null == config) {
-      return false;
-    }
-    return config.getProperties().containsKey(propertyKey);
-  }
-
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/771deecd/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
index ce87668..be0aeef 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
@@ -53,6 +53,7 @@ import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinitio
 import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Replace;
 import org.apache.ambari.server.state.stack.upgrade.ConfigUpgradeChangeDefinition.Transfer;
 import org.apache.ambari.server.state.stack.upgrade.ConfigureTask;
+import org.apache.ambari.server.state.stack.upgrade.PropertyKeyState;
 import org.apache.ambari.server.state.stack.upgrade.TransferCoercionType;
 import org.apache.ambari.server.state.stack.upgrade.TransferOperation;
 import org.junit.After;
@@ -658,6 +659,1009 @@ public class ConfigureActionTest {
 
   }
 
+  @Test
+  public void testAllowedSet() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setCurrentStackVersion(HDP_211_STACK);
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {
+      {
+        put("set.key.1", "s1");
+        put("set.key.2", "s2");
+        put("set.key.3", "s3");
+        put("set.key.4", "s4");
+      }
+    }, new HashMap<String, Map<String, String>>());
+
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    // create several configurations
+    List<ConfigurationKeyValue> configurations = new ArrayList<ConfigurationKeyValue>();
+    ConfigurationKeyValue fooKey1 = new ConfigurationKeyValue();
+    configurations.add(fooKey1);
+    fooKey1.key = "fooKey1";
+    fooKey1.value = "barValue1";
+
+    ConfigurationKeyValue fooKey2 = new ConfigurationKeyValue();
+    configurations.add(fooKey2);
+    fooKey2.key = "fooKey2";
+    fooKey2.value = "barValue2";
+
+    ConfigurationKeyValue fooKey3 = new ConfigurationKeyValue();
+    configurations.add(fooKey3);
+    fooKey3.key = "fooKey3";
+    fooKey3.value = "barValue3";
+    fooKey3.ifKey = "set.key.1";
+    fooKey3.ifType = "zoo.cfg";
+    fooKey3.ifValue = "s1";
+
+    ConfigurationKeyValue fooKey4 = new ConfigurationKeyValue();
+    configurations.add(fooKey4);
+    fooKey4.key = "fooKey4";
+    fooKey4.value = "barValue4";
+    fooKey4.ifKey = "set.key.2";
+    fooKey4.ifType = "zoo.cfg";
+    fooKey4.ifKeyState= PropertyKeyState.PRESENT;
+
+    ConfigurationKeyValue fooKey5 = new ConfigurationKeyValue();
+    configurations.add(fooKey5);
+    fooKey5.key = "fooKey5";
+    fooKey5.value = "barValue5";
+    fooKey5.ifKey = "abc";
+    fooKey5.ifType = "zoo.cfg";
+    fooKey5.ifKeyState= PropertyKeyState.ABSENT;
+
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    ExecutionCommand executionCommand = new ExecutionCommand();
+    executionCommand.setCommandParams(commandParams);
+    executionCommand.setClusterName("c1");
+
+    HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null);
+    hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    action.setExecutionCommand(executionCommand);
+    action.setHostRoleCommand(hostRoleCommand);
+
+    CommandReport report = action.execute(null);
+    assertNotNull(report);
+
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    config = c.getDesiredConfigByType("zoo.cfg");
+    assertNotNull(config);
+    assertEquals("barValue1", config.getProperties().get("fooKey1"));
+    assertEquals("barValue2", config.getProperties().get("fooKey2"));
+    assertEquals("barValue3", config.getProperties().get("fooKey3"));
+    assertEquals("barValue4", config.getProperties().get("fooKey4"));
+    assertEquals("barValue5", config.getProperties().get("fooKey5"));
+    assertEquals("s1", config.getProperties().get("set.key.1"));
+    assertEquals("s2", config.getProperties().get("set.key.2"));
+    assertEquals("s3", config.getProperties().get("set.key.3"));
+    assertEquals("s4", config.getProperties().get("set.key.4"));
+  }
+
+  @Test
+  public void testDisallowedSet() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setCurrentStackVersion(HDP_211_STACK);
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {
+      {
+        put("set.key.1", "s1");
+        put("set.key.2", "s2");
+        put("set.key.3", "s3");
+        put("set.key.4", "s4");
+      }
+    }, new HashMap<String, Map<String, String>>());
+
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    // create several configurations
+    List<ConfigurationKeyValue> configurations = new ArrayList<ConfigurationKeyValue>();
+    ConfigurationKeyValue fooKey3 = new ConfigurationKeyValue();
+    configurations.add(fooKey3);
+    fooKey3.key = "fooKey3";
+    fooKey3.value = "barValue3";
+    fooKey3.ifKey = "set.key.1";
+    fooKey3.ifType = "zoo.cfg";
+    fooKey3.ifValue = "no-such-value";
+
+    ConfigurationKeyValue fooKey4 = new ConfigurationKeyValue();
+    configurations.add(fooKey4);
+    fooKey4.key = "fooKey4";
+    fooKey4.value = "barValue4";
+    fooKey4.ifKey = "set.key.2";
+    fooKey4.ifType = "zoo.cfg";
+    fooKey4.ifKeyState= PropertyKeyState.ABSENT;
+
+    ConfigurationKeyValue fooKey5 = new ConfigurationKeyValue();
+    configurations.add(fooKey5);
+    fooKey5.key = "fooKey5";
+    fooKey5.value = "barValue5";
+    fooKey5.ifKey = "abc";
+    fooKey5.ifType = "zoo.cfg";
+    fooKey5.ifKeyState= PropertyKeyState.PRESENT;
+
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    ExecutionCommand executionCommand = new ExecutionCommand();
+    executionCommand.setCommandParams(commandParams);
+    executionCommand.setClusterName("c1");
+
+    HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null);
+    hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    action.setExecutionCommand(executionCommand);
+    action.setHostRoleCommand(hostRoleCommand);
+
+    CommandReport report = action.execute(null);
+    assertNotNull(report);
+
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    config = c.getDesiredConfigByType("zoo.cfg");
+    assertNotNull(config);
+    assertEquals("s1", config.getProperties().get("set.key.1"));
+    assertEquals("s2", config.getProperties().get("set.key.2"));
+    assertEquals("s3", config.getProperties().get("set.key.3"));
+    assertEquals("s4", config.getProperties().get("set.key.4"));
+    assertFalse(config.getProperties().containsKey("fooKey3"));
+    assertFalse(config.getProperties().containsKey("fooKey4"));
+    assertFalse(config.getProperties().containsKey("fooKey5"));
+  }
+
+  @Test
+  public void testAllowedReplacment() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setCurrentStackVersion(HDP_211_STACK);
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {
+      {
+        put("replace.key.1", "r1");
+        put("replace.key.2", "r2");
+        put("replace.key.3", "r3a1");
+        put("replace.key.4", "r4");
+        put("replace.key.5", "r5");
+      }
+    }, new HashMap<String, Map<String, String>>());
+
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    // create several configurations
+    List<Replace> replacements = new ArrayList<Replace>();
+    Replace replace = new Replace();
+    replace.key = "replace.key.3";
+    replace.find = "a";
+    replace.replaceWith = "A";
+    replacements.add(replace);
+
+    Replace replace2 = new Replace();
+    replacements.add(replace2);
+    replace2.key = "replace.key.4";
+    replace2.find = "r";
+    replace2.replaceWith = "R";
+    replace2.ifKey = "replace.key.1";
+    replace2.ifType = "zoo.cfg";
+    replace2.ifValue = "r1";
+    replacements.add(replace2);
+
+    Replace replace3 = new Replace();
+    replacements.add(replace3);
+    replace3.key = "replace.key.2";
+    replace3.find = "r";
+    replace3.replaceWith = "R";
+    replace3.ifKey = "replace.key.1";
+    replace3.ifType = "zoo.cfg";
+    replace3.ifKeyState = PropertyKeyState.PRESENT;
+    replacements.add(replace3);
+
+    Replace replace4 = new Replace();
+    replacements.add(replace3);
+    replace4.key = "replace.key.5";
+    replace4.find = "r";
+    replace4.replaceWith = "R";
+    replace4.ifKey = "no.such.key";
+    replace4.ifType = "zoo.cfg";
+    replace4.ifKeyState = PropertyKeyState.ABSENT;
+    replacements.add(replace4);
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_REPLACEMENTS, new Gson().toJson(replacements));
+
+    ExecutionCommand executionCommand = new ExecutionCommand();
+    executionCommand.setCommandParams(commandParams);
+    executionCommand.setClusterName("c1");
+
+    HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null);
+    hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    action.setExecutionCommand(executionCommand);
+    action.setHostRoleCommand(hostRoleCommand);
+
+    CommandReport report = action.execute(null);
+    assertNotNull(report);
+
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    config = c.getDesiredConfigByType("zoo.cfg");
+    assertNotNull(config);
+    assertEquals("r1", config.getProperties().get("replace.key.1"));
+    assertEquals("R2", config.getProperties().get("replace.key.2"));
+    assertEquals("r3A1", config.getProperties().get("replace.key.3"));
+    assertEquals("R4", config.getProperties().get("replace.key.4"));
+    assertEquals("R5", config.getProperties().get("replace.key.5"));
+  }
+
+  @Test
+  public void testDisallowedReplacment() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setCurrentStackVersion(HDP_211_STACK);
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {
+      {
+        put("replace.key.1", "r1");
+        put("replace.key.2", "r2");
+        put("replace.key.3", "r3a1");
+        put("replace.key.4", "r4");
+        put("replace.key.5", "r5");
+      }
+    }, new HashMap<String, Map<String, String>>());
+
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    // create several configurations
+    List<Replace> replacements = new ArrayList<Replace>();
+
+    Replace replace2 = new Replace();
+    replacements.add(replace2);
+    replace2.key = "replace.key.4";
+    replace2.find = "r";
+    replace2.replaceWith = "R";
+    replace2.ifKey = "replace.key.1";
+    replace2.ifType = "zoo.cfg";
+    replace2.ifValue = "not-this-value";
+    replacements.add(replace2);
+
+    Replace replace3 = new Replace();
+    replacements.add(replace3);
+    replace3.key = "replace.key.2";
+    replace3.find = "r";
+    replace3.replaceWith = "R";
+    replace3.ifKey = "replace.key.1";
+    replace3.ifType = "zoo.cfg";
+    replace3.ifKeyState = PropertyKeyState.ABSENT;
+    replacements.add(replace3);
+
+    Replace replace4 = new Replace();
+    replacements.add(replace3);
+    replace4.key = "replace.key.5";
+    replace4.find = "r";
+    replace4.replaceWith = "R";
+    replace4.ifKey = "no.such.key";
+    replace4.ifType = "zoo.cfg";
+    replace4.ifKeyState = PropertyKeyState.PRESENT;
+    replacements.add(replace4);
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_REPLACEMENTS, new Gson().toJson(replacements));
+
+    ExecutionCommand executionCommand = new ExecutionCommand();
+    executionCommand.setCommandParams(commandParams);
+    executionCommand.setClusterName("c1");
+
+    HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null);
+    hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    action.setExecutionCommand(executionCommand);
+    action.setHostRoleCommand(hostRoleCommand);
+
+    CommandReport report = action.execute(null);
+    assertNotNull(report);
+
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    config = c.getDesiredConfigByType("zoo.cfg");
+    assertNotNull(config);
+    assertEquals("r1", config.getProperties().get("replace.key.1"));
+    assertEquals("r2", config.getProperties().get("replace.key.2"));
+    assertEquals("r3a1", config.getProperties().get("replace.key.3"));
+    assertEquals("r4", config.getProperties().get("replace.key.4"));
+    assertEquals("r5", config.getProperties().get("replace.key.5"));
+  }
+
+  @Test
+  public void testAllowedTransferCopy() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {{
+          put("initLimit", "10");
+          put("copy.key.1", "c1");
+          put("copy.key.2", "c2");
+        }}, new HashMap<String, Map<String,String>>());
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    List<ConfigurationKeyValue> configurations = new ArrayList<>();
+    ConfigurationKeyValue keyValue = new ConfigurationKeyValue();
+    configurations.add(keyValue);
+    keyValue.key = "initLimit";
+    keyValue.value = "11";
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    // normal copy
+    List<Transfer> transfers = new ArrayList<>();
+    Transfer transfer1 = new Transfer();
+    transfer1.operation = TransferOperation.COPY;
+    transfer1.fromKey = "copy.key.1";
+    transfer1.toKey = "copy.to.key.1";
+    transfers.add(transfer1);
+
+    // copy with default
+    Transfer transfer2 = new Transfer();
+    transfer2.operation = TransferOperation.COPY;
+    transfer2.fromKey = "copy.key.no.need.to.exit.1";
+    transfer2.toKey = "copy.to.key.with.default.1";
+    transfer2.defaultValue = "defaultValue";
+    transfers.add(transfer2);
+
+    Transfer transfer3 = new Transfer();
+    transfer3.operation = TransferOperation.COPY;
+    transfer3.fromKey = "copy.key.2";
+    transfer3.toKey = "copy.to.key.2";
+    transfer3.ifKey = "initLimit";
+    transfer3.ifType = "zoo.cfg";
+    transfer3.ifValue = "10";
+    transfers.add(transfer3);
+
+    Transfer transfer4 = new Transfer();
+    transfer4.operation = TransferOperation.COPY;
+    transfer4.fromKey = "copy.key.2";
+    transfer4.toKey = "copy.to.key.3";
+    transfer4.ifKey = "initLimit";
+    transfer4.ifType = "zoo.cfg";
+    transfer4.ifKeyState = PropertyKeyState.PRESENT;
+    transfers.add(transfer4);
+
+    Transfer transfer5 = new Transfer();
+    transfer5.operation = TransferOperation.COPY;
+    transfer5.fromKey = "copy.key.no.need.to.exist.2";
+    transfer5.toKey = "copy.to.key.with.default.2";
+    transfer5.defaultValue = "defaultValue2";
+    transfer5.ifKey = "no.such.key";
+    transfer5.ifType = "zoo.cfg";
+    transfer5.ifKeyState = PropertyKeyState.ABSENT;
+    transfers.add(transfer5);
+
+    commandParams.put(ConfigureTask.PARAMETER_TRANSFERS, new Gson().toJson(transfers));
+
+    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));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    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()));
+
+    Map<String, String> map = config.getProperties();
+    assertEquals(8, map.size());
+    assertEquals("11", map.get("initLimit"));
+    assertEquals(map.get("copy.key.1"), map.get("copy.to.key.1"));
+    assertTrue(!map.containsKey("copy.key.no.need.to.exit.1"));
+    assertEquals("defaultValue", map.get("copy.to.key.with.default.1"));
+    assertTrue(!map.containsKey("copy.key.no.need.to.exit.2"));
+    assertEquals("defaultValue2", map.get("copy.to.key.with.default.2"));
+    assertEquals(map.get("copy.key.2"), map.get("copy.to.key.2"));
+    assertEquals(map.get("copy.key.2"), map.get("copy.to.key.3"));
+  }
+
+  @Test
+  public void testDisallowedTransferCopy() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {{
+          put("initLimit", "10");
+          put("copy.key.1", "c1");
+          put("copy.key.2", "c2");
+        }}, new HashMap<String, Map<String,String>>());
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    List<ConfigurationKeyValue> configurations = new ArrayList<>();
+    ConfigurationKeyValue keyValue = new ConfigurationKeyValue();
+    configurations.add(keyValue);
+    keyValue.key = "initLimit";
+    keyValue.value = "11";
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    List<Transfer> transfers = new ArrayList<>();
+    Transfer transfer = new Transfer();
+    transfer.operation = TransferOperation.COPY;
+    transfer.fromKey = "copy.key.2";
+    transfer.toKey = "copy.to.key.2";
+    transfer.ifKey = "initLimit";
+    transfer.ifType = "zoo.cfg";
+    transfer.ifValue = "not-the-real-value";
+    transfers.add(transfer);
+
+    transfer = new Transfer();
+    transfer.operation = TransferOperation.COPY;
+    transfer.fromKey = "copy.key.2";
+    transfer.toKey = "copy.to.key.3";
+    transfer.ifKey = "initLimit";
+    transfer.ifType = "zoo.cfg";
+    transfer.ifKeyState = PropertyKeyState.ABSENT;
+    transfers.add(transfer);
+
+    transfer = new Transfer();
+    transfer.operation = TransferOperation.COPY;
+    transfer.fromKey = "copy.key.no.need.to.exist.2";
+    transfer.toKey = "copy.to.key.with.default.2";
+    transfer.defaultValue = "defaultValue2";
+    transfer.ifKey = "no.such.key";
+    transfer.ifType = "zoo.cfg";
+    transfer.ifKeyState = PropertyKeyState.PRESENT;
+    transfers.add(transfer);
+
+    commandParams.put(ConfigureTask.PARAMETER_TRANSFERS, new Gson().toJson(transfers));
+
+    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));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    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()));
+
+    Map<String, String> map = config.getProperties();
+    assertEquals(3, map.size());
+    assertEquals("11", map.get("initLimit"));
+    assertEquals("c1", map.get("copy.key.1"));
+    assertEquals("c2", map.get("copy.key.2"));
+  }
+
+  @Test
+  public void testAllowedTransferMove() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {{
+          put("initLimit", "10");
+          put("move.key.1", "m1");
+          put("move.key.2", "m2");
+          put("move.key.3", "m3");
+          put("move.key.4", "m4");
+        }}, new HashMap<String, Map<String,String>>());
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    List<ConfigurationKeyValue> configurations = new ArrayList<>();
+    ConfigurationKeyValue keyValue = new ConfigurationKeyValue();
+    configurations.add(keyValue);
+    keyValue.key = "initLimit";
+    keyValue.value = "11";
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    List<Transfer> transfers = new ArrayList<>();
+    Transfer transfer1 = new Transfer();
+    transfer1.operation = TransferOperation.MOVE;
+    transfer1.fromKey = "move.key.1";
+    transfer1.toKey = "move.to.key.1";
+    transfers.add(transfer1);
+
+    Transfer transfer2 = new Transfer();
+    transfer2.operation = TransferOperation.MOVE;
+    transfer2.fromKey = "move.key.2";
+    transfer2.toKey = "move.to.key.2";
+    transfer2.ifKey = "initLimit";
+    transfer2.ifType = "zoo.cfg";
+    transfer2.ifValue = "10";
+    transfers.add(transfer2);
+
+    Transfer transfer3 = new Transfer();
+    transfer3.operation = TransferOperation.MOVE;
+    transfer3.fromKey = "move.key.3";
+    transfer3.toKey = "move.to.key.3";
+    transfer3.ifKey = "initLimit";
+    transfer3.ifType = "zoo.cfg";
+    transfer3.ifKeyState = PropertyKeyState.PRESENT;
+    transfers.add(transfer3);
+
+    Transfer transfer4 = new Transfer();
+    transfer4.operation = TransferOperation.MOVE;
+    transfer4.fromKey = "move.key.4";
+    transfer4.toKey = "move.to.key.4";
+    transfer4.ifKey = "no.such.key";
+    transfer4.ifType = "zoo.cfg";
+    transfer4.ifKeyState = PropertyKeyState.ABSENT;
+    transfers.add(transfer4);
+
+    commandParams.put(ConfigureTask.PARAMETER_TRANSFERS, new Gson().toJson(transfers));
+
+    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));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    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()));
+
+    Map<String, String> map = config.getProperties();
+    assertEquals(5, map.size());
+    String[] shouldNotExitKeys = new String[]{"move.key.1", "move.key.2", "move.key.3", "move.key.4"};
+    String[] shouldExitKeys = new String[]{"move.to.key.1", "move.to.key.2", "move.to.key.3", "move.to.key.4"};
+    for(String key: shouldNotExitKeys){
+      assertFalse(map.containsKey(key));
+    }
+
+    for(String key: shouldExitKeys){
+      assertTrue(map.containsKey(key));
+    }
+  }
+
+  @Test
+  public void testDisallowedTransferMove() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {{
+          put("initLimit", "10");
+          put("move.key.1", "m1");
+          put("move.key.2", "m2");
+          put("move.key.3", "m3");
+          put("move.key.4", "m4");
+        }}, new HashMap<String, Map<String,String>>());
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    List<ConfigurationKeyValue> configurations = new ArrayList<>();
+    ConfigurationKeyValue keyValue = new ConfigurationKeyValue();
+    configurations.add(keyValue);
+    keyValue.key = "initLimit";
+    keyValue.value = "11";
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    List<Transfer> transfers = new ArrayList<>();
+    Transfer transfer2 = new Transfer();
+    transfer2.operation = TransferOperation.MOVE;
+    transfer2.fromKey = "move.key.2";
+    transfer2.toKey = "move.to.key.2";
+    transfer2.ifKey = "initLimit";
+    transfer2.ifType = "zoo.cfg";
+    transfer2.ifValue = "not-real-value";
+    transfers.add(transfer2);
+
+    Transfer transfer3 = new Transfer();
+    transfer3.operation = TransferOperation.MOVE;
+    transfer3.fromKey = "move.key.3";
+    transfer3.toKey = "move.to.key.3";
+    transfer3.ifKey = "initLimit";
+    transfer3.ifType = "zoo.cfg";
+    transfer3.ifKeyState = PropertyKeyState.ABSENT;
+    transfers.add(transfer3);
+
+    Transfer transfer4 = new Transfer();
+    transfer4.operation = TransferOperation.MOVE;
+    transfer4.fromKey = "move.key.4";
+    transfer4.toKey = "move.to.key.4";
+    transfer4.ifKey = "no.such.key";
+    transfer4.ifType = "zoo.cfg";
+    transfer4.ifKeyState = PropertyKeyState.PRESENT;
+    transfers.add(transfer3);
+
+    commandParams.put(ConfigureTask.PARAMETER_TRANSFERS, new Gson().toJson(transfers));
+
+    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));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    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()));
+
+    Map<String, String> map = config.getProperties();
+    assertEquals(5, map.size());
+
+    String[] shouldExitKeys = new String[]{"move.key.1", "move.key.2", "move.key.3", "move.key.4"};
+    String[] shouldNotExitKeys = new String[]{"move.to.key.1", "move.to.key.2", "move.to.key.3", "move.to.key.4"};
+    for(String key: shouldNotExitKeys){
+      assertFalse(map.containsKey(key));
+    }
+
+    for(String key: shouldExitKeys){
+      assertTrue(map.containsKey(key));
+    }
+  }
+
+  @Test
+  public void testAllowedTransferDelete() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {{
+          put("initLimit", "10");
+          put("delete.key.1", "d1");
+          put("delete.key.2", "d2");
+          put("delete.key.3", "d3");
+          put("delete.key.4", "d4");
+        }}, new HashMap<String, Map<String,String>>());
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    List<ConfigurationKeyValue> configurations = new ArrayList<>();
+    ConfigurationKeyValue keyValue = new ConfigurationKeyValue();
+    configurations.add(keyValue);
+    keyValue.key = "initLimit";
+    keyValue.value = "11";
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    List<Transfer> transfers = new ArrayList<>();
+    Transfer transfer1 = new Transfer();
+    transfer1.operation = TransferOperation.DELETE;
+    transfer1.deleteKey = "delete.key.1";
+    transfers.add(transfer1);
+
+    Transfer transfer2 = new Transfer();
+    transfer2.operation = TransferOperation.DELETE;
+    transfer2.deleteKey = "delete.key.2";
+    transfer2.ifKey = "initLimit";
+    transfer2.ifType = "zoo.cfg";
+    transfer2.ifValue = "10";
+    transfers.add(transfer2);
+
+    Transfer transfer3 = new Transfer();
+    transfer3.operation = TransferOperation.DELETE;
+    transfer3.deleteKey = "delete.key.3";
+    transfer3.ifKey = "initLimit";
+    transfer3.ifType = "zoo.cfg";
+    transfer3.ifKeyState = PropertyKeyState.PRESENT;
+    transfers.add(transfer3);
+
+    Transfer transfer4 = new Transfer();
+    transfer4.operation = TransferOperation.DELETE;
+    transfer4.deleteKey = "delete.key.4";
+    transfer4.ifKey = "no.such.key";
+    transfer4.ifType = "zoo.cfg";
+    transfer4.ifKeyState = PropertyKeyState.ABSENT;
+    transfers.add(transfer4);
+
+    commandParams.put(ConfigureTask.PARAMETER_TRANSFERS, new Gson().toJson(transfers));
+
+    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));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    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()));
+
+    Map<String, String> map = config.getProperties();
+    assertEquals(1, map.size());
+    assertEquals("11", map.get("initLimit"));
+    String[] shouldNotExitKeys = new String[]{"delete.key.1","delete.key.2","delete.key.3","delete.key.4"};
+    for(String key: shouldNotExitKeys){
+      assertFalse(map.containsKey(key));
+    }
+  }
+
+  @Test
+  public void testDisallowedTransferDelete() throws Exception {
+    makeUpgradeCluster();
+
+    Cluster c = m_injector.getInstance(Clusters.class).getCluster("c1");
+    assertEquals(1, c.getConfigsByType("zoo.cfg").size());
+
+    c.setDesiredStackVersion(HDP_220_STACK);
+    ConfigFactory cf = m_injector.getInstance(ConfigFactory.class);
+    Config config = cf.createNew(c, "zoo.cfg", new HashMap<String, String>() {{
+          put("initLimit", "10");
+          put("delete.key.1", "d1");
+          put("delete.key.2", "d2");
+          put("delete.key.3", "d3");
+          put("delete.key.4", "d4");
+        }}, new HashMap<String, Map<String,String>>());
+    config.setTag("version2");
+    config.persist();
+
+    c.addConfig(config);
+    c.addDesiredConfig("user", Collections.singleton(config));
+    assertEquals(2, c.getConfigsByType("zoo.cfg").size());
+
+    List<ConfigurationKeyValue> configurations = new ArrayList<>();
+    ConfigurationKeyValue keyValue = new ConfigurationKeyValue();
+    configurations.add(keyValue);
+    keyValue.key = "initLimit";
+    keyValue.value = "11";
+
+    Map<String, String> commandParams = new HashMap<String, String>();
+    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");
+    commandParams.put(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS, new Gson().toJson(configurations));
+
+    List<Transfer> transfers = new ArrayList<>();
+    Transfer transfer2 = new Transfer();
+    transfer2.operation = TransferOperation.DELETE;
+    transfer2.deleteKey = "delete.key.2";
+    transfer2.ifKey = "initLimit";
+    transfer2.ifType = "zoo.cfg";
+    transfer2.ifValue = "not.real.value";
+    transfers.add(transfer2);
+
+    Transfer transfer3 = new Transfer();
+    transfer3.operation = TransferOperation.DELETE;
+    transfer3.deleteKey = "delete.key.3";
+    transfer3.ifKey = "initLimit";
+    transfer3.ifType = "zoo.cfg";
+    transfer3.ifKeyState = PropertyKeyState.ABSENT;
+    transfers.add(transfer3);
+
+    Transfer transfer4 = new Transfer();
+    transfer4.operation = TransferOperation.DELETE;
+    transfer4.deleteKey = "delete.key.4";
+    transfer4.ifKey = "no.such.key";
+    transfer4.ifType = "zoo.cfg";
+    transfer4.ifKeyState = PropertyKeyState.PRESENT;
+    transfers.add(transfer4);
+
+    commandParams.put(ConfigureTask.PARAMETER_TRANSFERS, new Gson().toJson(transfers));
+
+    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));
+
+    ConfigureAction action = m_injector.getInstance(ConfigureAction.class);
+    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()));
+
+    Map<String, String> map = config.getProperties();
+    assertEquals(5, map.size());
+    assertEquals("11", map.get("initLimit"));
+    String[] shouldExitKeys = new String[]{"delete.key.1","delete.key.2","delete.key.3","delete.key.4"};
+    for(String key: shouldExitKeys){
+      assertTrue(map.containsKey(key));
+    }
+  }
+
   private void makeUpgradeCluster() throws Exception {
     String clusterName = "c1";
     String hostName = "h1";

http://git-wip-us.apache.org/repos/asf/ambari/blob/771deecd/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
index 1a5d4e7..e443d9d 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
@@ -554,7 +554,7 @@ public class UpgradeHelperTest {
 
     assertEquals(4, groups.get(0).items.size());
     assertEquals(8, groups.get(1).items.size());
-    assertEquals(3, groups.get(2).items.size());
+    assertEquals(5, groups.get(2).items.size());
     assertEquals(8, groups.get(3).items.size());
     assertEquals(8, groups.get(4).items.size());
   }
@@ -670,8 +670,9 @@ public class UpgradeHelperTest {
 
     List<ConfigUpgradeChangeDefinition.Transfer> transfers = m_gson.fromJson(configurationJson,
             new TypeToken<List<ConfigUpgradeChangeDefinition.Transfer>>() { }.getType());
+    System.out.println(">> transfers"+transfers);
 
-    assertEquals(10, transfers.size());
+    assertEquals(6, transfers.size());
     assertEquals("copy-key", transfers.get(0).fromKey);
     assertEquals("copy-key-to", transfers.get(0).toKey);
 
@@ -679,15 +680,178 @@ public class UpgradeHelperTest {
     assertEquals("move-key-to", transfers.get(1).toKey);
 
     assertEquals("delete-key", transfers.get(2).deleteKey);
+    assertEquals("delete-http-1", transfers.get(3).deleteKey);
+    assertEquals("delete-http-2", transfers.get(4).deleteKey);
+    assertEquals("delete-http-3", transfers.get(5).deleteKey);
 
-    assertEquals("delete-http", transfers.get(3).deleteKey);
-    assertEquals("delete-null-if-value", transfers.get(4).deleteKey);
-    assertEquals("delete-blank-if-key", transfers.get(5).deleteKey);
-    assertEquals("delete-blank-if-type", transfers.get(6).deleteKey);
-    assertEquals("delete-thrift", transfers.get(7).deleteKey);
 
-    assertEquals("delete-if-key-present", transfers.get(8).deleteKey);
-    assertEquals("delete-if-key-absent", transfers.get(9).deleteKey);
+  }
+
+  @Test
+  public void testConfigTaskConditionMet() throws Exception {
+    Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");
+    assertTrue(upgrades.containsKey("upgrade_test"));
+    UpgradePack upgrade = upgrades.get("upgrade_test");
+    ConfigUpgradePack cup = ambariMetaInfo.getConfigUpgradePack("HDP", "2.1.1");
+    assertNotNull(upgrade);
+
+    Cluster cluster = makeCluster();
+
+    UpgradeContext context = new UpgradeContext(m_masterHostResolver, HDP_21,
+        HDP_21, UPGRADE_VERSION, Direction.UPGRADE, UpgradeType.ROLLING);
+
+    List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade,
+        context);
+
+    assertEquals(7, groups.size());
+
+    // grab the configure task out of Hive
+    UpgradeGroupHolder hiveGroup = groups.get(4);
+    assertEquals("HIVE", hiveGroup.name);
+
+    //Condition is met
+    ConfigureTask configureTask = (ConfigureTask) hiveGroup.items.get(3).getTasks().get(0).getTasks().get(0);
+    Map<String, String> configProperties = configureTask.getConfigurationChanges(cluster, cup);
+
+    assertFalse(configProperties.isEmpty());
+    assertEquals(configProperties.get(ConfigureTask.PARAMETER_CONFIG_TYPE), "hive-site");
+
+    assertTrue(configProperties.containsKey(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS));
+    assertTrue(configProperties.containsKey(ConfigureTask.PARAMETER_REPLACEMENTS));
+    assertTrue(configProperties.containsKey(ConfigureTask.PARAMETER_TRANSFERS));
+
+    String configurationJson = configProperties.get(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS);
+    String transferJson = configProperties.get(ConfigureTask.PARAMETER_TRANSFERS);
+    String replacementJson = configProperties.get(ConfigureTask.PARAMETER_REPLACEMENTS);
+    assertNotNull(configurationJson);
+    assertNotNull(transferJson);
+    assertNotNull(replacementJson);
+
+    //if conditions for sets...
+    List<ConfigUpgradeChangeDefinition.ConfigurationKeyValue> keyValuePairs = m_gson.fromJson(configurationJson,
+        new TypeToken<List<ConfigUpgradeChangeDefinition.ConfigurationKeyValue>>() {
+        }.getType());
+    assertEquals("setKeyOne", keyValuePairs.get(0).key);
+    assertEquals("1", keyValuePairs.get(0).value);
+
+    assertEquals("setKeyTwo", keyValuePairs.get(1).key);
+    assertEquals("2", keyValuePairs.get(1).value);
+
+    assertEquals("setKeyThree", keyValuePairs.get(2).key);
+    assertEquals("3", keyValuePairs.get(2).value);
+
+    assertEquals("setKeyFour", keyValuePairs.get(3).key);
+    assertEquals("4", keyValuePairs.get(3).value);
+
+    //if conditions for transfer
+    List<ConfigUpgradeChangeDefinition.Transfer> transfers = m_gson.fromJson(transferJson,
+        new TypeToken<List<ConfigUpgradeChangeDefinition.Transfer>>() {
+        }.getType());
+
+    System.out.println(" testConfigTaskConditionMet >> transfer"+transfers);
+
+    assertEquals("copy-key-one", transfers.get(0).fromKey);
+    assertEquals("copy-to-key-one", transfers.get(0).toKey);
+
+    assertEquals("copy-key-two", transfers.get(1).fromKey);
+    assertEquals("copy-to-key-two", transfers.get(1).toKey);
+
+    assertEquals("copy-key-three", transfers.get(2).fromKey);
+    assertEquals("copy-to-key-three", transfers.get(2).toKey);
+
+    assertEquals("copy-key-four", transfers.get(3).fromKey);
+    assertEquals("copy-to-key-four", transfers.get(3).toKey);
+
+    assertEquals("move-key-one", transfers.get(4).fromKey);
+    assertEquals("move-to-key-one", transfers.get(4).toKey);
+
+    assertEquals("move-key-two", transfers.get(5).fromKey);
+    assertEquals("move-to-key-two", transfers.get(5).toKey);
+
+    assertEquals("move-key-three", transfers.get(6).fromKey);
+    assertEquals("move-to-key-three", transfers.get(6).toKey);
+
+    assertEquals("move-key-four", transfers.get(7).fromKey);
+    assertEquals("move-to-key-four", transfers.get(7).toKey);
+
+    assertEquals("delete-key-one", transfers.get(8).deleteKey);
+    assertEquals("delete-key-two", transfers.get(9).deleteKey);
+    assertEquals("delete-key-three", transfers.get(10).deleteKey);
+    assertEquals("delete-key-four", transfers.get(11).deleteKey);
+
+    //if conditions for replace
+    List<ConfigUpgradeChangeDefinition.Replace> replacements = m_gson.fromJson(replacementJson,
+        new TypeToken<List<ConfigUpgradeChangeDefinition.Replace>>() {
+        }.getType());
+    assertEquals("replace-key-one", replacements.get(0).key);
+    assertEquals("abc", replacements.get(0).find);
+    assertEquals("abc-replaced", replacements.get(0).replaceWith);
+    assertEquals("replace-key-two", replacements.get(1).key);
+    assertEquals("efg", replacements.get(1).find);
+    assertEquals("efg-replaced", replacements.get(1).replaceWith);
+    assertEquals("replace-key-three", replacements.get(2).key);
+    assertEquals("ijk", replacements.get(2).find);
+    assertEquals("ijk-replaced", replacements.get(2).replaceWith);
+    assertEquals("replace-key-four", replacements.get(3).key);
+    assertEquals("lmn", replacements.get(3).find);
+    assertEquals("lmn-replaced", replacements.get(3).replaceWith);
+  }
+
+  @Test
+  public void testConfigTaskConditionSkipped() throws Exception {
+    Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");
+    assertTrue(upgrades.containsKey("upgrade_test"));
+    UpgradePack upgrade = upgrades.get("upgrade_test");
+    ConfigUpgradePack cup = ambariMetaInfo.getConfigUpgradePack("HDP", "2.1.1");
+    assertNotNull(upgrade);
+
+    Cluster cluster = makeCluster();
+
+    UpgradeContext context = new UpgradeContext(m_masterHostResolver, HDP_21,
+        HDP_21, UPGRADE_VERSION, Direction.UPGRADE, UpgradeType.ROLLING);
+
+    List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade,
+        context);
+
+    assertEquals(7, groups.size());
+
+    UpgradeGroupHolder hiveGroup = groups.get(4);
+    assertEquals("HIVE", hiveGroup.name);
+
+    //Condition is not met, so no config operations should be present in the configureTask...
+    ConfigureTask configureTask = (ConfigureTask) hiveGroup.items.get(4).getTasks().get(0).getTasks().get(0);
+    Map<String, String> configProperties = configureTask.getConfigurationChanges(cluster, cup);
+
+    assertFalse(configProperties.isEmpty());
+    assertEquals(configProperties.get(ConfigureTask.PARAMETER_CONFIG_TYPE), "hive-site");
+
+    assertTrue(configProperties.containsKey(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS));
+    assertTrue(configProperties.containsKey(ConfigureTask.PARAMETER_REPLACEMENTS));
+    assertTrue(configProperties.containsKey(ConfigureTask.PARAMETER_TRANSFERS));
+
+    String configurationJson = configProperties.get(ConfigureTask.PARAMETER_KEY_VALUE_PAIRS);
+    String transferJson = configProperties.get(ConfigureTask.PARAMETER_TRANSFERS);
+    System.out.println(" testConfigTaskConditionSkip >> transferJson"+transferJson);
+
+    String replacementJson = configProperties.get(ConfigureTask.PARAMETER_REPLACEMENTS);
+    assertNotNull(configurationJson);
+    assertNotNull(transferJson);
+    assertNotNull(replacementJson);
+
+    List<ConfigUpgradeChangeDefinition.ConfigurationKeyValue> keyValuePairs = m_gson.fromJson(configurationJson,
+        new TypeToken<List<ConfigUpgradeChangeDefinition.ConfigurationKeyValue>>() {
+        }.getType());
+    assertTrue(keyValuePairs.isEmpty());
+
+    List<ConfigUpgradeChangeDefinition.Replace> replacements = m_gson.fromJson(replacementJson,
+        new TypeToken<List<ConfigUpgradeChangeDefinition.Replace>>() {
+        }.getType());
+    assertTrue(replacements.isEmpty());
+
+    List<ConfigUpgradeChangeDefinition.Transfer> transfers = m_gson.fromJson(transferJson,
+        new TypeToken<List<ConfigUpgradeChangeDefinition.Transfer>>() {
+        }.getType());
+    assertTrue(transfers.isEmpty());
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/771deecd/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/config-upgrade.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/config-upgrade.xml b/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/config-upgrade.xml
index f345d12..cb034d0 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/config-upgrade.xml
+++ b/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/config-upgrade.xml
@@ -111,19 +111,108 @@
             <transfer operation="copy" from-key="copy-key" to-key="copy-key-to" />
             <transfer operation="move" from-key="move-key" to-key="move-key-to" />
             <transfer operation="delete" delete-key="delete-key" />
-            <transfer operation="delete" delete-key="delete-http" if-key="hive.server2.transport.mode" if-type="hive-site" if-value="http" />
-            <transfer operation="delete" delete-key="delete-https-fail" if-key="hive.server2.transport.mode" if-type="hive-site" if-value="https" />
-            <transfer operation="delete" delete-key="delete-prop-fail" if-key="non.existent" if-type="hive-site" if-value="https" />
-            <transfer operation="delete" delete-key="delete-type-fail" if-key="non.existent" if-type="non.existent" if-value="" />
-            <transfer operation="delete" delete-key="delete-null-if-value" if-key="non.existent" if-type="non.existent" />
-            <transfer operation="delete" delete-key="delete-blank-if-key" if-key="" if-type="non.existent" />
-            <transfer operation="delete" delete-key="delete-blank-if-type" if-key="non.existent" if-type="" />
-            <transfer operation="delete" delete-key="delete-thrift" if-key="hive.server2.thrift.port" if-type="hive-site" if-value="10001" />
-
-            <transfer operation="delete" delete-key="delete-if-key-present" if-key="condition" if-type="hive-site" if-key-state="present"/>
-            <transfer operation="delete" delete-key="delete-if-key-absent" if-key="condition1" if-type="hive-site" if-key-state="absent"/>
-            <transfer operation="delete" delete-key="not-executed-transfer" if-key="non-existed-key" if-type="hive-site" if-key-state="present"/>
+            <transfer operation="delete" delete-key="delete-http-1" if-key="hive.server2.transport.mode" if-type="hive-site" if-value="http" />
+            <transfer operation="delete" delete-key="delete-http-2" if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="present" />
+            <transfer operation="delete" delete-key="delete-http-3" if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="absent" />
 
+            <!-- None of the following should pass the if attribute validation -->
+            <transfer operation="delete" delete-key="delete-blank-if-key" if-key="" if-type="type" />
+            <transfer operation="delete" delete-key="delete-blank-if-type" if-key="key" if-type="" />
+            <transfer operation="delete" delete-key="delete-null-if-value" if-key="key" if-type="type" />
+            <transfer operation="delete" delete-key="delete-blank-if-type-if-key-1" if-value="value" />
+            <transfer operation="delete" delete-key="delete-blank-if-type-if-key-2" if-key-state="present" />
+            <transfer operation="delete" delete-key="delete-blank-if-type-if-key-3" if-key-state="absent" />
+
+          </definition>
+
+          <definition xsi:type="configure" id="hdp_2_1_1_hive_server_conditions">
+              <type>hive-site</type>
+              <!-- set -->
+              <set key="setKeyOne" value="1" />
+              <set key="setKeyTwo" value="2"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="present"/>
+              <set key="setKeyThree" value="3"
+              if-key="foo.bar" if-type="hive-site" if-key-state="absent"/>
+              <set key="setKeyFour" value="4"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-value="binary"/>
+
+              <!-- transfer operation Copy -->
+              <transfer operation="copy" from-type="hive-site" from-key="copy-key-one" to-key="copy-to-key-one" default-value="1" />
+              <transfer operation="copy" from-type="hive-site" from-key="copy-key-two" to-key="copy-to-key-two" default-value="1"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="present"/>
+              <transfer operation="copy" from-type="hive-site" from-key="copy-key-three" to-key="copy-to-key-three" default-value="1"
+              if-key="foo.bar" if-type="hive-site" if-key-state="absent"/>
+              <transfer operation="copy" from-type="hive-site" from-key="copy-key-four" to-key="copy-to-key-four" default-value="1"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-value="binary"/>
+
+              <!-- transfer operation move -->
+              <transfer operation="move" from-type="hive-site" from-key="move-key-one" to-key="move-to-key-one" default-value="1" />
+              <transfer operation="move" from-type="hive-site" from-key="move-key-two" to-key="move-to-key-two" default-value="1"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="present"/>
+              <transfer operation="move" from-type="hive-site" from-key="move-key-three" to-key="move-to-key-three" default-value="1"
+              if-key="foo.bar" if-type="hive-site" if-key-state="absent"/>
+              <transfer operation="move" from-type="hive-site" from-key="move-key-four" to-key="move-to-key-four" default-value="1"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-value="binary"/>
+
+              <!-- transfer operation delete -->
+              <transfer operation="delete" delete-key="delete-key-one" />
+              <transfer operation="delete" delete-key="delete-key-two" if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="present"/>
+              <transfer operation="delete" delete-key="delete-key-three" if-key="foo.bar" if-type="hive-site" if-key-state="absent"/>
+              <transfer operation="delete" delete-key="delete-key-four" if-key="hive.server2.transport.mode" if-type="hive-site" if-value="binary"/>
+
+              <!-- replace -->
+              <replace key="replace-key-one" find="abc" replace-with="abc-replaced" />
+              <replace key="replace-key-two" find="efg" replace-with="efg-replaced"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="present"/>
+              <replace key="replace-key-three" find="ijk" replace-with="ijk-replaced"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="absent"/>
+              <replace key="replace-key-four" find="lmn" replace-with="lmn-replaced"
+              if-key="hive.server2.transport.mode" if-type="hive-site" if-value="binary"/>
+          </definition>
+
+          <definition xsi:type="configure" id="hdp_2_1_1_hive_server_conditions_skip">
+             <type>hive-site</type>
+             <!-- set -->
+             <set key="setKeyOne" value="1" if-key="hive.server2.transport.mode" if-type="" if-value="skip"/>
+             <set key="setKeyTwo" value="2" if-key="" if-type="hive-site" if-key-state="absent"/>
+             <set key="setKeyThree" value="3" if-key="foo.bar" if-type="hive-site" if-key-state="abcd"/>
+             <set key="setKeyThree" value="3" if-key="foo.bar" if-type="hive-site" />
+
+             <!-- transfer operation Copy -->
+             <transfer operation="copy" from-type="hive-site" from-key="copy-key-one" to-key="copy-to-key-two" default-value="1"
+             if-key="hive.server2.transport.mode" if-type="" if-key-state="absent"/>
+             <transfer operation="copy" from-type="hive-site" from-key="copy-key-two" to-key="copy-to-key-three" default-value="1"
+             if-key="" if-type="hive-site" if-key-state="present"/>
+             <transfer operation="copy" from-type="hive-site" from-key="copy-key-three" to-key="copy-to-key-four" default-value="1"
+             if-key="hive.server2.transport.mode" if-type="hive-site" />
+             <transfer operation="copy" from-type="hive-site" from-key="copy-key-four" to-key="copy-to-key-four" default-value="1"
+             if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="abcd"/>
+
+             <!-- transfer operation move -->
+             <transfer operation="move" from-type="hive-site" from-key="move-key-one" to-key="move-to-key-four" default-value="1"
+             if-key="hive.server2.transport.mode" if-type="" if-value="skip"/>
+             <transfer operation="move" from-type="hive-site" from-key="move-key-two" to-key="move-to-key-two" default-value="1"
+             if-key="" if-type="hive-site" if-key-state="absent"/>
+             <transfer operation="move" from-type="hive-site" from-key="move-key-three" to-key="move-to-key-three" default-value="1"
+             if-key="hive.server2.transport.mode" if-type="hive-site" if-key-state="abcd"/>
+             <transfer operation="move" from-type="hive-site" from-key="move-key-four" to-key="move-to-key-four" default-value="1"
+             if-key="hive.server2.transport.mode" if-type="hive-site"/>
+
+             <!-- transfer operation delete -->
+             <transfer operation="delete" delete-key="delete-key-one" if-key="hive.server2.transport.mode" if-type="" if-key-state="absent"/>
+             <transfer operation="delete" delete-key="delete-key-two" if-key="" if-type="hive-site" if-key-state="absent"/>
+             <transfer operation="delete" delete-key="delete-key-three" if-key="foo.bar" if-type="hive-site" if-key-state="abcd"/>
+             <transfer operation="delete" delete-key="delete-key-four" if-key="hive.server2.transport.mode" if-type="hive-site" />
+
+             <!-- replacement -->
+             <replace key="replace-key-one" find="abc" replace-with="abc-replaced"
+             if-key="hive.server2.transport.mode" if-type="" if-value="skip"/>
+             <replace key="replace-key-two" find="efg" replace-with="efg-replaced"
+             if-key="" if-type="hive-site" if-key-state="absent"/>
+             <replace key="replace-key-three" find="ijk" replace-with="ijk-replaced"
+             if-key="foo.bar" if-type="hive-site" if-key-state="abcd"/>
+             <replace key="replace-key-three" find="ijk" replace-with="ijk-replaced"
+             if-key="foo.bar" if-type="hive-site"/>
           </definition>
         </changes>
       </component>

http://git-wip-us.apache.org/repos/asf/ambari/blob/771deecd/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test.xml b/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test.xml
index 237da77..623b45c 100644
--- a/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test.xml
+++ b/ambari-server/src/test/resources/stacks/HDP/2.1.1/upgrades/upgrade_test.xml
@@ -211,6 +211,8 @@
           </task>
           <task xsi:type="configure" id="hdp_2_1_1_set_transport_mode"/>
           <task xsi:type="configure" id="hdp_2_1_1_hive_server_foo"/>
+          <task xsi:type="configure" id="hdp_2_1_1_hive_server_conditions"/>
+          <task xsi:type="configure" id="hdp_2_1_1_hive_server_conditions_skip"/>
         </pre-upgrade>
        </component>
      </service>