KBEC-00176 - Ending a step before it completes

Description

This article describes how to end a step when it prints specific text.

Symptom

You have a step with one of the following characteristics:

  1. a step you want to end after certain text is printed
  2. a step never ends because it:
    1. completed, printing its completed text however it never exits the step
    2. printed an error, warning, or status message before hanging

Solution

  1. Find a very recognizable message in the log of the build step that says something like:

    "finished with exit code X at <timestamp>"
  2. Create a parallel step that monitors a property and, when the right value appears, abort the other step. In pseudo-code, the step looks like this:

    Parallel Monitor Step
      $jobStepIdToAbort = getProperty /myJob/jobStepIdToAbort
      while(!$finished)
        $finished = getProperty(/myJob/finished)
        sleep 20
      abortJobStep $jobStepIdToAbort
  3. In the main build step, the step you want to end:
    1. Set the monitor property:

      setProperty /myJob/jobStepIdToAbort /myJobStep/jobStepId
    2. Implement a postp matcher that runs on the build step that
      1. matches for the "finished" message
      2. sets the /myJob/finished property
      3. extracts the exit code from the build
      4. sets a /myJob/exitCode property.
  4. For the step that will be ended, set its error handling to "ignore" so that the abort will not create a failed job.
  5. A subsequent step after the two parallel steps sets the correct exit status:

    $exitCode = getProperty /myJob/exitCode
    exit $exitCode

    This last step serves as a sort of status proxy step so that the job will end up with the correct outcome from the build even though the build step itself is always aborted.

Supplemental

Property changes via postp's internal incValue() and setProperty() routines do not immediately take effect, as they are cached for efficiency. They also do not look-up previous values on the Flow server!

Here is a quick overview:

  1. When postp is in LiveUpdate mode (default) it will scan a log file line by line
  2. For each line it checks if any matchers exist that match the line
  3. If so, the actions for each of those matchers are executed
  4. Common actions are:
    1. incValue

      incValue (name,value):
                     This routine checks if the name "errors" or "warnings" is present in the internal property hash.
                     If not then this is the first time an error or warning has been detected and incValue sets an
                                    internal flag $::gUrgentPropertyChange to true.  We will see what this does later in the
                                    "updateServer" step.
                     Now incValue calls the internal setProperty command with a value of current + value
                     Note that incValue does not treat "name" as  a property path and does not lookup it's current value.
                     Name is simply a string for now
    2. setProperty

      setProperty(name, value)
                     This routine sets the value of an internal hash based on the name.
                     Note that the value is stored in the internal hash and no changes to the Flow server have been executed
                     Note also that this is NOT the same as calling the Flow perl API setProperty()
  5. Once all the matchers have been processed and before the next line of log is scanned, postp calls the internal routine "updateServer"

    updateServer()
    Update server checks to see if any changes have been posted to the internal hash.  If not it returns without updating the server
    Next it checks to see if an internal clock (30 seconds by default) has expired OR if the $::gUrgentPropertyChange flag is set to true
    If not, it returns without updating the server
    Otherwise the internal hash is flushed to the server with a batch API call

    For example, the call incValue("/myWorkflow/recover") in a matcher will only get posted after the timer expires. This can be anywhere between immediately and 30 seconds. You can bypass the postp property caching and call Flow directly from within your matcher

    $::gCommander->getProperty("/increment /myWorkflow/recover")

    If you attempt to set the UrgentPropertyChange value like this:

    {
        id => "ctsMatchUnknownReason",
        pattern => q{Installing met timeout due to Unknown reason},
        action => q{incValue("errors");
           incValue("/myWorkflow/recover");
           $::gUrgentPropertyChange = 1;
           $::gCommander->abortJobStep($::gStepId, {"reason" => "CTS hung while running"}); },
      },

    You will not get the desired result. incValue() does not look up the current value on the Flow server first. It only increments it's own internal notion of the value that it tracks during the scan of the log file. Any changes made outside postp and any pre-existing value will be ignored.

 

 

Have more questions? Submit a request

Comments

Powered by Zendesk