How to provide expression as value inside an ssm document? - aws-ssm

I would like to add a server to an ausostaling-group using SSM document, if the group has n instances running - i want to have (n+1).
Since this stack is managed by cloudformation, i just need to increase the 'DesiredCapacity' variable and update the stack. so i created a document with 2 steps:
get the current value of 'DesiredCapacity'
update stack with value of 'DesiredCapacity' + 1
I didnt find a way to express this simple operation, i guess im doing something wrong ...
SSM Document:
schemaVersion: '0.3'
parameters:
cfnStack:
description: 'The cloudformation stack to be updated'
type: String
mainSteps:
- name: GetDesiredCount
action: 'aws:executeAwsApi'
inputs:
Service: cloudformation
Api: DescribeStacks
StackName: '{{ cfnStack }}'
outputs:
- Selector: '$.Stacks[0].Outputs.DesiredCapacity'
Type: String
Name: DesiredCapacity
- name: UpdateCloudFormationStack
action: 'aws:executeAwsApi'
inputs:
Service: cloudformation
Api: UpdateStack
StackName: '{{ cfnStack }}'
UsePreviousTemplate: true
Parameters:
- ParameterKey: WebServerCapacity
ParameterValue: 'GetDesiredCount.DesiredCapacity' + 1 ### ERROR
# ParameterValue: '{{GetDesiredCount.DesiredCapacity}}' + 1 ### ERROR (trying to concat STR to INT)
# ParameterValue: '{{ GetDesiredCount.DesiredCapacity + 1}}' ### ERROR

There is a way to do calculation inside an SSM document using python runtime.
The additional python step do the following:
Python runtime get variables via the the 'InputPayload' property
The 'current' (str) key added to the event object
The python function script_handler called
The 'current' extracted using event['current']
Converting string to int and adding 1
return a dictionary with the 'desired_capacity' key and value as string
expose the output ($.Payload.desired_capacity referred to the 'desired_capacity' of the returned dictionary)
schemaVersion: '0.3'
parameters:
cfnStack:
description: 'The cloudformation stack to be updated'
type: String
mainSteps:
- name: GetDesiredCount
action: 'aws:executeAwsApi'
inputs:
Service: cloudformation
Api: DescribeStacks
StackName: '{{ cfnStack }}'
outputs:
- Selector: '$.Stacks[0].Outputs.DesiredCapacity'
Type: String
Name: DesiredCapacity
- name: Calculate
action: 'aws:executeScript'
inputs:
Runtime: python3.6
Handler: script_handler
Script: |-
def script_handler(events, context):
desired_capacity = int(events['current']) + 1
return {'desired_capacity': str(desired_capacity)}
InputPayload:
current: '{{ GetDesiredCount.DesiredCapacity }}'
outputs:
- Selector: $.Payload.desired_capacity
Type: String
Name: NewDesiredCapacity
- name: UpdateCloudFormationStack
action: 'aws:executeAwsApi'
inputs:
Service: cloudformation
Api: UpdateStack
StackName: '{{ cfnStack }}'
UsePreviousTemplate: true
Parameters:
- ParameterKey: WebServerCapacity
ParameterValue: '{{ Calculate.NewDesiredCapacity}}'

Related

Publishing react app to gitlab using template in backstage

