Link Search Menu Expand Document

Adding custom annotations to Kubernetes YAMLs

Big picture

Move2Kube generates Kubernetes yamls based on the needs of the application. But there might be situations where you might require specific fields to look different in the output. In this example, we illustrate how we could add an annotation to the Ingress YAML specifying an ingress class.

  1. Let us start by creating an empty workspace directory say workspace and make it the current working directory. We will assume all commands are executed within this directory.
      $ mkdir workspace && cd workspace
  2. Lets use the enterprise-app as input for this flow.
      $ curl | bash -s -- -d samples/enterprise-app/src -r move2kube-demos    
      $ ls src		config-utils		customers	docs			frontend		gateway			orders
  3. Let’s first run Move2Kube without any customization. The output ingress does not have any annotation. Once done, lets delete the myproject directory.
      $ move2kube transform -s src/ --qa-skip && cat myproject/deploy/yamls/myproject-ingress.yaml && rm -rf myproject
      kind: Ingress
     creationTimestamp: null
     labels: myproject
     name: myproject
  4. We will use the starlark based custom transformer here. We copy it into the customizations sub-directory.
      $ curl | bash -s -- -d add-custom-kubernetes-annotation -r move2kube-transformers -o customizations
  5. Now lets transform with this customization. Specify the customization using the -c flag.
      $ move2kube transform -s src/ -c customizations/ --qa-skip

Once the output is generated, we can observe from the below snippet of the ingress file (myproject/deploy/yamls/myproject-ingress.yaml) that there is an annotation for the ingress class added ( haproxy):

  $ cat myproject/deploy/yamls/myproject-ingress.yaml
  kind: Ingress
    annotations: haproxy
    creationTimestamp: null
    labels: myproject
    name: myproject

Anatomy of ingress annotator transformer

This custom transformer uses a configuration yaml (ingress-annotator.yaml) and a starlark script ( which adds the annotation to the ingress yaml. The contents of custom transformer are as shown below:

  $ ls customizations/add-custom-kubernetes-annotation  ingress-annotator.yaml

The configuration yaml specifies that the custom transformer consumes and produces kubernetes yaml artifact type as shown in the consumes and produces section.

  $ cat customizations/add-custom-kubernetes-annotation/ingress-annotator.yaml
  kind: Transformer
    name: IngressAnnotator
    labels: false
    class: "Starlark"
        merge: false
        # Ensures a artifact of this type gets immediately intercepted by this transformer
        mode: "MandatoryPassThrough" 
        disabled: false
      starFile: ""

The code of the starlark script is shown below. At a high-level, the code requires only the transform() function as it acts upon any kubernetes yaml generated within Move2Kube. The transform() function loops through every yaml generated for every detected service, checks whether it is an ingress yaml, and if so adds the annotation. The path mappings are meant to persist these changes.

  $ cat customizations/add-custom-kubernetes-annotation/
  def transform(new_artifacts, old_artifacts):
      pathMappings = []
      artifacts = []

      for a in new_artifacts:
          yamlsPath = a["paths"]["KubernetesYamls"][0]
          serviceName = a["name"]

          fileList = fs.read_dir(yamlsPath)
          yamlsBasePath = yamlsPath.split("/")[-1]
          # Create a custom path template for the service, whose values gets filled and can be used in other pathmappings
          pathTemplateName = serviceName + yamlsBasePath
          pathTemplateName = pathTemplateName.replace("-", "")
          tplPathData = {'PathTemplateName': pathTemplateName}
          pathMappings.append({'type': 'PathTemplate', \
                              'sourcePath': "{{ OutputRel \"" + yamlsPath + "\" }}", \
                              'templateConfig': tplPathData})
          for f in fileList:
              filePath = fs.path_join(yamlsPath, f)
              s =
              yamlData = yaml.loads(s)
              if yamlData['kind'] != 'Ingress':
              if 'annotations' not in yamlData['metadata']:
                  yamlData['metadata']['annotations'] = {'': 'haproxy'}
                  yamlData['metadata']['annotations'][''] = 'haproxy'
              s = yaml.dumps(yamlData)
              fs.write(filePath, s)
              pathMappings.append({'type': 'Default', \
                      'sourcePath': yamlsPath, \
                      'destinationPath': "{{ ." + pathTemplateName + " }}"})

      return {'pathMappings': pathMappings, 'artifacts': artifacts}

The above steps can be replicated in the UI, by uploading the zip of the custom transformer as a customization. You can get the zip of the source and customization by adding a -z to the end of the commands used in step 2 and step 4.

Next step Parameterizing custom fields in Helm Chart, Kustomize, OC Templates