Stitch processors

A Stitch processor is a part of a Stitch rule that is responsible for modifying the application’s resource configuration files during the deployment planning phase. Processors are defined in a Stitch YAML file in the processor array. A processor is applied if the condition in the Stitch rule containing the processor is satisfied. Processors are ordered by phase and weight properties. Each processor’s output is merged with the input(the output from the previous processor).

Here’s an example of a Stitch rule with a processor that adds a label to any Kubernetes resource file:

 kind: Rules
 metadata:
   namespace: k8s-labels
 spec:
   - name: "k8s.AddLabel"
     condition:
       deployedType: k8s.Resources
     processor:
       - type: freemarker
         description: "Adding label to kubernetes spec"
         phase: POST_FLIGHT
         weight: 30
         merge:
           type: overlay
         parameters:
           template: |
             { "metadata" : {
                "labels": {
                  "labelToAdd": "addedLabel"
                }
               }
             }

Processor types

You can specify the type of a Stitch processor in the type property, as shown in the example above. Some of the supported processor types are:

  • FreeMarker (type: freemarker)
  • jsonpatch (type: patch)
  • Groovy (type: groovy)
  • Macro (type: macroname)
  • AddYamlObject (type: addYamlObject)

You can also create a new processor type with custom defined handling.

Note: Only if a supported processor type is not found in either the core or the custom types, then Deploy will try to apply a Macro. See Stitch Macros for information about Macros usage.

FreeMarker processor type

The FreeMarker processor type is used to render FreeMarker templates (see Official FreeMarker documentation). A FreeMarker template has direct access to the deployment context through the ctx variable, as defined by the Java interface com.xebialabs.deployit.plugin.stitch.service.engine.context.DeploymentContext

Parameters
  • template - inline FreeMarker template
  • templateFile - the relative path to the external file containing FreeMarker template
  • variables - variables that can be used to render the FreeMarker template. It is possible to resolve them using SpEL expressions.

Important: You can define either the template parameter or the templateFile parameter, but not both.

Here’s an example of using the FreeMarker processor with inline template definition: :

...
- type: freemarker
  description: "Adding label to kubernetes spec"
  parameters:
    template: |
      { "metadata" : {
         "labels": {
           "myLabel": "${myValue}",
           "fromContext": "${ctx.environment.name}"
         }
        }
      }
    variables:
      myValue: the value
...

Here’s an example of a FreeMarker processor using an external template file:

...
- type: freemarker
  description: "Adding label to kubernetes spec with external ftl file"      
  parameters:
    templateFile: templates/myTemplate.ftl
...

JSON Patch processor type

A JSON Patch processor type is used for small scale adjustments to the input file. The full specification for the JSON patch can be found here. Stitch supports all JSON Patch operations such as: add, remove, replace, copy, move, test. For test operation, if the condition isn’t met whole patch is not applied, resulting in the processor being ignored.

Parameters
  • patch - patch to be applied, it has same format as the JSON Patch but in YAML
  • patchFile - external patch file, both YAML and JSON files are supported

Important: You can define either the patch parameter or the patchFile parameter, but not both.

Here’s an example of using a JSON Patch processor type:

- type: patch
  description: "Using patching to create and change content"
  parameters:
    patch:
      - op: add
        path: "/base/patchAdd"
        value: "I was added"
      - op: replace
        path: "/base/replace"
        value: "I was replaced"
      - op: remove
        path: "/base/remove"

Here’s an example of a JSON patch processor type using an external file (.json, .yaml and .yml file extensions are supported):

...
- type: freemarker
  description: "Using patch processor with external json file"      
  parameters:
    patchFile: patches/patch.json
...

Groovy processor type

This processor allows modifying the input using Groovy scripts. A Groovy script can be provided using one of the two parameters, script or scriptFile. A Groovy script should have a method with a name stitch and four arguments: spec, params, document, context.

Parameters
  • script - inline Groovy script to be executed
  • scriptFile - external Groovy script file to be executed
Stitch method arguments

spec - original input in a JSON string format params - parameters from a processor document - a Document instance based on a Document API, which is a part of the stitch-api library (interface com.xebialabs.deployit.plugin.stitch.service.engine.processor.handler.groovy.Document). It can be used to modify the input in a useful way and add/remove/update any properties of the input document. To return the modified version of the document, thedocument.getMutatedDocument() method is used. See the following example to get more insight.