I want to use templates in my local backstage and have been trying to publish a create-react-app to my gitlab instance, but keep getting the following
22022-10-21T22:36:25.000Z HTTPError: Response code 400 (Bad Request)
I have added the integration within my app-config yaml file. There is some connection happening, but seams that I have missed a required attribute for this request. For example, the title for a merge request was not given. A missed a required attribute for this request. For example, the title for a merge request was not given. Wondering whats another required attribute that I am missing for when publishing to gitlab.
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: create-react-app-template
title: Create React App Template
description: Create a new React website project
tags:
- react
- cra
spec:
owner: web#example.com
type: website
parameters:
- title: Provide some simple information
required:
- component_id
- owner
properties:
component_id:
title: Name
type: string
description: Unique name of the component
ui:field: EntityNamePicker
description:
title: Description
type: string
description: Help others understand what this website is for.
owner:
title: Owner
type: string
description: Owner of the component
ui:field: OwnerPicker
ui:options:
allowedKinds:
- Group
- title: Choose a location
required:
- repoUrl
properties:
repoUrl:
title: Repository Location
type: string
ui:field: RepoUrlPicker
ui:options:
allowedHosts:
- gitlab.example.com
steps:
- id: template
name: Fetch Skeleton + Template
action: fetch:template
input:
url: ./skeleton
copyWithoutRender:
- .github/workflows/*
values:
component_id: ${{ parameters.component_id }}
description: ${{ parameters.description }}
destination: ${{ parameters.repoUrl | parseRepoUrl }}
owner: ${{ parameters.owner }}
- id: publish
name: Publish
action: publish:gitlab
input:
allowedHosts:
- gitlab.example.com
description: This is ${{ parameters.component_id }}
repoUrl: ${{ parameters.repoUrl }}
title: Creating catalog-info.yaml ${{ parameters.name }} for backstage
- id: register
name: Register
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
catalogInfoPath: "/catalog-info.yaml"
output:
links:
- title: Repository
url: ${{ steps.publish.output.remoteUrl }}
- title: Open in catalog
icon: catalog
entityRef: ${{ steps.register.output.entityRef }}
When I want to go through the template of the Create React App it creates a
Repo Url -> gitlab.example.com?owner=maxbojorquez&repo=template

Azure Pipelines Automatic retries for a task

This is part of my Yml file
I need to re-call this template if it failed.it should be rerun again. After a few seconds, ideally.I am new to yml files
I tried to use retryCountOnTaskFailure but it should be under task but the template calling different hierarchy
https://learn.microsoft.com/en-us/azure/devops/release-notes/2021/sprint-195-update#automatic-retries-for-a-task
- template: ${{variables['System.DefaultWorkingDirectory']}}
parameters:
Test: ${{ parameters.isTestRelease }}
Environment: ${{ parameters.deploymentTarget }}
Component: '${{ parameters.component }}'
The retryCountOnTaskFailure feature is applied to individual tasks within a pipeline. Templates aren't tasks, they act more like an include that expands the contents of the template into your pipeline.
# pipeline.yml
trigger: none
parameters:
- name: isTestRelease
type: boolean
default: false
- name: deploymentTarget
type: string
default: DEV
values:
- DEV
- QA
- UAT
- PROD
- name: component
type: string
default: 'x'
stages:
- template: my-template.yml
parameters:
Test: ${{ parameters.isTestRelease }}
Environment: ${{ parameters.deploymentTarget }}
Component: ${{ parameters.component }}
And within the template, you'd want to add the retry logic to specific tasks:
# my-template.yml
parameters:
- name: isTestRelease
type: boolean
- name: component
type: string
stages:
- stage: Test
jobs:
- job: 1
steps:
- task: ...
- task: ...
- task: ...
retryCountOnFailure: 2
- task: ...
It's also located under "Control Options" when the "Command Line" task is added:

Azure pipeline expand each parameter when using template

I have the following setup, a template file, and a pipeline that extends the template. I am wondering is it possible to dynamically add all parameters to extends' parameter?
Template.yml
parameters:
- name: Location
type: string
default: 'eastus'
Washington.yml
parameters:
- name: Location
type: string
default: 'westus'
extends:
template: Template.yml
parameters:
Location: ${{ parameters.Location }}
I can do something like this but I think it doesn't work because the shadowed parameters variable will be used instead of root level parameters.
parameters:
- name: Location
type: string
default: 'westus'
extends:
template: Template.yml
parameters:
- ${{ each param in parameters }}
${{ param.Name }}: ${{ param.Value }}
This works for me:
parameters:
- name: Location
type: string
default: 'westus'
extends:
template: Template.yml
parameters:
${{ each param in parameters }}:
${{ param.Key }}: ${{ param.Value }}
So you had small syntax issues.
It printed:
Assuming that template is:
parameters:
- name: Location
type: string
default: 'eastus'
steps:
- script: echo ${{ parameters.Location }}

How to pass variables to the template parameter in azure yaml?

I have template
dockerbuild.yml
steps:
- task: Bash#3
displayName: Build an image to container registry
inputs:
script : echo $(PATH)
then a variable file
var.build.yml
- name: PATH
value: 'docker/path'
- name: PATH1
value: 'docker/oldpath'
- name: PATH2
value: 'docker/newpath'
azurepipeline1.yml
resources:
repositories:
- repository: templates
type: git
name: components/pipeline_templates
trigger:
- none
pool:
name: PoolA
variables:
- template: variabletemplates/var.build.yml#templates
jobs:
steps:
- template: CI-CD/dockerbuild.yml#templates # Template reference
parameters:
PATH: ${{ variables.PATH }}
- template: CI-CD/dockerbuild.yml#templates # Template reference
parameters:
PATH: ${{ variables.PATH1 }}
- template: CI-CD/dockerbuild.yml#templates # Template reference
parameters:
PATH: ${{ variables.PATH2 }}
The above code works
But if I change the parameter to
parameters:
PATH: ${{ variables.PATH1 }}
OR
parameters:
PATH: ${{ variables.PATH2 }}
In the output it shows
Output:
docker/path
$(PATH1)
$(PATH2)
I need to reuse the template with many times within the pipeline with different paths. Please help in resolving the issue
Your template needs a parameters block.
parameters:
- name: PATH
type: string
steps:
- task: Bash#3
displayName: Build an image to container registry
inputs:
script : echo ${{ parameters.PATH }}

Is it possible to mix map arguments in Azure Pipelines template yaml? How?

I wonder if it is possible to mix map arguments in Azure Pipelines template yaml, and how to do it.
These two scenarios shown bellow do same thing: place template parameter as env argument in a task, but in the second I'm trying to do it through two maps instead of a single one. That could be useful when I have different purposes to those values (at the eyes of someone who is extending the template) but both are going to be used as 'env' under the hood.
This works fine:
Main Pipeline:
...
extends:
template: templates/deploy/v1/deployment.job.yaml#infrastructure-templates
parameters:
name: dev
variableGroup: 'AzureDevopsVariableGroupName'
secretEnvVariables:
SECRET1: ${SECRET1}
SECRET2: ${SECRET2}
Target Template:
parameters:
- name: secretEnvVariables
type: object
jobs:
...
steps:
- bash: |
#!/bin/bash
echo "SECRET1 = ${SECRET1}"
...
displayName: Substitute Env VARS on files
enabled: true
env:
${{ parameters.secretEnvVariables }}
This doesn't work (and I wonder if it is possible to make it work):
Main Pipeline:
...
extends:
template: templates/deploy/v1/deployment.job.yaml#infrastructure-templates
parameters:
name: dev
variableGroup: 'AzureDevopsVariableGroupName'
secretEnvVariables:
SECRET1: ${SECRET1}
SECRET2: ${SECRET2}
moreVariables:
VAR1: ${VAR1}
Target Template:
parameters:
- name: secretEnvVariables
type: object
- name: moreVariables
type: object
jobs:
...
steps:
- bash: |
#!/bin/bash
echo "SECRET1 = ${SECRET1}"
echo "VAR = ${VAR1}"
...
displayName: Substitute Env VARS on files
enabled: true
env:
${{ parameters.secretEnvVariables }}
${{ parameters.moreVariables }}
Can it be done? How to do it?
I am doing something similar and this isn't well documented but can use objects to accomodate for this.
Here it is the combo of environment and region deployment:
- name: environmentObjects
type: object
default:
- environmentName: 'dev'
regionAbrvs: ['eus']
- environmentName: 'uat'
regionAbrvs: ['eus', 'cus']
From there it would be a loop to access each one like:
- ${{ each environmentObject in parameters.environmentObjects }} :
- ${{ each regionAbrv in enviornmentObject.regionAbrvs }} :
This should work for your scenario as well.

Resources