aws / amazon-ssm-agent

An agent to enable remote management of your EC2 instances, on-premises servers, or virtual machines (VMs).
https://aws.amazon.com/systems-manager/
Apache License 2.0
1.04k stars 323 forks source link

[Feature request] Run Command: successAndContinue value for onFailure input #341

Open bryanburke opened 3 years ago

bryanburke commented 3 years ago

As of 3.0.502.0, SSM Agent supports shared inputs for all plugins that facilitate low-level conditional logic. However, a common if-else workflow does not seem straightforward with the current available values for onFailure.

For example, in a configuration management scenario, I have two separate Linux shell scripts. The first script (verify) checks a set of conditions and exits non-zero if any condition is not met. The second script (apply) makes changes to the system such that all conditions are now met. In this scenario, I want to invoke apply only if verify fails, but I do not want verify's failure to affect the status of the overall execution. Here is the equivalent if-else logic in shell:

if ! ./verify; then ./apply; fi
# apply's exit status determines overall success or failure, not verify's.

Here is a partial document that conditionally invokes apply but also considers the entire command failed when verify fails:

mainSteps:
  - action: aws:runShellScript
    inputs:
      onSuccess: exit # Overall status will be Failed if this step fails.
      runCommand:
        - '#!/bin/sh'
        - '$(exit 1)' # Change to 0 and the command skips apply.
    name: verify
  - action: aws:runShellScript
    inputs:
      runCommand:
        - '#!/bin/sh'
        - 'echo "apply ran"'
    name: apply

In order both conditionally to invoke apply and to have verify not affect the overall command status, you have to invert verify's exit status and use successAndExit for onFailure:

mainSteps:
  - action: aws:runShellScript
    inputs:
      onFailure: successAndExit # Overall status not affected by this step.
      runCommand:
        - '#!/bin/sh'
        - '! $(exit 0)' # Change to 1 and the command skips apply.
    name: verify
  - action: aws:runShellScript
    inputs:
      runCommand:
        - '#!/bin/sh'
        - 'echo "apply ran"'
    name: apply

If onFailure supported a successAndContinue value that could be used in conjunction with onSuccess, the above inverted logic would not be necessary:

mainSteps:
  - action: aws:runShellScript
    inputs:
      onFailure: successAndContinue # Overall status not affected by this step.
      onSuccess: exit
      runCommand:
        - '#!/bin/sh'
        - '$(exit 1)' # Change to 0 and the command skips apply.
    name: verify
  - action: aws:runShellScript
    inputs:
      runCommand:
        - '#!/bin/sh'
        - 'echo "apply ran"'
    name: apply

Alternatively, a more generic feature might be a critical Boolean property for steps (similar to Automation's isCritical):

mainSteps:
  - action: aws:runShellScript
    critical: false # Overall status not affected by this step.
    inputs:
      onSuccess: exit
      runCommand:
        - '#!/bin/sh'
        - '$(exit 1)' # Change to 0 and the command skips apply.
    name: verify
  - action: aws:runShellScript
    inputs:
      runCommand:
        - '#!/bin/sh'
        - 'echo "apply ran"'
    name: apply