private void processConfigurationChanges(Cluster cluster, StackId targetStackId,
                                           KerberosDescriptor kerberosDescriptor,
                                           Map<String, Map<String, String>> kerberosConfigurations,
                                           Map<String, Set<String>> propertiesToBeRemoved,
                                           Map<String, Map<String, String>> variableReplaments)
      throws AmbariException {
    actionLog.writeStdOut("Determining configuration changes");

    if (!kerberosConfigurations.isEmpty()) {
      Map<String, Service> installedServices = cluster.getServices();

      // Build a map of configuration types to properties that indicate which properties should be altered
      // This map should contain only properties defined in service-level Kerberos descriptors that
      // have been flagged to be preconfigured and that have not yet been installed.
      Map<String, Set<String>> propertyFilter = new HashMap<>();
      Map<String, KerberosServiceDescriptor> serviceDescriptors = kerberosDescriptor.getServices();
      if (serviceDescriptors != null) {
        for (KerberosServiceDescriptor serviceDescriptor : serviceDescriptors.values()) {
          if (!installedServices.containsKey(serviceDescriptor.getName()) && serviceDescriptor.shouldPreconfigure()) {
            buildFilter(Collections.singleton(serviceDescriptor), propertyFilter, variableReplaments);
          }
        }
      }

      // Add the auth-to-local rule configuration specifications to the filter
      Map<String, Set<String>> authToLocalProperties = kerberosHelper.translateConfigurationSpecifications(kerberosDescriptor.getAllAuthToLocalProperties());
      if (!MapUtils.isEmpty(authToLocalProperties)) {
        for (Map.Entry<String, Set<String>> entry : authToLocalProperties.entrySet()) {
          Set<String> properties = entry.getValue();

          if (!CollectionUtils.isEmpty(properties)) {
            String configurationType = entry.getKey();

            Set<String> propertyNames = propertyFilter.get(configurationType);
            if (propertyNames == null) {
              propertyNames = new HashSet<>();
              propertyFilter.put(configurationType, propertyNames);
            }

            propertyNames.addAll(properties);
          }
        }
      }

      Set<String> visitedTypes = new HashSet<>();

      for (Map.Entry<String, Map<String, String>> entry : kerberosConfigurations.entrySet()) {
        String configType = entry.getKey();

        String service = cluster.getServiceByConfigType(configType);
        Set<String> allowedProperties = propertyFilter.get(configType);

        // Update properties for services that are installed and not filtered out
        if (installedServices.containsKey(service) && !CollectionUtils.isEmpty(allowedProperties)) {
          Map<String, String> propertiesToUpdate = entry.getValue();
          Set<String> propertiesToRemove = (propertiesToBeRemoved == null) ? null : propertiesToBeRemoved.get(configType);

          // Filter the properties to update
          if (propertiesToUpdate != null) {
            Iterator<Map.Entry<String, String>> mapIterator = propertiesToUpdate.entrySet().iterator();
            while (mapIterator.hasNext()) {
              Map.Entry<String, String> mapEntry = mapIterator.next();

              if (!allowedProperties.contains(mapEntry.getKey())) {
                mapIterator.remove();
              }
            }
          }

          // Filter the properties to remove
          if (propertiesToRemove != null) {
            Iterator<String> setIterator = propertiesToRemove.iterator();
            while (setIterator.hasNext()) {
              String setEntry = setIterator.next();
              if (!allowedProperties.contains(setEntry)) {
                setIterator.remove();
              }
            }
          }

          visitedTypes.add(configType);

          if (!MapUtils.isEmpty(propertiesToUpdate) || !CollectionUtils.isEmpty(propertiesToRemove)) {
            if (!MapUtils.isEmpty(propertiesToUpdate)) {
              for (Map.Entry<String, String> property : propertiesToUpdate.entrySet()) {
                actionLog.writeStdOut(String.format("Setting: %s/%s = %s", configType, property.getKey(), property.getValue()));
              }
            }

            if (!CollectionUtils.isEmpty(propertiesToRemove)) {
              for (String property : propertiesToRemove) {
                actionLog.writeStdOut(String.format("Removing: %s/%s", configType, property));
              }
            }

            configHelper.updateConfigType(cluster, targetStackId,
                ambariManagementController, configType, propertiesToUpdate, propertiesToRemove,
                ambariManagementController.getAuthName(), "Preconfiguring for Kerberos during upgrade");
          }
        }
      }

      if (!MapUtils.isEmpty(propertiesToBeRemoved)) {
        for (Map.Entry<String, Set<String>> entry : propertiesToBeRemoved.entrySet()) {
          String configType = entry.getKey();

          if (!visitedTypes.contains(configType)) {
            Set<String> propertiesToRemove = entry.getValue();

            if (!CollectionUtils.isEmpty(propertiesToRemove)) {
              for (String property : propertiesToRemove) {
                actionLog.writeStdOut(String.format("Removing: %s/%s", configType, property));
              }

              configHelper.updateConfigType(cluster, targetStackId,
                  ambariManagementController, configType, null, entry.getValue(),
                  ambariManagementController.getAuthName(), "Preconfiguring for Kerberos during upgrade");
            }
          }
        }
      }
    }
  }
Processes configuration changes to determine if any work needs to be done.
<p/>
If work is to be done, a data file containing the details is created so it they changes may be
processed in the appropriate stage.

@param cluster                the cluster
@param targetStackId          the target stack id
@param kerberosConfigurations the Kerberos-specific configuration map
@param propertiesToBeRemoved  a map of properties to be removed from the current configuration,
                              grouped by configuration type.
@param variableReplaments     replacement values to use when attempting to perform variable replacements on the property names
@throws AmbariException if an issue is encountered
ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/PreconfigureKerberosAction.java