3

I'm trying to figure out how I can use yaml pipelines to deploy an application to a multi web-node environment.

I'm trying to create a pipeline with 2 stages. Stage 1 will build the project, and stage 2 will deploy it to a staging environment. This staging environment (currently) has 2 web nodes. I don't want to hardcode the actual machines to deploy to into my pipeline. So I thought I'd add a variable group with a variable containing the web nodes to deploy to, and use a "each" statement to generate a job per node.

However, this doesn't work for several reasons:

  • The jobs are generated before the variable group is read, so it shows an error it cannot find the variable
  • Apparently an array variable is not supported at all, except for the built in variables

So my question is, how do other people solve this? I'd like to define the servers to deploy to in a central place, and not in my pipeline definition.

My initial attempt is printed below. This doesn't work, but it does describe what I'm trying to accomplish.

Main yaml:

variables:
- group: LicenseServerVariables #this contains StagingWebNodes variable

stages:
- stage: Build
  displayName: Build
  <some build steps>

- stage: DeployTest
  displayName: Deploy on test
  condition: and(succeeded(), eq(variables['DeployToTest'], 'true'))
  jobs:
  - template: Templates\Deploy.yaml
    parameters:
      nodes: $(StagingWebNodes)

Deploy.yaml:

parameters:
  nodes: []

jobs:
- ${{ each node in parameters.nodes }}:
  - job: ${{ node }}
    displayname: deploy to ${{ node }}
    pool: Saas Staging
      demands: ${{ node }}
    steps:
    - template: DeployToNode.yaml

edit:

I'm a bit closer to a solution. I was able to get the pipeline to work with the "each" construct using the following adjustment to the Deploy.yaml:

parameters:
  nodes: 
  - name: 'Node1'
    pool: 
      name: StagingPool
      demands: 'Node1'
  - name: 'Node2'
    pool: 
      name: StagingPool
      demands: 'Node2'

jobs:
- ${{ each node in parameters.nodes }}:
  - job: ${{ node.name }}
    displayName: deploy to ${{ node.name }}
    pool: ${{ node.pool }}
    steps:
    - template: DeployToNode.yaml

This makes it a bit better. However, I still don't want to define the "nodes" parameter in my pipeline yaml source, but in a variable group (or some other place if anyone has a good suggestion)

PaulVrugt
  • 1,682
  • 2
  • 17
  • 40
  • As our designed, the variable group object is a list of **single-level mappings**. If you want to achieve hide some sensitive message in variable group, you need split your current map. Like **job name** must get value from server once you queue the build. This needs node.name must be hard coded in YAML. And then, other variables could store at variable group. What about this method? – Mengdi Liang Nov 22 '19 at 13:04
  • 1
    Thanks for your reply! Unfortunately that doesn't solve my issue with x nodes. I want to be able to define the nodes in something else than my yaml. But it seems the current design has me stuck at naming all the nodes within my yaml. Hopefully the upcoming support for rolling deployment and virtual machine resources fixes this issue – PaulVrugt Nov 22 '19 at 18:12
  • I got a crazy idea inspired by my recent work, but it's **downside** is would let your script more complication. Though Variable group does not allow multi-level mapping, you could store them in JSON file by using nested array. Then use powershell script to compile them out as variables. – Mengdi Liang Nov 28 '19 at 02:17
  • I'm not sure I understand what you mean. Could you give me a basic example? Then I'll test it and see if resolves my issue – PaulVrugt Nov 28 '19 at 13:06

1 Answers1

1

With the addition of virtual machines as resource for environments this issue has gone away. I can now use a rolling deployment task to deploy the apppicatio to all web nodes

PaulVrugt
  • 1,682
  • 2
  • 17
  • 40