variablesazure-devopsyamlazure-pipelinesazure-pipelines-yaml

Azure Pipelines - Replace a variable in a yaml file


I have a deployment pipeline that uses a Kubernetes task:

          - task: Kubernetes@1
            displayName: 'Apply deployment'
            inputs:
              connectionType: '***'
              namespace: '***'
              command: 'apply'
              useConfigurationFile: true
              configuration: '$(System.DefaultWorkingDirectory)/deploy/kube/api/deployment.yaml'
              secretType: 'generic'

This task uses another yaml file (deployment.yaml) I would like to vary some data in my deployment.yaml For this I tested Yaml writer

Which works well except for resource tables. Example: I have in deployment.yaml:

spec:
  template:
    spec:
      containers:
        - name: api
          image: 'imageVersion'

I want to change the 'image' property, which gives us spec.template.spec.containers[0].image

          - task: YamlWriter@0
            inputs:
              file: '$(System.DefaultWorkingDirectory)/deploy/kube/api/deployment.yaml'
              set: "spec.template.spec.containers['api'].image='my-image:latest'"

The value is replaced, however it also adds 'containers[0]': {} at the end of deployment.yaml.

How to fix this / do you have any alternatives that can solve this need without using a script with the sed command?

Thanks a lot 🙏


Solution

  • I can reproduce the same situation when using the Yaml Writer task in Azure Pipelines. It will add additional value 'containers[0]': {} at the end of the YAML file. It seems that it cannot correctly handle the contents of the resource table inside the Yaml file.

    How to fix this / do you have any alternatives that can solve this need without using a script with the sed command?

    To meet your requirement, you can change to use the following methods:

    Method1: you can try to use the Replace Token task from Replace Tokens Extension.

    Here are the steps:

    Step1: Add placeholder character in the yaml file with the format: ${PipelinevariableName}#

    For example:

    spec:
      template:
        spec:
          containers:
            - name: api
              image: '#{APIimageversion}#'
    

    Step2: In Azure Pipeline, you can add the replace token task and set the Pipeline variable(the same name as the name in placeholder character).

    For example:

    variables:
      APIimageversion: my-image:latest
    
    - task: qetza.replacetokens.replacetokens-task.replacetokens@6
      displayName: 'Replace tokens'
      inputs:
        root: '$(System.DefaultWorkingDirectory)/deploy/kube/api'
        sources: deployment.yaml
    

    Result:

    enter image description here

    Method2: If you don't want to use placeholder character in YAML file, you can use the RegEx Match & Replace task from RegEx Match & Replace extension.

    This task will use regular expressions to match fields in the file.

    Here is an example:

    spec:
      template:
        spec:
          containers:
            - name: api
              image: 'imageVersion'
    

    Task sample:

    steps:
    - task: RegExMatchReplace@2
      displayName: 'RegEx Match & Replace'
      inputs:
        PathToFile: $(System.DefaultWorkingDirectory)/deploy/kube/api/deployment.yaml
        RegEx: "image: '[A-Za-z]+'"
        ValueToReplace: "image: 'my-image:latest'"
    

    You can use this site to convert the regular expressions : Regex Generator