class AmbariCustomCommandExecutionHelper {

  public void addServiceCheckAction(Stage stage, String hostname, String smokeTestRole,
      long nowTimestamp, String serviceName, String componentName,
      Map<String, String> actionParameters, boolean retryAllowed, boolean autoSkipFailure, boolean useLatestConfigs)
          throws AmbariException {

    String clusterName = stage.getClusterName();
    Cluster cluster = clusters.getCluster(clusterName);
    Service service = cluster.getService(serviceName);
    ServiceComponent component = null;
    if (null != componentName) {
      component = service.getServiceComponent(componentName);
    }
    StackId stackId = (null != component) ? component.getDesiredStackId() : service.getDesiredStackId();

    AmbariMetaInfo ambariMetaInfo = managementController.getAmbariMetaInfo();
    ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
        stackId.getStackVersion(), serviceName);

    stage.addHostRoleExecutionCommand(hostname, Role.valueOf(smokeTestRole),
        RoleCommand.SERVICE_CHECK,
        new ServiceComponentHostOpInProgressEvent(componentName, hostname, nowTimestamp),
        cluster.getClusterName(), serviceName, retryAllowed, autoSkipFailure);

    HostRoleCommand hrc = stage.getHostRoleCommand(hostname, smokeTestRole);
    if (hrc != null) {
      hrc.setCommandDetail(String.format("%s %s", RoleCommand.SERVICE_CHECK.toString(), serviceName));
    }
    // [ type -> [ key, value ] ]
    Map<String, Map<String, String>> configurations =
        new TreeMap<>();
    Map<String, Map<String, Map<String, String>>> configurationAttributes =
        new TreeMap<>();
    Map<String, Map<String, String>> configTags = new TreeMap<>();

    ExecutionCommand execCmd = stage.getExecutionCommandWrapper(hostname,
        smokeTestRole).getExecutionCommand();

    // if the command should fetch brand new configuration tags before
    // execution, then we don't need to fetch them now
    if(actionParameters != null && actionParameters.containsKey(KeyNames.REFRESH_CONFIG_TAGS_BEFORE_EXECUTION)){
      execCmd.setForceRefreshConfigTagsBeforeExecution(true);
    }

    // when building complex orchestration ahead of time (such as when
    // performing ugprades), fetching configuration tags can take a very long
    // time - if it's not needed, then don't do it
    if (!execCmd.getForceRefreshConfigTagsBeforeExecution()) {
      configTags = managementController.findConfigurationTagsWithOverrides(cluster, hostname);
    }

    execCmd.setConfigurations(configurations);
    execCmd.setConfigurationAttributes(configurationAttributes);
    execCmd.setConfigurationTags(configTags);

    // Generate localComponents
    for (ServiceComponentHost sch : cluster.getServiceComponentHosts(hostname)) {
      execCmd.getLocalComponents().add(sch.getServiceComponentName());
    }

    Map<String, String> commandParams = new TreeMap<>();
    String commandTimeout = getStatusCommandTimeout(serviceInfo);

    if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
      // Service check command is not custom command
      CommandScriptDefinition script = serviceInfo.getCommandScript();
      if (script != null) {
        commandParams.put(SCRIPT, script.getScript());
        commandParams.put(SCRIPT_TYPE, script.getScriptType().toString());
      } else {
        String message = String.format("Service %s has no command script " +
            "defined. It is not possible to run service check" +
            " for this service", serviceName);
        throw new AmbariException(message);
      }
      // We don't need package/repo information to perform service check
    }

    commandParams.put(COMMAND_TIMEOUT, commandTimeout);
    String checkType = configHelper.getValueFromDesiredConfigurations(cluster, ConfigHelper.CLUSTER_ENV, ConfigHelper.SERVICE_CHECK_TYPE);
    if (ConfigHelper.SERVICE_CHECK_MINIMAL.equals(checkType)) {
      int actualTimeout = Integer.parseInt(commandParams.get(COMMAND_TIMEOUT)) / 2;
      actualTimeout = actualTimeout < MIN_STRICT_SERVICE_CHECK_TIMEOUT ? MIN_STRICT_SERVICE_CHECK_TIMEOUT : actualTimeout;
      commandParams.put(COMMAND_TIMEOUT, Integer.toString(actualTimeout));
    }

    StageUtils.useAmbariJdkInCommandParams(commandParams, configs);

    execCmd.setCommandParams(commandParams);

    if (actionParameters != null) { // If defined
      execCmd.setRoleParams(actionParameters);
    }
    if (useLatestConfigs) {
      execCmd.setUseLatestConfigs(useLatestConfigs);
    }
  }

}