diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..8bf9d4b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,111 @@ +name: "Bug report \U0001F41B" +description: Report errors or unexpected behaviour +title: "bug:" +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to fill out a bug report. + + If you are not running the latest version of this module, please try to reproduce your bug with the latest version before opening an issue. + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + - type: dropdown + attributes: + label: Bootstrap or Starter Module Deployment? (Required) + description: Do you have a problem with deploying the Bootstrap Resources or the Starter Module through CI/CD? + multiple: false + options: + - bootstrap + - starter_module + validations: + required: true + - type: input + id: ps_module + attributes: + label: ALZ-PowerShell-Module Version (Required) + description: Which ALZ-PowerShell-Module version are you using? + placeholder: Example value, 1.1.6 + validations: + required: true + - type: input + id: alz_tf_acc + attributes: + label: alz-terraform-accelerator Version (Required) + description: Which alz-terraform-accelerator version are you using? + placeholder: Example value, 1.1.0 + validations: + required: true + - type: input + id: starter_module + attributes: + label: Starter Module (Required) + description: Which Starter Module are you using? + placeholder: Example value, complete + validations: + required: true + - type: textarea + id: inputs + attributes: + label: Input arguments of the ALZ-PowerShell-Module (Required) + description: | + Please provide the input arguments of the ALZ-PowerShell-Module that can reproduce the issue. If not stated explicitly please find these details in the `cache-bootstrap-.json` and `cache-starter-.json` files in the copy of the alz-terraform-accelerator that the ALZ-PowerShell-Module downloaded on execution. + render: YAML + validations: + required: true + - type: textarea + id: config + attributes: + label: Contents of the configuration file used for the `complete` starter module. (Optional) + description: | + Please provide contents of the configuration file used for the `complete` starter module. + render: YAML + - type: textarea + id: debug + attributes: + label: Debug Output/Panic Output (Optional) + description: | + For long debug logs please provide a link to a GitHub Gist containing the complete debug output. Please do NOT paste the debug output in the issue; just paste a link to the Gist. + + To obtain the debug output, see the [Terraform documentation on debugging](https://www.terraform.io/docs/internals/debugging.html). + render: shell + - type: textarea + id: expected + attributes: + label: Expected Behaviour (Required) + description: What should have happened? + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual Behaviour (Required) + description: What actually happened? + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to Reproduce (Optional) + description: | + Please list the steps required to reproduce the issue, e.g. + - type: input + id: facts + attributes: + label: Important Factoids (Optional) + description: | + Are there anything atypical about your accounts that we should know? For example: Running in a Azure China/Germany/Government? + - type: textarea + id: references + attributes: + label: References (Optional) + description: | + Information about referencing Github Issues: https://help.github.com/articles/basic-writing-and-formatting-syntax/#referencing-issues-and-pull-requests + + Are there any other GitHub issues (open or closed) or pull requests that should be linked here? Such as vendor documentation? diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..bd9dfe4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,2 @@ +--- +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..f361483 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,31 @@ +--- +name: "Feature request \U0001F680" +about: Suggest an idea for this project +title: 'Feature Request' +labels: 'needs triage :warning:' +assignees: '' +--- + +### Community Note + + + +- Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request +- Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request +- If you are interested in working on this issue or have submitted a pull request, please leave a comment + + + +### Description + +**Is your feature request related to a problem?** + + + +**Describe the solution you'd like** + + + + + +**Additional context** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..b001836 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,27 @@ + +## Overview/Summary + +Replace this with a brief description of what this Pull Request fixes, changes, etc. + +## This PR fixes/adds/changes/removes + +1. *Replace me* +2. *Replace me* +3. *Replace me* + +### Breaking Changes + +1. *Replace me* +2. *Replace me* + +## Testing Evidence + +Please provide any testing evidence to show that your Pull Request works/fixes as described and planned (include screenshots, if appropriate). + +## As part of this Pull Request I have + +- [ ] Checked for duplicate [Pull Requests](https://github.com/Azure/alz-terraform-accelerator/pulls) +- [ ] Associated it with relevant [issues](https://github.com/Azure/alz-terraform-accelerator/issues), for tracking and closure. +- [ ] Ensured my code/branch is up-to-date with the latest changes in the `main` [branch](https://github.com/Azure/alz-terraform-accelerator/tree/main) +- [ ] Performed testing and provided evidence. +- [ ] Updated relevant and associated documentation. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f364ef3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +--- +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "terraform" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 0000000..61f8bc2 --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,36 @@ +--- +########################### +########################### +## Markdown Linter rules ## +########################### +########################### + +# Linter rules doc: +# - https://github.com/DavidAnson/markdownlint +# +# Note: +# To comment out a single error: +# +# any violations you want +# +# + +############### +# Rules by id # +############### +MD004: false # ul-style - Unordered list style +MD007: + indent: 2 # ul-indent - Unordered list indentation +MD013: + line_length: 400 # line-length - Line length +MD026: + punctuation: ".,;:!。,;:" # no-trailing-punctuation - Trailing punctuation in heading +MD029: false # ol-prefix - Ordered list item prefix +MD033: false # no-inline-html - Inline HTML +MD036: false # no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD041: false # first-line-heading/first-line-h1 - First line in a file should be a top-level heading + +################# +# Rules by tags # +################# +blank_lines: false # MD012, MD022, MD031, MD032, MD047 diff --git a/.github/linters/.yaml-lint.yml b/.github/linters/.yaml-lint.yml new file mode 100644 index 0000000..01c763d --- /dev/null +++ b/.github/linters/.yaml-lint.yml @@ -0,0 +1,11 @@ +--- +extends: default + +rules: + # 200 chars should be enough, but don't fail if a line is longer + line-length: + max: 200 + level: warning + truthy: + check-keys: false + level: warning diff --git a/.github/tests/README.md b/.github/tests/README.md new file mode 100644 index 0000000..5a447e1 --- /dev/null +++ b/.github/tests/README.md @@ -0,0 +1,34 @@ +# End to End Tests + +## Overview + +The end to end tests can be found in the ./github/workflows/end-to-end-test.yml action. + +- The tests are triggered by `workflow_dispatch` or on `pull_request` only when the label `PR: Safe to test 🧪` has been added to the PR. +- The tests run against the environment `CSUTF`, which requires a manual approval to deploy. +- The tests run as a matrix, targeting different OS, VCS, Terraform and Auth Methods. + +## Test Process + +The test follow this process: + +1. Check out the module from the PR merge branch. +1. Generate an `inputs.json` file that is used to override the prompts in the `ALZ` PowerShell module. +1. Install the `ALZ` PowerShell module. +1. Get the latest version tag for the live accelerator module. +1. Copy the `boostrap` and `template` folders into a folder named by the latest version tag. +1. Run the `New-New-ALZEnvironment` function to deploy the terraform. +1. Run a `terraform destroy` to clean up the environment. + +## Environment + +The tests use a set of environemnts to managed by the ALZ team. These are: + +- Azure: + - Tenant: CSU TF + - Subscription: csu-tf-devops + - User Assigned Managed Identity: alz-terraform-accelerator-cd-tests-identity (this has federated credentials) +- Azure DevOps + - Organisation: microsoft-azure-landing-zones-cd-tests +- GiHub + - Organisation: microsoft-azure-landingzones-cd-tests diff --git a/.github/tests/cleanup-scripts/cleanup_github-repositories.ps1 b/.github/tests/cleanup-scripts/cleanup_github-repositories.ps1 new file mode 100644 index 0000000..7a47fcc --- /dev/null +++ b/.github/tests/cleanup-scripts/cleanup_github-repositories.ps1 @@ -0,0 +1,15 @@ +# This file can be used to clean up GitHub repositories if there has been an issue with the End to End tests. +# CAUTION: Make sure you are connected to the correct organization before running this script! +$repos = gh repo list microsoft-azure-landing-zones-cd-tests --json name,owner | ConvertFrom-Json + +$repos | ForEach-Object -Parallel { + $match = "*229*" + $repoName = "$($_.owner.login)/$($_.name)" + + if($repoName -like $match) + { + Write-Host "Deleting repo: $repoName" + gh repo delete $repoName --yes + + } +} -ThrottleLimit 10 diff --git a/.github/tests/cleanup-scripts/cleanup_resouce_groups.ps1 b/.github/tests/cleanup-scripts/cleanup_resouce_groups.ps1 new file mode 100644 index 0000000..535a58d --- /dev/null +++ b/.github/tests/cleanup-scripts/cleanup_resouce_groups.ps1 @@ -0,0 +1,9 @@ +# This file can be used to clean up Resource Groups if there has been an issue with the End to End tests. +# CAUTION: Make sure you are connected to the correct subscription before running this script! +az account show +$resourceGroups = az group list --query "[?contains(name, '254-')]" | ConvertFrom-Json + +$resourceGroups | ForEach-Object -Parallel { + Write-Host "Deleting resource group: $($_.name)" + az group delete --name $_.name --yes +} -ThrottleLimit 10 diff --git a/.github/tests/scripts/Install-AcceleratorModule.ps1 b/.github/tests/scripts/Install-AcceleratorModule.ps1 new file mode 100644 index 0000000..727db9c --- /dev/null +++ b/.github/tests/scripts/Install-AcceleratorModule.ps1 @@ -0,0 +1,13 @@ +param ( + [string]$ModuleUrl = "https://github.com/Azure/ALZ-PowerShell-Module", + [string]$ModuleBranch = "main" +) + +$targetDirectory = "./accelerator-powershell-module" + +if(!(Test-Path $targetDirectory)) { + git clone -b $ModuleBranch $ModuleUrl $targetDirectory +} + +./accelerator-powershell-module/actions_bootstrap_for_e2e_tests.ps1 | Out-String | Write-Verbose +Invoke-Build -File ./accelerator-powershell-module/src/ALZ.build.ps1 BuildAndInstallOnly | Out-String | Write-Verbose diff --git a/.github/tests/scripts/azuredevops-pipeline-run.ps1 b/.github/tests/scripts/azuredevops-pipeline-run.ps1 new file mode 100644 index 0000000..4e93ab8 --- /dev/null +++ b/.github/tests/scripts/azuredevops-pipeline-run.ps1 @@ -0,0 +1,159 @@ +param ( + [string]$organizationName, + [string]$projectName, + [string]$personalAccessToken, + [string]$pipelineNamePart = "Continuous Delivery", + [switch]$skipDestroy = $false, + [int]$maximumRetries = 10, + [int]$retryCount = 0, + [int]$retryDelay = 10000 +) + +function Invoke-Pipeline { + param ( + [string]$organizationName, + [string]$projectName, + [int]$pipelineId, + [string]$pipelineAction = "", + [hashtable]$headers + ) + $pipelineDispatchUrl = "https://dev.azure.com/$organizationName/$projectName/_apis/pipelines/$pipelineId/runs?api-version=7.2-preview.1" + Write-Host "Pipeline Dispatch URL: $pipelineDispatchUrl" + + $pipelineDispatchBody = @{} + if($pipelineAction -eq "") { + $pipelineDispatchBody = @{ + "resources" = @{ + "repositories" = @{ + "self" = @{ + "refName" = "refs/heads/main" + } + } + } + } | ConvertTo-Json -Depth 100 + } else { + $pipelineDispatchBody = @{ + "resources" = @{ + "repositories" = @{ + "self" = @{ + "refName" = "refs/heads/main" + } + } + } + "templateParameters" = @{ + "terraform_action" = $pipelineAction + } + } | ConvertTo-Json -Depth 100 + } + + $result = Invoke-RestMethod -Method POST -Uri $pipelineDispatchUrl -Headers $headers -Body $pipelineDispatchBody -StatusCodeVariable statusCode -ContentType "application/json" + if ($statusCode -ne 200) { + throw "Failed to dispatch the pipeline." + } + + # Get the pipeline run id + $pipelineRunId = $result.id + Write-Host "Pipeline Run ID: $pipelineRunId" + return [int]$pipelineRunId +} + +function Wait-ForPipelineRunToComplete { + param ( + [string]$organizationName, + [string]$projectName, + [int]$pipelineId, + [int]$pipelineRunId, + [hashtable]$headers + ) + + $pipelineRunUrl = "https://dev.azure.com/$organizationName/$projectName/_apis/pipelines/$pipelineId/runs/$($pipelineRunId)?api-version=7.2-preview.1" + Write-Host "Pipeline Run URL: $pipelineRunUrl" + + $pipelineRunStatus = "" + $pipelineRunResult = "" + while($pipelineRunStatus -ne "completed") { + Start-Sleep -Seconds 10 + $pipelineRun = Invoke-RestMethod -Method GET -Uri $pipelineRunUrl -Headers $headers -StatusCodeVariable statusCode + if ($statusCode -lt 300) { + $pipelineRunStatus = $pipelineRun.state + $pipelineRunResult = $pipelineRun.result + Write-Host "Pipeline Run Status: $pipelineRunStatus - Conclusion: $pipelineRunResult" + } else { + Write-Host "Failed to find the pipeline run. Status Code: $statusCode" + throw "Failed to find the pipeline run." + } + } + + if($pipelineRunResult -ne "succeeded") { + throw "The pipeline run did not complete successfully. Conclusion: $pipelineRunResult" + } +} + +# Setup Variables +$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$personalAccessToken")) +$headers = @{ + "Authorization" = "Basic $token" + "Accept" = "application/json" +} + +# Run the Module in a retry loop +$success = $false + +do { +$retryCount++ +try { + # Get the pipeline id + Write-Host "Getting the pipeline id" + $pipelinesUrl = "https://dev.azure.com/$organizationName/$projectName/_apis/pipelines?api-version=7.2-preview.1" + Write-Host "Pipelines URL: $pipelinesUrl" + $pipelines = Invoke-RestMethod -Method GET -Uri $pipelinesUrl -Headers $headers -StatusCodeVariable statusCode + if ($statusCode -ne 200) { + throw "Failed to find the pipelines." + } + $pipeline = $pipelines.value | Where-Object { $_.name -like "*$pipelineNamePart*" } + + $pipelineId = $pipeline.id + Write-Host "Pipeline ID: $pipelineId" + + $pipelineAction = "" + if(!($skipDestroy)) { + $pipelineAction = "apply" + } + + # Trigger the apply pipeline + Write-Host "Triggering the $pipelineAction pipeline" + $pipelineRunId = Invoke-Pipeline -organizationName $organizationName -projectName $projectName -pipelineId $pipelineId -pipelineAction $pipelineAction -headers $headers + Write-Host "$pipelineAction pipeline triggered successfully" + + # Wait for the apply pipeline to complete + Write-Host "Waiting for the $pipelineAction pipeline to complete" + Wait-ForPipelineRunToComplete -organizationName $organizationName -projectName $projectName -pipelineId $pipelineId -pipelineRunId $pipelineRunId -headers $headers + Write-Host "$pipelineAction pipeline completed successfully" + + if($skipDestroy) { + $success = $true + break + } + + $pipelineAction = "destroy" + + # Trigger the destroy pipeline + Write-Host "Triggering the $pipelineAction pipeline" + $pipelineRunId = Invoke-Pipeline -organizationName $organizationName -projectName $projectName -pipelineId $pipelineId -pipelineAction "destroy" -headers $headers + Write-Host "$pipelineAction pipeline triggered successfully" + + # Wait for the apply pipeline to complete + Write-Host "Waiting for the $pipelineAction pipeline to complete" + Wait-ForPipelineRunToComplete -organizationName $organizationName -projectName $projectName -pipelineId $pipelineId -pipelineRunId $pipelineRunId -headers $headers + Write-Host "$pipelineAction pipeline completed successfully" + + $success = $true +} catch { + Write-Host $_ + Write-Host "Failed to trigger the pipeline successfully, trying again..." +} +} while ($success -eq $false -and $retryCount -lt $maximumRetries) + +if ($success -eq $false) { + throw "Failed to trigger the pipeline after $maximumRetries attempts." +} diff --git a/.github/tests/scripts/destroy.ps1 b/.github/tests/scripts/destroy.ps1 new file mode 100644 index 0000000..d075a48 --- /dev/null +++ b/.github/tests/scripts/destroy.ps1 @@ -0,0 +1,41 @@ +param ( + [int]$maximumRetries = 10, + [int]$retryCount = 0, + [int]$retryDelay = 10000, + [string]$versionControlSystem +) + +$bootstrapDirectoryPath = "./bootstrap/local/alz/$versionControlSystem" +Write-Host "Bootstrap Directory Path: $bootstrapDirectoryPath" + +if(Test-Path -Path "$bootstrapDirectoryPath/override.tfvars") { + Write-Host "Bootstrap tfvars Exists" +} else { + Write-Host "Bootstrap tfvars does not exist, so there is nothing to clean up. Exiting now." + exit 0 +} + +$success = $false + +do { + $retryCount++ + try { + $myIp = Invoke-RestMethod -Uri http://ipinfo.io/json | Select-Object -ExpandProperty ip + Write-Host "Runner IP Address: $myIp" + + Write-Host "Running Terraform Destroy" + Deploy-Accelerator -inputs "./inputs.json" -bootstrapModuleOverrideFolderPath "./$($env:SOURCE_CODE_FOLDER)" -autoApprove -destroy -ErrorAction Stop + if ($LastExitCode -eq 0) { + $success = $true + } else { + throw "Failed to destroy the bootstrap environment." + } + } catch { + Write-Host "Failed to destroy the bootstrap environment." + Start-Sleep -Milliseconds $retryDelay + } +} while ($success -eq $false -and $retryCount -lt $maximumRetries) + +if ($success -eq $false) { + throw "Failed to destroy the bootstrap environment after $maximumRetries attempts." +} \ No newline at end of file diff --git a/.github/tests/scripts/github-action-run.ps1 b/.github/tests/scripts/github-action-run.ps1 new file mode 100644 index 0000000..aaa3a1a --- /dev/null +++ b/.github/tests/scripts/github-action-run.ps1 @@ -0,0 +1,140 @@ +param ( + [string]$organizationName, + [string]$repositoryName, + [string]$personalAccessToken, + [string]$workflowFileName = "cd.yaml", + [switch]$skipDestroy = $false, + [int]$maximumRetries = 10, + [int]$retryCount = 0, + [int]$retryDelay = 10000 +) + +function Invoke-Workflow { + param ( + [string]$organizationName, + [string]$repositoryName, + [string]$workflowId, + [string]$workflowAction = "", + [hashtable]$headers + ) + $workflowDispatchUrl = "https://api.github.com/repos/$organizationName/$repositoryName/actions/workflows/$workflowId/dispatches" + Write-Host "Workflow Dispatch URL: $workflowDispatchUrl" + + $workflowDispatchBody = @{} + if($workflowAction -eq "") { + $workflowDispatchBody = @{ + ref = "main" + } | ConvertTo-Json -Depth 100 + } else { + $workflowDispatchBody = @{ + ref = "main" + inputs = @{ + terraform_action = $workflowAction + } + } | ConvertTo-Json -Depth 100 + } + + $result = Invoke-RestMethod -Method POST -Uri $workflowDispatchUrl -Headers $headers -Body $workflowDispatchBody -StatusCodeVariable statusCode + if ($statusCode -ne 204) { + throw "Failed to dispatch the workflow. $result" + } +} + +function Wait-ForWorkflowRunToComplete { + param ( + [string]$organizationName, + [string]$repositoryName, + [hashtable]$headers + ) + + $workflowRunUrl = "https://api.github.com/repos/$organizationName/$repositoryName/actions/runs" + Write-Host "Workflow Run URL: $workflowRunUrl" + + $workflowRunStatus = "" + $workflowRunConclusion = "" + while($workflowRunStatus -ne "completed") { + Start-Sleep -Seconds 10 + + $workflowRun = Invoke-RestMethod -Method GET -Uri $workflowRunUrl -Headers $headers -StatusCodeVariable statusCode + if ($statusCode -lt 300) { + $workflowRunStatus = $workflowRun.workflow_runs[0].status + $workflowRunConclusion = $workflowRun.workflow_runs[0].conclusion + Write-Host "Workflow Run Status: $workflowRunStatus - Conclusion: $workflowRunConclusion" + } else { + Write-Host "Failed to find the workflow run. Status Code: $statusCode" + throw "Failed to find the workflow run." + } + } + + if($workflowRunConclusion -ne "success") { + throw "The workflow run did not complete successfully. Conclusion: $workflowRunConclusion" + } +} + +# Setup Variables +$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$personalAccessToken")) +$headers = @{ + "Authorization" = "Basic $token" + "Accept" = "application/vnd.github+json" +} + +# Run the Module in a retry loop +$success = $false + +do { +$retryCount++ +try { + # Get the workflow id + Write-Host "Getting the workflow id" + $workflowUrl = "https://api.github.com/repos/$organizationName/$repositoryName/actions/workflows/$workflowFileName" + Write-Host "Workflow URL: $workflowUrl" + $workflow = Invoke-RestMethod -Method GET -Uri $workflowUrl -Headers $headers -StatusCodeVariable statusCode + if ($statusCode -ne 200) { + throw "Failed to find the workflow." + } + $workflowId = $workflow.id + Write-Host "Workflow ID: $workflowId" + + $workflowAction = "" + + if(!($skipDestroy)) { + $workflowAction = "apply" + } + + # Trigger the apply workflow + Write-Host "Triggering the $workflowAction workflow" + Invoke-Workflow -organizationName $organizationName -repositoryName $repositoryName -workflowId $workflowId -workflowAction $workflowAction -headers $headers + Write-Host "$workflowAction workflow triggered successfully" + + # Wait for the apply workflow to complete + Write-Host "Waiting for the $workflowAction workflow to complete" + Wait-ForWorkflowRunToComplete -organizationName $organizationName -repositoryName $repositoryName -headers $headers + Write-Host "$workflowAction workflow completed successfully" + + if($skipDestroy) { + $success = $true + break + } + + $workflowAction = "destroy" + + # Trigger the destroy workflow + Write-Host "Triggering the $workflowAction workflow" + Invoke-Workflow -organizationName $organizationName -repositoryName $repositoryName -workflowId $workflowId -workflowAction $workflowAction -headers $headers + Write-Host "$workflowAction workflow triggered successfully" + + # Wait for the apply workflow to complete + Write-Host "Waiting for the $workflowAction workflow to complete" + Wait-ForWorkflowRunToComplete -organizationName $organizationName -repositoryName $repositoryName -headers $headers + Write-Host "$workflowAction workflow completed successfully" + + $success = $true +} catch { + Write-Host $_ + Write-Host "Failed to trigger the workflow successfully, trying again..." +} +} while ($success -eq $false -and $retryCount -lt $maximumRetries) + +if ($success -eq $false) { + throw "Failed to trigger the workflow after $maximumRetries attempts." +} diff --git a/.github/workflows/docs-fmt-test.yml b/.github/workflows/docs-fmt-test.yml new file mode 100644 index 0000000..99e2324 --- /dev/null +++ b/.github/workflows/docs-fmt-test.yml @@ -0,0 +1,42 @@ +--- +name: Docs & fmt test + +on: + pull_request: + types: ['opened', 'reopened', 'synchronize'] + merge_group: + workflow_dispatch: + +concurrency: + group: docsfmttest-${{ github.event.pull_request.head.repo.full_name }}/${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + docsfmttest: + name: Docs & fmt test + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup go + uses: actions/setup-go@v4 + with: + go-version: '1.20.x' + cache-dependency-path: tests/go.sum + + - name: Install tools + run: make tools + + - name: Check fmt and docs + run: | + echo "==> Running make fmt & make docs" + make fmt + make docs + echo "==> Testing for changes to tracked files" + CHANGES=$(git status -suno) + if [ "$CHANGES" ]; then + echo "Repository formatting or documentation is not correct." + echo "Run 'make fmt && make docs' locally and commit the changes to fix." + exit 1 + fi diff --git a/.github/workflows/end-to-end-test.yml b/.github/workflows/end-to-end-test.yml new file mode 100644 index 0000000..17ff79c --- /dev/null +++ b/.github/workflows/end-to-end-test.yml @@ -0,0 +1,336 @@ +--- +name: End to End Tests + +on: + pull_request: + branches: + - main + types: ['opened', 'reopened', 'synchronize', 'labeled'] + workflow_dispatch: + schedule: + - cron: '0 9 * * 1' + +permissions: + id-token: write + contents: read + +env: + SOURCE_CODE_FOLDER: source-code + ALZ_POWERSHELL_BRANCH: "bug-fixing-for-e2e-tests" + +jobs: + e2e-test: + name: "IAC: ${{ matrix.iac }}, OS: ${{ matrix.os }}, VCS: ${{ matrix.vcs }}, A: ${{ matrix.as }}, TF: ${{ matrix.tf }}, AG: ${{ matrix.ag }}" + environment: ${{ github.event_name == 'schedule' && 'CSUTFAUTO' || 'CSUTF' }} + if: "${{ github.repository == 'Azure/accelerator-bootstrap-modules' && (contains(github.event.pull_request.labels.*.name, 'PR: Safe to test 🧪') || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') }}" + strategy: + fail-fast: false + matrix: + iac: ['terraform', 'bicep'] + os: ['ubuntu-latest', 'windows-latest', 'macos-latest'] # Operating System + tf: ['latest', '1.5.0'] # Terraform Version + vcs: ['github', 'azuredevops', 'local'] # Version Control System + as: ['ManagedServiceIdentity', 'WorkloadIdentityFederation'] # Authentication Scheme + ag: ['public', 'private', 'none'] # Self Hosted Agents + exclude: + - iac: bicep + tf: 1.5.0 + - iac: bicep + vcs: local + - iac: bicep + as: ManagedServiceIdentity + - iac: bicep + ag: public + - iac: bicep + ag: private + - vcs: github + as: ManagedServiceIdentity + - vcs: local + as: ManagedServiceIdentity + - vcs: local + ag: public + - vcs: local + ag: private + - vcs: azuredevops + tf: 1.5.0 + - vcs: github + tf: 1.5.0 + - as: ManagedServiceIdentity + ag: none + - os: windows-latest + vcs: azuredevops + - os: macos-latest + vcs: azuredevops + - os: windows-latest + vcs: github + - os: macos-latest + vcs: github + + runs-on: ${{ matrix.os }} + steps: + - name: Show env + run: env | sort + + - name: Checkout repository + uses: actions/checkout@v4 + with: + path: ${{ env.SOURCE_CODE_FOLDER }} + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: ${{ matrix.tf }} + terraform_wrapper: false + if: ${{ matrix.tf != 'latest' }} + + - name: Setup ALZ Module Inputs + run: | + + # Get Inputs + $infrastructureAsCode = "${{ matrix.iac }}" + $versionControlSystem = "${{ matrix.vcs }}" + $authScheme = "${{ matrix.as }}" + $operatingSystem = "${{ matrix.os }}" + $terraformVersion = "${{ matrix.tf }}" + $selfHostedAgents = "${{ matrix.ag }}" + + $enableSelfHostedAgents = "false" + if($selfHostedAgents -eq "public" -or $selfHostedAgents -eq "private") { + $enableSelfHostedAgents = "true" + } + + $enablePrivateNetworking = "false" + if($selfHostedAgents -eq "private") { + $enablePrivateNetworking = "true" + } + + # Get Unique ID + $infrastructureAsCodeShort = $infrastructureAsCode.Substring(0, 1) + $versionControlSystemShort = $versionControlSystem.Substring(0, 1) + $authSchemeShort = $authScheme.Substring(0, 1) + $operatingSystemShort = $operatingSystem.Substring(0, 1) + $terraformVersionShort = if ($terraformVersion -eq "latest") { "l" } else { "m" } + $selfhostedAgentsShort = "n" + if($selfHostedAgents -eq "public") { + $selfhostedAgentsShort = "p" + } + if($selfHostedAgents -eq "private") { + $selfhostedAgentsShort = "r" + } + + $localDeployAzureResources = if($terraformVersion -eq "latest") { "true" } else { "false" } + + $runNumber = "${{ github.run_number }}" + + Write-Host "Infrastructure As Code: $infrastructureAsCode ($infrastructureAsCodeShort)" + Write-Host "Version Control System: $versionControlSystem ($versionControlSystemShort)" + Write-Host "Auth Scheme: $authScheme ($authSchemeShort)" + Write-Host "Operating System: $operatingSystem ($operatingSystemShort)" + Write-Host "Terraform Version: $terraformVersion ($terraformVersionShort)" + Write-Host "Self Hosted Agents: $selfHostedAgents ($selfhostedAgentsShort)" + Write-Host "Local Deploy Azure Resources: $localDeployAzureResources" + Write-Host "Run Number: $runNumber" + + $uniqueId = "$infrastructureAsCodeShort$operatingSystemShort$versionControlSystemShort$authSchemeShort$terraformVersionShort$selfhostedAgentsShort$runNumber".ToLower() + echo "UNIQUE_ID=$uniqueId" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + + Write-Host "Unique ID: $uniqueId" + + $Inputs = @{} + $Inputs["iac"] = $infrastructureAsCode + $Inputs["bootstrap"] = "alz_$versionControlSystem" + $Inputs["starter"] = ".test" + $Inputs["bootstrap_location"] = "uksouth" + $Inputs["bootstrap_subscription_id"] = "" + $Inputs["service_name"] = "alz" + $Inputs["environment_name"] = $uniqueId + $Inputs["postfix_number"] = "1" + + $Inputs["use_private_networking"] = $enablePrivateNetworking + $Inputs["allow_storage_access_from_my_ip"] = "true" + + if($versionControlSystem -eq "github") { + $Inputs["github_personal_access_token"] = "${{ secrets.VCS_TOKEN_GITHUB }}" + $Inputs["github_runners_personal_access_token"] = "${{ secrets.VCS_TOKEN_GITHUB }}" + $Inputs["github_organization_name"] = "${{ vars.VCS_ORGANIZATION }}" + $Inputs["use_separate_repository_for_workflow_templates"] = "true" + $Inputs["use_self_hosted_runners"] = $enableSelfHostedAgents + } + + if($versionControlSystem -eq "azuredevops") { + $Inputs["azure_devops_personal_access_token"] = "${{ secrets.VCS_TOKEN_AZURE_DEVOPS }}" + $Inputs["azure_devops_organization_name"] = "${{ vars.VCS_ORGANIZATION }}" + $Inputs["use_separate_repository_for_pipeline_templates"] = "true" + $Inputs["azure_devops_use_organisation_legacy_url"] = "false" + $Inputs["azure_devops_create_project"] = "true" + $Inputs["azure_devops_project_name"] = "alz-test-$uniqueId" + $Inputs["azure_devops_authentication_scheme"] = $authScheme + $Inputs["use_self_hosted_agents"] = $enableSelfHostedAgents + } + + if($versionControlSystem -eq "local") { + $Inputs["target_directory"] = "" + $Inputs["create_bootstrap_resources_in_azure"] = $localDeployAzureResources + } + + $Inputs["apply_approvers"] = "" # if ($versionControlSystem -eq "github") { "${{ vars.VCS_APPROVER_GITHUB }}" } else { "${{ vars.VCS_APPROVER_AZUREDEVOPS }}" } + $Inputs["root_parent_management_group_id"] = "" + $Inputs["root_parent_management_group_display_name"] = "Tenant Root Group" + + $Inputs["subscription_id_connectivity"] = "${{ vars.ARM_SUBSCRIPTION_ID }}" + $Inputs["subscription_id_identity"] = "${{ vars.ARM_SUBSCRIPTION_ID }}" + $Inputs["subscription_id_management"] = "${{ vars.ARM_SUBSCRIPTION_ID }}" + $Inputs["parent_management_group_display_name"] = "Tenant Root Group" + $Inputs["child_management_group_display_name"] = "E2E Test" + $Inputs["resource_group_location"] = "uksouth" + + if($infrastructureAsCode -eq "bicep") { + $Inputs["Prefix"] = "alz" + $Inputs["Location"] = "uksouth" + $Inputs["Environment"] = "live" + $Inputs["IdentitySubscriptionId"] = "${{ vars.ARM_SUBSCRIPTION_ID }}" + $Inputs["ConnectivitySubscriptionId"] = "${{ vars.ARM_SUBSCRIPTION_ID }}" + $Inputs["ManagementSubscriptionId"] = "${{ vars.ARM_SUBSCRIPTION_ID }}" + $Inputs["SecurityContact"] = "test@test.com" + } + + $json = $Inputs | ConvertTo-Json -Depth 100 | Out-File -FilePath inputs.json -Encoding utf8 -Force + + shell: pwsh + + - name: Run ALZ PowerShell + run: | + + $myIp = Invoke-RestMethod -Uri http://ipinfo.io/json | Select -ExpandProperty ip + Write-Host "Runner IP Address: $myIp" + + # Get Inputs + $versionControlSystem = "${{ matrix.vcs }}" + + # Install the Module + Write-Host "Installing the Accelerator PowerShell Module" + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/Install-AcceleratorModule.ps1 -ModuleBranch "${{ env.ALZ_POWERSHELL_BRANCH }}" + Write-Host "Installed Accelerator Module" + + # Run the Module in a retry loop + $retryCount = 0 + $maximumRetries = 10 + $retryDelay = 10000 + $success = $false + + do { + $retryCount++ + try { + Write-Host "Running the ALZ Module" + Deploy-Accelerator -inputs "./inputs.json" -bootstrapModuleOverrideFolderPath "./${{ env.SOURCE_CODE_FOLDER }}" -autoApprove -ErrorAction Stop -Verbose + if ($LastExitCode -eq 0) { + $success = $true + } else { + throw "Failed to apply the bootstrap environment." + } + } catch { + Write-Host "Failed to apply the bootstrap environment. Destroy and retry..." + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/destroy.ps1 -versionControlSystem $versionControlSystem + } + } while ($success -eq $false -and $retryCount -lt $maximumRetries) + + if ($success -eq $false) { + Write-Host "File Structure after Bootstrap..." + $files = Get-ChildItem -Recurse -Force + $files | ForEach-Object { Write-Host (Resolve-Path $_ -Relative)} + throw "Failed to apply the bootstrap environment after $maximumRetries attempts." + } + + shell: pwsh + env: + ARM_TENANT_ID: ${{ vars.ARM_TENANT_ID }} + ARM_SUBSCRIPTION_ID: ${{ vars.ARM_SUBSCRIPTION_ID }} + ARM_CLIENT_ID: ${{ vars.ARM_CLIENT_ID }} + ARM_USE_OIDC: true + + - name: Run Pipelines or Actions + run: | + $infrastructureAsCode = "${{ matrix.iac }}" + + if($infrastructureAsCode -eq "bicep") { + Write-Host "Skipping Pipelines or Actions for Bicep" + exit 0 + } + + # Get Inputs + $versionControlSystem = "${{ matrix.vcs }}" + $versionControlSystemOrganisationName = "${{ vars.VCS_ORGANIZATION }}" + $uniqueId = $ENV:UNIQUE_ID + + if($versionControlSystem -eq "github") { + $repositoryName = "alz-$uniqueId" + + Write-Host "Running GitHub Actions Test for CI" + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/github-action-run.ps1 ` + -organizationName $versionControlSystemOrganisationName ` + -repositoryName $repositoryName ` + -workflowFileName "ci.yaml" ` + -skipDestroy ` + -personalAccessToken "${{ secrets.VCS_TOKEN_GITHUB }}" + + Write-Host "Running GitHub Actions Test for CD" + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/github-action-run.ps1 ` + -organizationName $versionControlSystemOrganisationName ` + -repositoryName $repositoryName ` + -workflowFileName "cd.yaml" ` + -personalAccessToken "${{ secrets.VCS_TOKEN_GITHUB }}" + } + + if($versionControlSystem -eq "azuredevops") { + $projectName = "alz-test-$uniqueId" + + Write-Host "Running Azure DevOps Pipelines Test for CI" + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/azuredevops-pipeline-run.ps1 ` + -organizationName $versionControlSystemOrganisationName ` + -projectName $projectName ` + -pipelineNamePart "Continuous Integration" ` + -skipDestroy ` + -personalAccessToken "${{ secrets.VCS_TOKEN_AZURE_DEVOPS }}" + + Write-Host "Running Azure DevOps Pipelines Test for CD" + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/azuredevops-pipeline-run.ps1 ` + -organizationName $versionControlSystemOrganisationName ` + -projectName $projectName ` + -pipelineNamePart "Continuous Delivery" ` + -personalAccessToken "${{ secrets.VCS_TOKEN_AZURE_DEVOPS }}" + } + + shell: pwsh + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: "latest" + terraform_wrapper: false + if: always() + + - name: Run Terraform Destroy to Clean Up + if: always() + run: | + + $myIp = Invoke-RestMethod -Uri http://ipinfo.io/json | Select -ExpandProperty ip + Write-Host "Runner IP Address: $myIp" + + # Get Inputs + $versionControlSystem = "${{ matrix.vcs }}" + + Write-Host "Installing the Accelerator PowerShell Module" + #Install-Module -Name ALZ -Force -Scope CurrentUser -Repository PSGallery -AllowPrerelease + #$module = Get-InstalledModule ALZ + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/Install-AcceleratorModule.ps1 -ModuleBranch "${{ env.ALZ_POWERSHELL_BRANCH }}" + Write-Host "Installed Accelerator Module: $($module.Name) $($module.Version)" + + # Run destroy + ./${{ env.SOURCE_CODE_FOLDER }}/.github/tests/scripts/destroy.ps1 -versionControlSystem $versionControlSystem + + shell: pwsh + env: + ARM_TENANT_ID: ${{ vars.ARM_TENANT_ID }} + ARM_SUBSCRIPTION_ID: ${{ vars.ARM_SUBSCRIPTION_ID }} + ARM_CLIENT_ID: ${{ vars.ARM_CLIENT_ID }} + ARM_USE_OIDC: true diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml new file mode 100644 index 0000000..97862d7 --- /dev/null +++ b/.github/workflows/super-linter.yml @@ -0,0 +1,49 @@ +--- +name: Linting +on: + pull_request: + types: ['opened', 'synchronize'] + merge_group: + workflow_dispatch: + +concurrency: + group: linting-${{ github.event.pull_request.head.repo.full_name }}/${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + superlinter: + name: super linter + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: latest + terraform_wrapper: false + - name: Run github/super-linter/slim + uses: github/super-linter/slim@v5 + env: + # Lint all code + VALIDATE_ALL_CODEBASE: true + FILTER_REGEX_EXCLUDE: '.*tests/vendor/.*' + # Need to define main branch as default + # is set to master in super-linter + DEFAULT_BRANCH: main + # Enable setting the status of each individual linter + # run in the Checks section of a pull request + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # The following linter types will be enabled: + VALIDATE_BASH: true + VALIDATE_BASH_EXEC: true + VALIDATE_GITHUB_ACTIONS: true + VALIDATE_JSON: true + VALIDATE_MARKDOWN: true + # VALIDATE_TERRAFORM_TERRASCAN: true # disabled for now as does not support TF 1.3 optional(type, default) + VALIDATE_TERRAFORM_TFLINT: true + VALIDATE_YAML: true + # VALIDATE_GO: true # Disabled because it down not work :( + # Additional settings: + # If a shell script is not executable, the bash-exec + # linter will report an error when set to true + ERROR_ON_MISSING_EXEC_BIT: true diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..09aecee --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +default: + @echo "==> Type make to run tasks" + @echo + @echo "Thing is one of:" + @echo "docs fmt fmtcheck tfclean tools" + +docs: + @echo "==> Updating documentation..." + find . | egrep "\.md" | grep -v README.md | sort | while read f; do terrafmt fmt $$f; done + +fmt: + @echo "==> Fixing Terraform code with terraform fmt..." + terraform fmt -recursive + @echo "==> Fixing embedded Terraform with terrafmt..." + find . | egrep "\.md|\.tf" | grep -v README.md | sort | while read f; do terrafmt fmt $$f; done + +fmtcheck: + @echo "==> Checking source code with gofmt..." + @sh "$(CURDIR)/scripts/gofmtcheck.sh" + @echo "==> Checking source code with terraform fmt..." + terraform fmt -check -recursive + +tfclean: + @echo "==> Cleaning terraform files..." + find . -type d -name '.terraform' | xargs rm -vrf + find . -type f -name 'tfplan' | xargs rm -vf + find . -type f -name 'terraform.tfstate*' | xargs rm -vf + find . -type f -name '.terraform.lock.hcl' | xargs rm -vf + +tools: + go install github.com/katbyte/terrafmt@latest + +# Makefile targets are files, but we aren't using it like this, +# so have to declare PHONY targets +.PHONY: docs fmt fmtcheck tfclean tools diff --git a/README.md b/README.md index 825d547..ceb66a9 100644 --- a/README.md +++ b/README.md @@ -432,7 +432,7 @@ Example code: "default": "", # For source `input`, a default empty value can be specified. "required": false, "maps_to": [ "bootstrap", "starter" ], - "display_map_filter" : "starter", # This setting is used to filter out this input if it is not present in the specified module. For example, if the `configuration_file_path` is not present in the `starter` module, then it will not be displayed in the UI and no attempt will be made to map it to the `starter` module. The default value will be set for the `bootstrap` module if it is present there. + "display_map_filter" : "starter", # Used to filter out this input if it is not present in the specified module. For example, if the `configuration_file_path` is not present in the `starter` module, then it will not be displayed in the UI and no attempt will be made to map it to the `starter` module. The default value will be set for the `bootstrap` module if it is present there. "validation": "configuration_file_path", "display_order": 6, "description": "The identifier of the Connectivity Subscription." @@ -445,7 +445,7 @@ Example code: This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. +the rights to use your contribution. For details, visit [https://cla.opensource.microsoft.com](https://cla.opensource.microsoft.com). When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions @@ -457,8 +457,8 @@ contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additio ## Trademarks -This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft -trademarks or logos is subject to and must follow +This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft +trademarks or logos is subject to and must follow [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. diff --git a/SECURITY.md b/SECURITY.md index b3c89ef..167c4b4 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -14,17 +14,17 @@ Instead, please report them to the Microsoft Security Response Center (MSRC) at If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. diff --git a/SUPPORT.md b/SUPPORT.md index 291d4d4..f9bb703 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,25 +1,11 @@ -# TODO: The maintainer of this repo has not yet edited this file - -**REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? - -- **No CSS support:** Fill out this template with information about how to file issues and get help. -- **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. -- **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. - -*Then remove this first heading from this SUPPORT.MD file before publishing your repo.* - -# Support - -## How to file issues and get help - -This project uses GitHub Issues to track bugs and feature requests. Please search the existing -issues before filing new issues to avoid duplicates. For new issues, file your bug or -feature request as a new Issue. - -For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE -FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER -CHANNEL. WHERE WILL YOU HELP PEOPLE?**. - -## Microsoft Support Policy - -Support for this **PROJECT or PRODUCT** is limited to the resources listed above. +# Support + +## How to file issues and get help + +This project uses GitHub Issues to track bugs and feature requests. Please search the existing +issues before filing new issues to avoid duplicates. For new issues, file your bug or +feature request as a new Issue. + +## Microsoft Support Polic + +Support for this PRODUCT is limited to the resources listed above. diff --git a/alz/azuredevops/locals.tf b/alz/azuredevops/locals.tf index bce5d5d..b7ca387 100644 --- a/alz/azuredevops/locals.tf +++ b/alz/azuredevops/locals.tf @@ -3,6 +3,10 @@ locals { resource_names = module.resource_names.resource_names } +locals { + root_parent_management_group_id = var.root_parent_management_group_id == "" ? data.azurerm_client_config.current.tenant_id : var.root_parent_management_group_id +} + locals { plan_key = "plan" apply_key = "apply" diff --git a/alz/azuredevops/main.tf b/alz/azuredevops/main.tf index c0cc470..1921dd0 100644 --- a/alz/azuredevops/main.tf +++ b/alz/azuredevops/main.tf @@ -38,7 +38,7 @@ module "azure" { agent_name_environment_variable = var.agent_name_environment_variable agent_token_environment_variable = var.agent_token_environment_variable target_subscriptions = local.target_subscriptions - root_parent_management_group_id = var.root_parent_management_group_id + root_parent_management_group_id = local.root_parent_management_group_id virtual_network_name = local.resource_names.virtual_network virtual_network_subnet_name_container_instances = local.resource_names.subnet_container_instances virtual_network_subnet_name_storage = local.resource_names.subnet_storage diff --git a/alz/azuredevops/outputs.tf b/alz/azuredevops/outputs.tf new file mode 100644 index 0000000..be65974 --- /dev/null +++ b/alz/azuredevops/outputs.tf @@ -0,0 +1,6 @@ +output "details" { + description = "The details of the settings used" + value = { + iac_type = var.iac_type + } +} diff --git a/alz/azuredevops/terraform.tfvars b/alz/azuredevops/terraform.tfvars index bd4091d..e89625f 100644 --- a/alz/azuredevops/terraform.tfvars +++ b/alz/azuredevops/terraform.tfvars @@ -39,9 +39,6 @@ resource_names = { } # Version Control System Variables -module_folder_path = "../../templates" -pipeline_folder_path = "../../templates/ci_cd" - pipeline_files = { ci = { pipeline_name = "01 Azure Landing Zone Continuous Integration" diff --git a/alz/azuredevops/variables.hidden.tf b/alz/azuredevops/variables.hidden.tf index fe11acc..ddcac24 100644 --- a/alz/azuredevops/variables.hidden.tf +++ b/alz/azuredevops/variables.hidden.tf @@ -42,13 +42,13 @@ variable "built_in_configurartion_file_name" { variable "module_folder_path_relative" { description = "Whether the module folder path is relative to the bootstrap module" type = bool - default = true + default = false } variable "pipeline_folder_path_relative" { description = "Whether the pipeline folder path is relative to the bootstrap module" type = bool - default = true + default = false } variable "pipeline_files" { diff --git a/alz/github/locals.tf b/alz/github/locals.tf index d5c1bf8..bb64707 100644 --- a/alz/github/locals.tf +++ b/alz/github/locals.tf @@ -3,6 +3,10 @@ locals { resource_names = module.resource_names.resource_names } +locals { + root_parent_management_group_id = var.root_parent_management_group_id == "" ? data.azurerm_client_config.current.tenant_id : var.root_parent_management_group_id +} + locals { plan_key = "plan" apply_key = "apply" diff --git a/alz/github/main.tf b/alz/github/main.tf index 41c637d..e794d7d 100644 --- a/alz/github/main.tf +++ b/alz/github/main.tf @@ -30,7 +30,7 @@ module "azure" { storage_container_name = local.resource_names.storage_container azure_location = var.bootstrap_location target_subscriptions = local.target_subscriptions - root_parent_management_group_id = var.root_parent_management_group_id + root_parent_management_group_id = local.root_parent_management_group_id agent_container_instances = local.runner_container_instances agent_container_instance_image = var.runner_container_image agent_organization_url = "${module.github.organization_url}/${module.github.repository_names.module}" diff --git a/alz/github/outputs.tf b/alz/github/outputs.tf new file mode 100644 index 0000000..be65974 --- /dev/null +++ b/alz/github/outputs.tf @@ -0,0 +1,6 @@ +output "details" { + description = "The details of the settings used" + value = { + iac_type = var.iac_type + } +} diff --git a/alz/github/terraform.tfvars b/alz/github/terraform.tfvars index 25c847f..7264033 100644 --- a/alz/github/terraform.tfvars +++ b/alz/github/terraform.tfvars @@ -29,8 +29,6 @@ resource_names = { } # Version Control System Variables -module_folder_path = "../../templates" -pipeline_folder_path = "../../templates/ci_cd" pipeline_files = { ci = { file_path = "github/ci.yaml" diff --git a/alz/local/data.tf b/alz/local/data.tf new file mode 100644 index 0000000..cee07df --- /dev/null +++ b/alz/local/data.tf @@ -0,0 +1 @@ +data "azurerm_client_config" "current" {} diff --git a/alz/local/locals.tf b/alz/local/locals.tf index 1e0b328..9ba0ee5 100644 --- a/alz/local/locals.tf +++ b/alz/local/locals.tf @@ -3,6 +3,11 @@ locals { resource_names = module.resource_names.resource_names } +locals { + root_parent_management_group_id = var.root_parent_management_group_id == "" ? data.azurerm_client_config.current.tenant_id : var.root_parent_management_group_id +} + + locals { plan_key = "plan" apply_key = "apply" diff --git a/alz/local/main.tf b/alz/local/main.tf index b77307f..b5de2c0 100644 --- a/alz/local/main.tf +++ b/alz/local/main.tf @@ -16,17 +16,17 @@ module "files" { } module "azure" { - source = "../../modules/azure" - count = var.create_bootstrap_resources_in_azure ? 1 : 0 - user_assigned_managed_identities = local.managed_identities - federated_credentials = local.federated_credentials - resource_group_identity_name = local.resource_names.resource_group_identity - resource_group_state_name = local.resource_names.resource_group_state - storage_account_name = local.resource_names.storage_account - storage_container_name = local.resource_names.storage_container - azure_location = var.bootstrap_location - target_subscriptions = local.target_subscriptions - root_parent_management_group_id = var.root_parent_management_group_id + source = "../../modules/azure" + count = var.create_bootstrap_resources_in_azure ? 1 : 0 + user_assigned_managed_identities = local.managed_identities + federated_credentials = local.federated_credentials + resource_group_identity_name = local.resource_names.resource_group_identity + resource_group_state_name = local.resource_names.resource_group_state + storage_account_name = local.resource_names.storage_account + storage_container_name = local.resource_names.storage_container + azure_location = var.bootstrap_location + target_subscriptions = local.target_subscriptions + root_parent_management_group_id = local.root_parent_management_group_id } resource "local_file" "alz" { diff --git a/alz/local/outputs.tf b/alz/local/outputs.tf index 36990c0..466ce64 100644 --- a/alz/local/outputs.tf +++ b/alz/local/outputs.tf @@ -2,3 +2,10 @@ output "module_output_directory_path" { description = "The path to the directory where the module files have been created." value = abspath(local.target_directory) } + +output "details" { + description = "The details of the settings used" + value = { + iac_type = var.iac_type + } +} diff --git a/alz/local/terraform.tfvars b/alz/local/terraform.tfvars index 366aa80..6596ad0 100644 --- a/alz/local/terraform.tfvars +++ b/alz/local/terraform.tfvars @@ -8,6 +8,3 @@ resource_names = { storage_account = "sto{{service_name}}{{environment_name}}{{azure_location_short}}{{postfix_number}}{{random_string}}" storage_container = "{{environment_name}}-tfstate" } - -# Version Control System Variables -module_folder_path = "../../templates" diff --git a/alz/local/variables.hidden.tf b/alz/local/variables.hidden.tf index 753bf53..ce76cc8 100644 --- a/alz/local/variables.hidden.tf +++ b/alz/local/variables.hidden.tf @@ -1,16 +1,9 @@ - variable "additional_files" { description = "Additional files to upload to the repository. This must be specified as a comma-separated list of absolute file paths (e.g. c:\\config\\config.yaml or /home/user/config/config.yaml)" type = list(string) default = [] } -variable "configuration_file_path" { - description = "The name of the configuration file to be generated" - type = string - default = "" -} - variable "built_in_configurartion_file_name" { description = "The name of the built-in configuration file" type = string @@ -20,7 +13,7 @@ variable "built_in_configurartion_file_name" { variable "module_folder_path_relative" { description = "Whether the module folder path is relative to the bootstrap module" type = bool - default = true + default = false } variable "resource_names" { diff --git a/alz/local/variables.input.tf b/alz/local/variables.input.tf index f356a5a..3cfddb3 100644 --- a/alz/local/variables.input.tf +++ b/alz/local/variables.input.tf @@ -38,4 +38,4 @@ variable "postfix_number" { description = "Used to build up the default resource names (e.g. rg-alz-mgmt-uksouth-)|8|number" type = number default = 1 -} \ No newline at end of file +}