class UpdateKerberosConfigsServerAction extends AbstractServerAction {

  @Override
  public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext)
      throws AmbariException, InterruptedException {

    CommandReport commandReport = null;

    String clusterName = getExecutionCommand().getClusterName();
    Clusters clusters = controller.getClusters();
    Cluster cluster = clusters.getCluster(clusterName);

    String authenticatedUserName = getCommandParameterValue(getCommandParameters(), KerberosServerAction.AUTHENTICATED_USER_NAME);
    String dataDirectoryPath = getCommandParameterValue(getCommandParameters(), KerberosServerAction.DATA_DIRECTORY);
    HashMap<String, Map<String, String>> propertiesToSet = new HashMap<>();
    HashMap<String, Collection<String>> propertiesToRemove = new HashMap<>();

    // If the data directory path is set, attempt to process further, else assume there is no work to do
    if (dataDirectoryPath != null) {
      File dataDirectory = new File(dataDirectoryPath);

      // If the data directory exists, attempt to process further, else assume there is no work to do
      if (dataDirectory.exists()) {
        KerberosConfigDataFileReader configReader = null;
        Set<String> configTypes = new HashSet<>();

        try {
          // If the config data file exists, iterate over the records to find the (explicit)
          // configuration settings to update
          File configFile = new File(dataDirectory, KerberosConfigDataFileReader.DATA_FILE_NAME);
          if (configFile.exists()) {
            configReader = kerberosConfigDataFileReaderFactory.createKerberosConfigDataFileReader(configFile);
            for (Map<String, String> record : configReader) {
              String configType = record.get(KerberosConfigDataFileReader.CONFIGURATION_TYPE);
              String configKey = record.get(KerberosConfigDataFileReader.KEY);
              String configOp = record.get(KerberosConfigDataFileReader.OPERATION);

              configTypes.add(configType);

              if (KerberosConfigDataFileReader.OPERATION_TYPE_REMOVE.equals(configOp)) {
                removeConfigTypeProp(propertiesToRemove, configType, configKey);
              } else {
                String configVal = record.get(KerberosConfigDataFileReader.VALUE);
                addConfigTypePropVal(propertiesToSet, configType, configKey, configVal);
              }
            }
          }

          // ensure that cluster-env/security_enabled have proper value
          final String securityEnabled = cluster.getSecurityType() == SecurityType.KERBEROS
              ? "true"
              : "false";

          if(!configTypes.contains("cluster-env")) {
            configTypes.add("cluster-env");
          }

          Map<String, String> clusterEnvProperties = propertiesToSet.get("cluster-env");
          if(clusterEnvProperties == null) {
            clusterEnvProperties = new HashMap<>();
            propertiesToSet.put("cluster-env", clusterEnvProperties);
          }

          clusterEnvProperties.put("security_enabled", securityEnabled);

          if (!configTypes.isEmpty()) {
            String configNote = getCommandParameterValue(getCommandParameters(), KerberosServerAction.UPDATE_CONFIGURATION_NOTE);

            if((configNote == null) || configNote.isEmpty()) {
              configNote = cluster.getSecurityType() == SecurityType.KERBEROS
                  ? "Enabling Kerberos"
                  : "Disabling Kerberos";
            }

            for (String configType : configTypes) {
              configHelper.updateConfigType(cluster, cluster.getDesiredStackVersion(), controller,
                  configType, propertiesToSet.get(configType), propertiesToRemove.get(configType),
                  authenticatedUserName, configNote);
            }
          }
        } catch (IOException e) {
          String message = "Could not update services configs to enable kerberos";
          actionLog.writeStdErr(message);
          LOG.error(message, e);
          commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(),
              actionLog.getStdErr());
        } finally {
          if (configReader != null && !configReader.isClosed()) {
            try {
              configReader.close();
            } catch (Throwable t) {
              // ignored
            }
          }
        }
      }
    }

    return (commandReport == null)
        ? createCommandReport(0, HostRoleStatus.COMPLETED, "{}", actionLog.getStdOut(), actionLog.getStdErr())
        : commandReport;
  }

}