Skip to content

Commit

Permalink
Append PR number to TF Workspace Name when available (#342)
Browse files Browse the repository at this point in the history
* Append PR number to TF Workspace Name when available
* Re-order names to preserve full WS name on resources with shorter maxlength
* Resolves 'Vault name must be between 3-24 alphanumeric characters. The name must begin with a letter, end with a letter or digit, and not contain consecutive hyphens.'
* Avoid double dashes in names when 'name' var is not present
* scripted workspace name computation
* Configurable PR and resource name isolation
  • Loading branch information
KeithJRome authored Oct 9, 2019
1 parent a5ff6b7 commit bf4963a
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 26 deletions.
4 changes: 3 additions & 1 deletion devops/providers/azure-devops/templates/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ stages:
- template: ./infrastructure/azure-pipeline-cicd-compose.yml
parameters:
environments:
- 'devint'
- name: 'devint'
enablePrIsolation: true
resourceNameIsolationLevel: 8

configurationMatrix:
- jobName: az_hello_world
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
parameters:
environment: ''
enablePrIsolation: true
resourceNameIsolationLevel: 8
configurationMatrix: []
forceRun: false
skipTests: false
Expand All @@ -21,21 +23,28 @@ jobs:
jobName: ${{ config.jobName }}

- ${{ each config in parameters.configurationMatrix }}:
- job: Build_${{ config.jobName }}_${{ parameters.environment }}
- job: Build_${{ config.jobName }}_${{ parameters.environment }}_ComputeWs
dependsOn: TemplateChangeDetection
pool: $(AGENT_POOL)
condition: or(coalesce(variables.FORCE_RUN, ${{ parameters.forceRun }}), eq(dependencies.TemplateChangeDetection.outputs['${{ config.jobName }}.needs_cicd'], 'true'))

steps:
- template: scripts/compute-workspace.yml
parameters:
terraformWorkspacePrefix: ${{ config.terraformWorkspacePrefix }}
environmentName: ${{ parameters.environment }}
enablePrIsolation: ${{ parameters.enablePrIsolation }}
stepName: ComputeWs

- job: Build_${{ config.jobName }}_${{ parameters.environment }}
dependsOn: Build_${{ config.jobName }}_${{ parameters.environment }}_ComputeWs
pool: $(AGENT_POOL)

variables:
- group: '${{ parameters.environment }} Environment Variables'

- ${{ if config.terraformWorkspacePrefix }}:
- name: TF_WORKSPACE_NAME
value: ${{ config.terraformWorkspacePrefix }}-${{ parameters.environment }}

- ${{ if not(config.terraformWorkspacePrefix) }}:
- name: TF_WORKSPACE_NAME
value: ${{ parameters.environment }}
- name: TF_WORKSPACE_NAME
value: $[ dependencies.Build_${{ config.jobName }}_${{ parameters.environment }}_ComputeWs.outputs['ComputeWs.TF_WORKSPACE_NAME'] ]

- name: ARTIFACT_ROOT
value: '$(System.DefaultWorkingDirectory)/$(BUILD_ARTIFACT_NAME)'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ stages:
- template: azure-pipeline-initial-artifact.yml

- ${{ each environment in parameters.environments }}:
- stage: ${{ environment }}_Build
- stage: ${{ environment.name }}_Build
jobs:
- template: azure-pipeline-build-stage.yml
parameters:
environment: ${{ environment }}
environment: ${{ environment.name }}
enablePrIsolation: ${{ environment.enablePrIsolation }}
resourceNameIsolationLevel: ${{ environment.resourceNameIsolationLevel }}
configurationMatrix: ${{ parameters.configurationMatrix }}

- stage: ${{ environment }}_Release
- stage: ${{ environment.name }}_Release
jobs:
- template: azure-pipeline-release-stage.yml
parameters:
environment: ${{ environment }}
environment: ${{ environment.name }}
enablePrIsolation: ${{ environment.enablePrIsolation }}
resourceNameIsolationLevel: ${{ environment.resourceNameIsolationLevel }}
configurationMatrix: ${{ parameters.configurationMatrix }}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
parameters:
environment: ''
enablePrIsolation: true
resourceNameIsolationLevel: 8
configurationMatrix: []
forceRun: false
skipTests: false
Expand All @@ -20,24 +22,31 @@ jobs:
jobName: ${{ config.jobName }}

- ${{ each config in parameters.configurationMatrix }}:
- deployment: Provision_${{ config.jobName }}_${{ parameters.environment }}
- job: Provision_${{ config.jobName }}_${{ parameters.environment }}_ComputeWs
dependsOn: TemplateChangeDetection
pool: $(AGENT_POOL)
condition: or(coalesce(variables.FORCE_RUN, ${{ parameters.forceRun }}), eq(dependencies.TemplateChangeDetection.outputs['${{ config.jobName }}.needs_cicd'], 'true'))

steps:
- template: scripts/compute-workspace.yml
parameters:
terraformWorkspacePrefix: ${{ config.terraformWorkspacePrefix }}
environmentName: ${{ parameters.environment }}
enablePrIsolation: ${{ parameters.enablePrIsolation }}
stepName: ComputeWs

- deployment: Provision_${{ config.jobName }}_${{ parameters.environment }}
dependsOn: Provision_${{ config.jobName }}_${{ parameters.environment }}_ComputeWs
pool: $(AGENT_POOL)

${{ if config.deploymentTimeoutInMinutes }}:
timeoutInMinutes: '${{ config.deploymentTimeoutInMinutes }}'

variables:
- group: '${{ parameters.environment }} Environment Variables'

- ${{ if config.terraformWorkspacePrefix }}:
- name: TF_WORKSPACE_NAME
value: ${{ config.terraformWorkspacePrefix }}-${{ parameters.environment }}

- ${{ if not(config.terraformWorkspacePrefix) }}:
- name: TF_WORKSPACE_NAME
value: ${{ parameters.environment }}
- name: TF_WORKSPACE_NAME
value: $[ dependencies.Provision_${{ config.jobName }}_${{ parameters.environment }}_ComputeWs.outputs['ComputeWs.TF_WORKSPACE_NAME'] ]

- name: RELEASE_ARTIFACT_NAME
value: $(BUILD_ARTIFACT_NAME)-$(TF_WORKSPACE_NAME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ stages:
- template: azure-pipeline-build-stage.yml
parameters:
environment: ${{ environment }}
enablePrIsolation: false
resourceNameIsolationLevel: 0
configurationMatrix: ${{ parameters.configurationMatrix }}
skipTests: true
forceRun: true
Expand All @@ -38,6 +40,8 @@ stages:
- template: azure-pipeline-release-stage.yml
parameters:
environment: ${{ environment }}
enablePrIsolation: false
resourceNameIsolationLevel: 0
configurationMatrix: ${{ parameters.configurationMatrix }}
skipTests: true
forceRun: true
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ stages:
- template: azure-pipeline-cicd-compose.yml
parameters:
environments:
- 'devint'
- 'qa'
- name: 'devint'
enablePrIsolation: true
resourceNameIsolationLevel: 8
- name: 'qa'
enablePrIsolation: false
resourceNameIsolationLevel: 0

configurationMatrix:
- jobName: template_deployment
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
parameters:
terraformWorkspacePrefix: ''
environmentName: ''
enablePrIsolation: true
stepName: ''

steps:
- task: Bash@3
name: ${{ parameters.stepName }}
displayName: Compute and output pipeline variable for Terraform Workspace
env:
TERRAFORM_WORKSPACE_PREFIX: ${{ parameters.terraformWorkspacePrefix }}
ENVIRONMENT_NAME: ${{ parameters.environmentName }}
PR_ISOLATION: ${{ parameters.enablePrIsolation }}
inputs:
targetType: 'inline'
script: |
#!/usr/bin/env bash
# Parses the PullRequest number from sourcebranch, if this is a PR build. Otherwise
# produces a simple combination of prefix+environment to be used as the workspace name.
PR_NUMBER=""
if [[ $PR_ISOLATION == true ]]; then
# BUILD_SOURCEBRANCH will look like "refs/pull/1/merge" if this is a PR branch
IFS='/' # delimiter
read -ra PARTS <<< "$BUILD_SOURCEBRANCH" # split the branch into parts
if [[ "${#PARTS[@]}" == "4" && "${PARTS[0]}" == "refs" && "${PARTS[1]}" == "pull" && "${PARTS[3]}" == "merge" ]]; then
PR_NUMBER="${PARTS[2]}"
fi
fi
OUTVAR=""
if [[ "$PR_NUMBER" != "" ]]; then
if [[ "$TERRAFORM_WORKSPACE_PREFIX" != "" ]]; then
OUTVAR="pr$PR_NUMBER-$TERRAFORM_WORKSPACE_PREFIX"
else
OUTVAR="pr$PR_NUMBER"
fi
else
if [[ "$TERRAFORM_WORKSPACE_PREFIX" != "" ]]; then
OUTVAR="$TERRAFORM_WORKSPACE_PREFIX-$ENVIRONMENT_NAME"
else
OUTVAR="$ENVIRONMENT_NAME"
fi
fi
echo "BUILD_SOURCEBRANCH: $BUILD_SOURCEBRANCH"
echo "TERRAFORM_WORKSPACE_PREFIX: $TERRAFORM_WORKSPACE_PREFIX"
echo "ENVIRONMENT_NAME: $ENVIRONMENT_NAME"
echo "PR_ISOLATION: $PR_ISOLATION"
echo "PR_NUMBER: $PR_NUMBER"
echo "OUTVAR: $OUTVAR"
echo "##vso[task.setvariable variable=TF_WORKSPACE_NAME;isOutput=true]$OUTVAR"
exit 0
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ steps:
env:
TF_VAR_remote_state_container: $(REMOTE_STATE_CONTAINER)
TF_VAR_remote_state_account: $(REMOTE_STATE_ACCOUNT)
TF_VAR_randomization_level: $(resourceNameIsolationLevel)
inputs:
azureSubscription: '$(SERVICE_CONNECTION_NAME)'
addSpnToEnvironment: true
Expand Down Expand Up @@ -35,4 +36,7 @@ steps:
# Setting the scripts to be run as executable
chmod -fR 755 *.sh || true
echo "TF_WORKSPACE_NAME: ${TF_WORKSPACE_NAME}"
echo "TF_VAR_randomization_level: $TF_VAR_randomization_level"
go test -v $(go list ./... | grep "$TERRAFORM_TEMPLATE_PATH" | grep "integration")
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ steps:
TF_VAR_remote_state_container: $(REMOTE_STATE_CONTAINER)
TF_VAR_remote_state_account: $(REMOTE_STATE_ACCOUNT)
TF_VAR_resource_ip_whitelist: $(TF_VAR_resource_ip_whitelist)
TF_VAR_randomization_level: $(resourceNameIsolationLevel)
inputs:
azureSubscription: '$(SERVICE_CONNECTION_NAME)'
addSpnToEnvironment: true
Expand Down Expand Up @@ -57,4 +58,7 @@ steps:
TF_PLAN_FILE="${TF_WORKSPACE_NAME}_plan.out"
TF_CLI_ARGS=${TF_CLI_ARGS:-}
echo "TF_WORKSPACE_NAME: ${TF_WORKSPACE_NAME}"
echo "TF_VAR_randomization_level: $TF_VAR_randomization_level"
terraform apply $TF_CLI_ARGS -input=false -auto-approve $TF_PLAN_FILE
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ steps:
TF_VAR_remote_state_container: $(REMOTE_STATE_CONTAINER)
TF_VAR_remote_state_account: $(REMOTE_STATE_ACCOUNT)
TF_VAR_resource_ip_whitelist: $(TF_VAR_resource_ip_whitelist)
TF_VAR_randomization_level: $(resourceNameIsolationLevel)
inputs:
azureSubscription: '$(SERVICE_CONNECTION_NAME)'
addSpnToEnvironment: true
Expand Down Expand Up @@ -38,4 +39,7 @@ steps:
TF_PLAN_FILE="${TF_WORKSPACE_NAME}_plan.out"
TF_CLI_ARGS=${TF_CLI_ARGS:-}
echo "TF_WORKSPACE_NAME: ${TF_WORKSPACE_NAME}"
echo "TF_VAR_randomization_level: $TF_VAR_randomization_level"
terraform plan $TF_CLI_ARGS -input=false -out $TF_PLAN_FILE
2 changes: 1 addition & 1 deletion infra/templates/az-hello-world/commons.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ locals {
suffix = var.randomization_level > 0 ? "-${random_string.workspace_scope.result}" : ""

// base name for resources, name constraints documented here: https://docs.microsoft.com/en-us/azure/architecture/best-practices/naming-conventions
base_name = "${local.app_id}-${local.ws_name}${local.suffix}"
base_name = length(local.app_id) > 0 ? "${local.ws_name}${local.suffix}-${local.app_id}" : "${local.ws_name}${local.suffix}"
base_name_21 = length(local.base_name) < 22 ? local.base_name : "${substr(local.base_name, 0, 21 - length(local.suffix))}${local.suffix}"
base_name_46 = length(local.base_name) < 47 ? local.base_name : "${substr(local.base_name, 0, 46 - length(local.suffix))}${local.suffix}"
base_name_60 = length(local.base_name) < 61 ? local.base_name : "${substr(local.base_name, 0, 60 - length(local.suffix))}${local.suffix}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ locals {
suffix = var.randomization_level > 0 ? "-${random_string.workspace_scope.result}" : ""

// base name for resources, name constraints documented here: https://docs.microsoft.com/en-us/azure/architecture/best-practices/naming-conventions
base_name = "${local.app_id}-${local.ws_name}${local.suffix}"
base_name = length(local.app_id) > 0 ? "${local.ws_name}${local.suffix}-${local.app_id}" : "${local.ws_name}${local.suffix}"
base_name_21 = length(local.base_name) < 22 ? local.base_name : "${substr(local.base_name, 0, 21 - length(local.suffix))}${local.suffix}"
base_name_46 = length(local.base_name) < 47 ? local.base_name : "${substr(local.base_name, 0, 46 - length(local.suffix))}${local.suffix}"
base_name_60 = length(local.base_name) < 61 ? local.base_name : "${substr(local.base_name, 0, 60 - length(local.suffix))}${local.suffix}"
Expand Down
2 changes: 1 addition & 1 deletion infra/templates/az-service-single-region/commons.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ locals {
suffix = var.randomization_level > 0 ? "-${random_string.workspace_scope.result}" : ""

// base name for resources, name constraints documented here: https://docs.microsoft.com/en-us/azure/architecture/best-practices/naming-conventions
base_name = "${local.app_id}-${local.ws_name}${local.suffix}"
base_name = length(local.app_id) > 0 ? "${local.ws_name}${local.suffix}-${local.app_id}" : "${local.ws_name}${local.suffix}"
base_name_21 = length(local.base_name) < 22 ? local.base_name : "${substr(local.base_name, 0, 21 - length(local.suffix))}${local.suffix}"
base_name_46 = length(local.base_name) < 47 ? local.base_name : "${substr(local.base_name, 0, 46 - length(local.suffix))}${local.suffix}"
base_name_60 = length(local.base_name) < 61 ? local.base_name : "${substr(local.base_name, 0, 60 - length(local.suffix))}${local.suffix}"
Expand Down

0 comments on commit bf4963a

Please sign in to comment.