Example of an inline Groovy script:

...
- type: groovy
  description: "Using groovy processor with inline groovy script."      
  parameters:
    script: |
      import com.xebialabs.deployit.plugin.stitch.service.engine.processor.handler.groovy.MapFunction
      def stitch(spec, params, document, ctx) {
        document.map('$..labels', new MapFunction() {
          Object map(currentValue) {
            currentValue.put("myCustomLabel", "myGroovyValue")
            currentValue
          }
        })
        document.getMutatedDocument()
      }
...

Example of an external Groovy script file:

...
- type: groovy
  description: "Using groovy processor with external groovy script."      
  parameters:
    scriptFile: groovy/script.groovy
...

Add YamlObject processor type

This processor allows easy appending of a YAML object into an array. A YAML object can be provided using one of the two parameters, yaml or yamlFile. If the input into this processor is not an array there won’t be any change to it.

Parameters
  • yaml - inline yaml file to be appended into input list
  • yamlFile - external yaml file to be appended into input list

Example of an AddYamlProcessor with an inline YAML object:

...
- type: addYamlObject
  description: "Using add yaml object processor to add k8s PDB"
  merge:
    type: none
  parameters:
    yaml: |
      apiVersion: policy/v1beta1
      kind: PodDisruptionBudget
      metadata:
        name: zk-pdb
      spec:
        minAvailable: 2
        selector:
          matchLabels:
            app: pet-clinic
...

Example of an AddYamlObject processor with an external YAML file:

...
- type: addYamlObject
  description: "Using addYamlObject with external yaml file to add k8s PDB."      
  parameters:
    yamlFile: yaml/k8s-pdb.yaml
...

Ordering execution with phase and weight

The execution order of Stitch processors is determined by two properties, phase and weight. First, all the processors are grouped by phase. Then within a phase, all processors are ordered by weight. In this way, all phases are executed in order. While both phase and weight properties require integer values, for phases, there are also the following predefined constants with their integer values:

  • PRE_FLIGHT - 0
  • BASE_DEFINITION - 10
  • GENERATE - 20
  • TRANSFORM - 50
  • OVERLAY - 60
  • PATCH_ADD - 70
  • PATCH - 80
  • PATCH_REMOVE - 90
  • POST_FLIGHT - 100

Both phase and weight properties are optional. The default value for phase is TRANSFORM and for weight is 50.

Note: The order of the execution is deterministic. Given the same definition, it will always execute in the same order, even if processors have the same phase and weight. With that in mind, processors that have same phase and weight shouldn’t be transforming same things in input.

Merging documents

The merge property specifies how the result of the current processor is merged with the result of the previous processor. This means that the output of one processor is the input of the next processor, where starting input comes from the plugin. Property is not required and default value is overlay.

Merge types

  • overlay - merge at the root, making the current content overlay possible existing data.
  • jsonPath - merge at the root(s) found by defined json path, also overlaying from that point in tree. It is possible to merge from multiple points in the tree. You can also see the specification for json path here.
  • none - do not merge output with the input, return the output from the current processor as is.

Here’s an example of merge types definitions:

...
- type: freemarker
  merge:
    type: overlay
...

and:

...
- type: freemarker
  merge:
    type: jsonpath
    path: "$.store.book[0]"
...

SpEL expressions

SpEL (Spring Expression Language) is a powerful expression language. In processors, it is used to resolve values of variables from the processor parameter. The only variable available inside those expressions is ctx, which is the deployment context as defined by the Java interface com.xebialabs.deployit.plugin.stitch.service.engine.context.DeploymentContext.

SpEL is also used for conditions in Rules and to resolve parameters in Macros. Here’s an example of using SpEL to resolve variables in processor:

...
- type: freemarker
  description: "Adding label to kubernetes spec"
  parameters:
    template: |
      { "metadata" : {
         "labels": {
           "application": "${application}",
           "environment": "${environment}"
         }
        }
      }
    variables:
      application: "#{#ctx.deployedApplication.id}"
      environment: "#{#ctx.deployedApplication.environment.name}"

...

Custom processors

You can create new processor types which is explained here.