ACI DevOps Agent Terraform Module
* add terraform module configuration * add documentation * add validation tests and end-to-end tests * add Azure pipeline
This commit is contained in:
Родитель
cd600bb923
Коммит
d6360df82b
|
@ -0,0 +1,47 @@
|
|||
# Local .terraform directories
|
||||
**/.terraform/*
|
||||
terraform.tfstate.d/
|
||||
logs/
|
||||
|
||||
# Variable files
|
||||
terraform.tfvars
|
||||
|
||||
# .tfstate files
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
|
||||
# Crash log files
|
||||
crash.log
|
||||
|
||||
# Go vendor directory
|
||||
vendor/
|
||||
|
||||
# Files generated by terratest
|
||||
.test-data/
|
||||
|
||||
# Terraform log file
|
||||
terraform.log
|
||||
|
||||
# Ignore override files as they are usually used to override resources locally and so
|
||||
# are not checked in
|
||||
override.tf
|
||||
override.tf.json
|
||||
*_override.tf
|
||||
*_override.tf.json
|
||||
|
||||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
|
||||
# example: *tfplan*
|
||||
*.plan
|
||||
|
||||
# Golang
|
||||
go.sum
|
||||
.vscode/
|
||||
|
||||
# IDE configs
|
||||
.idea
|
||||
|
||||
# Ruby download package lock file.
|
||||
Gemfile.lock
|
||||
|
||||
# Mac folder attribute file
|
||||
.DS_Store
|
|
@ -0,0 +1,36 @@
|
|||
# Pull the base image with given version.
|
||||
ARG BUILD_TERRAFORM_VERSION="0.12.20"
|
||||
FROM mcr.microsoft.com/terraform-test:${BUILD_TERRAFORM_VERSION}
|
||||
|
||||
ARG MODULE_NAME="terraform-azure-devops-eagent-aci"
|
||||
|
||||
# Declare default build configurations for terraform.
|
||||
ARG BUILD_ARM_SUBSCRIPTION_ID=""
|
||||
ARG BUILD_ARM_CLIENT_ID=""
|
||||
ARG BUILD_ARM_CLIENT_SECRET=""
|
||||
ARG BUILD_ARM_TENANT_ID=""
|
||||
ARG BUILD_ARM_TEST_LOCATION="WestEurope"
|
||||
ARG BUILD_ARM_TEST_LOCATION_ALT="WestUS"
|
||||
|
||||
# Set environment variables for terraform runtime.
|
||||
ENV ARM_SUBSCRIPTION_ID=${BUILD_ARM_SUBSCRIPTION_ID}
|
||||
ENV ARM_CLIENT_ID=${BUILD_ARM_CLIENT_ID}
|
||||
ENV ARM_CLIENT_SECRET=${BUILD_ARM_CLIENT_SECRET}
|
||||
ENV ARM_TENANT_ID=${BUILD_ARM_TENANT_ID}
|
||||
ENV ARM_TEST_LOCATION=${BUILD_ARM_TEST_LOCATION}
|
||||
ENV ARM_TEST_LOCATION_ALT=${BUILD_ARM_TEST_LOCATION_ALT}
|
||||
|
||||
# Set work directory.
|
||||
RUN mkdir /go
|
||||
RUN mkdir /go/bin
|
||||
RUN mkdir /go/src
|
||||
RUN mkdir /go/src/${MODULE_NAME}
|
||||
COPY . /go/src/${MODULE_NAME}
|
||||
WORKDIR /go/src/${MODULE_NAME}
|
||||
|
||||
# Install dep.
|
||||
ENV GOPATH /go
|
||||
ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH
|
||||
RUN /bin/bash -c "curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh"
|
||||
|
||||
RUN ["bundle", "install", "--gemfile", "./Gemfile"]
|
|
@ -0,0 +1,9 @@
|
|||
source 'https://rubygems.org/' do
|
||||
|
||||
group :test do
|
||||
git 'https://github.com/Azure/terramodtest.git' do
|
||||
gem 'terramodtest', tag: '0.5.0'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
292
README.md
292
README.md
|
@ -1,9 +1,297 @@
|
|||
# terraform-azurerm-aci-devops-agent
|
||||
|
||||
# Contributing
|
||||
This repository contains a Terraform module that helps you to deploy [Azure DevOps self-hosted agents](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/agents?view=azure-devops&tabs=browser#install) running on Azure Container Instance.
|
||||
|
||||
You can choose to deploy Linux or Windows agents, provide custom Docker images for the agents to include the tools you really need. It also give you the option to deploy the agents into a private virtual network, if the agents needs to access internal resources.
|
||||
|
||||
## How-to use this module to deploy Azure DevOps agents
|
||||
|
||||
### Build the Docker images
|
||||
|
||||
This module requires that you build your own Linux and/or Windows Docker images, to run the Azure DevOps agents. The [docker](docker/README.md) contains Dockerfile and instructions for both.
|
||||
|
||||
### Create an Azure DevOps agent pool and personal access token
|
||||
|
||||
Before running this module, you need to [create an agent pool in your Azure DevOps organization](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/pools-queues?view=azure-devops&tabs=yaml%2Cbrowser#creating-agent-pools) and a [personal access token](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-linux?view=azure-devops#permissions) that it authorized to manage this agent pool.
|
||||
|
||||
This module has 3 variables related to Azure DevOps:
|
||||
|
||||
- `azure_devops_org_name`: the name of your Azure DevOps organization (if you are connecting to `https://dev.azure.com/helloworld`, then `helloworld` is your organization name)
|
||||
- `azure_devops_personal_access_token`: the personal access token that you have generated
|
||||
- `agent_pool_name`: both in the `linux_agents_configuration` and `windows_agents_configuration`, it is the name of the agent pool that you have created in which the Linux or Windows agents must be deployed
|
||||
|
||||
### Terraform ACI DevOps Agents usage
|
||||
|
||||
#### Create or use an existing a resource group
|
||||
|
||||
This module offers to create a new resource group to deploy the Azure Container instances into it, or import an existing one. This behavior is controlled using the `create_resource_group` flag:
|
||||
|
||||
- if `create_resource_group` is set to true, the module will create a resource group named `resource_group_name` in the `location` region
|
||||
- if `create_resource_group` is set to false, the module will import a resource group data source with the name `resource_group_name`
|
||||
|
||||
#### Terraform ACI DevOps Agents - Deploy Linux Agents
|
||||
|
||||
The configuration below can be used to deploy Linux DevOps agents using Azure Container Instances.
|
||||
|
||||
```hcl
|
||||
module "aci-devops-agent" {
|
||||
source = "Azure/aci-devops-agent/azurerm"
|
||||
resource_group_name = "rg-linux-devops-agents"
|
||||
location = "westeurope"
|
||||
enable_vnet_integration = false
|
||||
create_resource_group = true
|
||||
|
||||
linux_agents_configuration = {
|
||||
agent_name_prefix = "linux-agent"
|
||||
agent_pool_name = "DEVOPS_POOL_NAME"
|
||||
count = 2,
|
||||
docker_image = "jcorioland/aci-devops-agent"
|
||||
docker_tag = "0.2-linux"
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
azure_devops_org_name = "DEVOPS_ORG_NAME"
|
||||
azure_devops_personal_access_token = "DEVOPS_PERSONAL_ACCESS_TOKEN"
|
||||
}
|
||||
```
|
||||
|
||||
Then, you can just Terraform it:
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform plan -out aci-linux-devops-agents.plan
|
||||
terraform apply "aci-linux-devops-agents.plan"
|
||||
```
|
||||
|
||||
You can destroy everything using `terraform destroy`:
|
||||
|
||||
```bash
|
||||
terraform destroy
|
||||
```
|
||||
|
||||
#### Terraform ACI DevOps Agents - Deploy Linux agents in an existing virtual network
|
||||
|
||||
The configuration below can be used to deploy Azure DevOps agents in Linux containers, in an existing virtual network.
|
||||
|
||||
```hcl
|
||||
resource "azurerm_resource_group" "vnet-rg" {
|
||||
name = "rg-aci-devops-network"
|
||||
location = "westeurope"
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_network" "vnet" {
|
||||
name = "vnet-aci-devops"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
location = azurerm_resource_group.vnet-rg.location
|
||||
resource_group_name = azurerm_resource_group.vnet-rg.name
|
||||
}
|
||||
|
||||
resource "azurerm_subnet" "aci-subnet" {
|
||||
name = "aci-subnet"
|
||||
resource_group_name = azurerm_resource_group.vnet-rg.name
|
||||
virtual_network_name = azurerm_virtual_network.vnet.name
|
||||
address_prefixes = ["10.0.1.0/24"]
|
||||
|
||||
delegation {
|
||||
name = "acidelegation"
|
||||
|
||||
service_delegation {
|
||||
name = "Microsoft.ContainerInstance/containerGroups"
|
||||
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "aci-devops-agent" {
|
||||
source = "Azure/aci-devops-agent/azurerm"
|
||||
resource_group_name = "rg-linux-devops-agents"
|
||||
location = "westeurope"
|
||||
enable_vnet_integration = true
|
||||
create_resource_group = true
|
||||
vnet_resource_group_name = azurerm_resource_group.vnet-rg.name
|
||||
vnet_name = azurerm_virtual_network.vnet.name
|
||||
subnet_name = azurerm_subnet.aci-subnet.name
|
||||
|
||||
linux_agents_configuration = {
|
||||
agent_name_prefix = "linux-agent"
|
||||
agent_pool_name = "DEVOPS_POOL_NAME"
|
||||
count = 2,
|
||||
docker_image = "jcorioland/aci-devops-agent"
|
||||
docker_tag = "0.2-linux"
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
|
||||
azure_devops_org_name = "DEVOPS_ORG_NAME"
|
||||
azure_devops_personal_access_token = "DEVOPS_PERSONAL_ACCESS_TOKEN"
|
||||
}
|
||||
```
|
||||
|
||||
Then, you can just Terraform it:
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform plan -out aci-linux-devops-agents.plan
|
||||
terraform apply "aci-linux-devops-agents.plan"
|
||||
```
|
||||
|
||||
You can destroy everything using `terraform destroy`:
|
||||
|
||||
```bash
|
||||
terraform destroy
|
||||
```
|
||||
|
||||
#### Terraform ACI DevOps Agents - Deploy both Linux and Windows agents
|
||||
|
||||
The configuration below can be used to deploy Azure DevOps Linux and Windows agents in containers on ACI.
|
||||
|
||||
```hcl
|
||||
module "aci-devops-agent" {
|
||||
source = "Azure/aci-devops-agent/azurerm"
|
||||
resource_group_name = "rg-aci-devops-agents-we"
|
||||
location = "westeurope"
|
||||
enable_vnet_integration = false
|
||||
create_resource_group = true
|
||||
|
||||
linux_agents_configuration = {
|
||||
agent_name_prefix = "linux-agent"
|
||||
agent_pool_name = "DEVOPS_POOL_NAME"
|
||||
count = 2,
|
||||
docker_image = "jcorioland/aci-devops-agent"
|
||||
docker_tag = "0.2-linux"
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
|
||||
windows_agents_configuration = {
|
||||
agent_name_prefix = "windows-agent"
|
||||
agent_pool_name = "DEVOPS_POOL_NAME"
|
||||
count = 2,
|
||||
docker_image = "jcorioland/aci-devops-agent"
|
||||
docker_tag = "0.2-win"
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
|
||||
azure_devops_org_name = "DEVOPS_ORG_NAME"
|
||||
azure_devops_personal_access_token = "DEVOPS_PERSONAL_ACCESS_TOKEN"
|
||||
}
|
||||
```
|
||||
|
||||
Then, you can just Terraform it:
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform plan -out aci-devops-agents.plan
|
||||
terraform apply "aci-devops-agents.plan"
|
||||
```
|
||||
|
||||
You can destroy everything using `terraform destroy`:
|
||||
|
||||
```bash
|
||||
terraform destroy
|
||||
```
|
||||
|
||||
## Test
|
||||
|
||||
### Configurations
|
||||
|
||||
- [Configure Terraform for Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/terraform-install-configure)
|
||||
|
||||
We provide 2 ways to build, run, and test the module on a local development machine. [Native (Mac/Linux)](#native-maclinux) or [Docker](#docker).
|
||||
|
||||
### Native (Mac/Linux)
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
- [Ruby **(~> 2.3)**](https://www.ruby-lang.org/en/downloads/)
|
||||
- [Bundler **(~> 1.15)**](https://bundler.io/)
|
||||
- [Terraform **(~> 0.11.7)**](https://www.terraform.io/downloads.html)
|
||||
- [Golang **(~> 1.12.3)**](https://golang.org/dl/)
|
||||
|
||||
#### Environment setup
|
||||
|
||||
We provide simple script to quickly set up module development environment:
|
||||
|
||||
```sh
|
||||
$ curl -sSL https://raw.githubusercontent.com/Azure/terramodtest/master/tool/env_setup.sh | sudo bash
|
||||
```
|
||||
|
||||
#### Run test
|
||||
|
||||
Then simply run it in local shell:
|
||||
|
||||
```sh
|
||||
$ bundle install
|
||||
$ rake build
|
||||
$ rake full
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
We provide a Dockerfile to build a new image based `FROM` the `microsoft/terraform-test` Docker hub image which adds additional tools / packages specific for this module (see Custom Image section). Alternatively use only the `microsoft/terraform-test` Docker hub image [by using these instructions](https://github.com/Azure/terraform-test).
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
- [Docker](https://www.docker.com/community-edition#/download)
|
||||
|
||||
#### Custom Image
|
||||
|
||||
This builds the custom image:
|
||||
|
||||
```sh
|
||||
$ docker build --build-arg BUILD_ARM_SUBSCRIPTION_ID=$ARM_SUBSCRIPTION_ID --build-arg BUILD_ARM_CLIENT_ID=$ARM_CLIENT_ID --build-arg BUILD_ARM_CLIENT_SECRET=$ARM_CLIENT_SECRET --build-arg BUILD_ARM_TENANT_ID=$ARM_TENANT_ID -t azure-devops-agent-aci-test .
|
||||
```
|
||||
|
||||
This runs the build and unit tests:
|
||||
|
||||
```sh
|
||||
$ docker run --rm \
|
||||
-e TF_VAR_azure_devops_org_name=$AZDO_ORG_NAME \
|
||||
-e TF_VAR_azure_devops_personal_access_token=$AZDO_PAT \
|
||||
-e TF_VAR_azure_devops_pool_name=$AZDO_POOL_NAME \
|
||||
azure-devops-agent-aci-test /bin/bash -c "bundle install && rake build"
|
||||
```
|
||||
|
||||
This runs the end to end tests:
|
||||
|
||||
```sh
|
||||
$ docker run --rm \
|
||||
-e TF_VAR_azure_devops_org_name=$AZDO_ORG_NAME \
|
||||
-e TF_VAR_azure_devops_personal_access_token=$AZDO_PAT \
|
||||
-e TF_VAR_azure_devops_pool_name=$AZDO_POOL_NAME \
|
||||
azure-devops-agent-aci-test /bin/bash -c "bundle install && rake e2e"
|
||||
```
|
||||
|
||||
This runs the full tests:
|
||||
|
||||
```sh
|
||||
$ docker run --rm \
|
||||
-e TF_VAR_azure_devops_org_name=$AZDO_ORG_NAME \
|
||||
-e TF_VAR_azure_devops_personal_access_token=$AZDO_PAT \
|
||||
-e TF_VAR_azure_devops_pool_name=$AZDO_POOL_NAME \
|
||||
azure-devops-agent-aci-test /bin/bash -c "bundle install && rake full"
|
||||
```
|
||||
|
||||
With:
|
||||
|
||||
- `AZDO_ORG_NAME` being the name of the Azure DevOps organization
|
||||
- `AZDO_PAT` being the personal access token to connect to Azure DevOps
|
||||
- `AZDO_POOL_NAME` being the name of the Azure DevOps agent pool
|
||||
|
||||
## Authors
|
||||
|
||||
Originally created by [Julien Corioland](http://github.com/jcorioland)
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
## Contributing
|
||||
|
||||
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
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# Official gems.
|
||||
require 'colorize'
|
||||
require 'rspec/core/rake_task'
|
||||
|
||||
# Git repo gems.
|
||||
require 'bundler/setup'
|
||||
require 'terramodtest'
|
||||
|
||||
namespace :presteps do
|
||||
task :ensure do
|
||||
puts "Using go mod to install required go packages.\n"
|
||||
success = system ("cd test && go mod download")
|
||||
if not success
|
||||
raise "ERROR: go mod download failed!\n".red
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
namespace :static do
|
||||
task :style do
|
||||
style_tf
|
||||
end
|
||||
task :lint do
|
||||
lint_tf
|
||||
end
|
||||
task :format do
|
||||
format_tf
|
||||
end
|
||||
end
|
||||
|
||||
namespace :integration do
|
||||
task :test do
|
||||
success = system ("cd test && go test -v ./ -timeout 30m -parallel 1")
|
||||
if not success
|
||||
raise "ERROR: Go test failed!\n".red
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
task :prereqs => [ 'presteps:ensure' ]
|
||||
|
||||
task :validate => [ 'static:style', 'static:lint' ]
|
||||
|
||||
task :format => [ 'static:format' ]
|
||||
|
||||
task :build => [ 'prereqs', 'validate' ]
|
||||
|
||||
task :unit => []
|
||||
|
||||
task :e2e => [ 'prereqs', 'integration:test' ]
|
||||
|
||||
task :default => [ 'build' ]
|
||||
|
||||
task :full => [ 'build', 'unit', 'e2e' ]
|
|
@ -0,0 +1,63 @@
|
|||
# Azure Pipeline that runs module integration tests
|
||||
|
||||
trigger: none
|
||||
|
||||
variables:
|
||||
- group: AzureDevOpsACI.Secrets
|
||||
- name: dockerImage
|
||||
value: 'terraform-azure-devops-aci'
|
||||
- name: terraformVersion
|
||||
value: 0.12.25
|
||||
- name: vmImage
|
||||
value: ubuntu-latest
|
||||
- name: serviceConnection
|
||||
value: "terraform-azure-devops-aci"
|
||||
|
||||
stages:
|
||||
- stage: AzureDevOpsACITerraformModule
|
||||
displayName: AZure DevOps ACI Agents Terraform Module - CI
|
||||
jobs:
|
||||
- job: AzureDevOpsACITerraformModuleJob
|
||||
displayName: AZure DevOps ACI Agents Terraform Module - CI Job
|
||||
pool:
|
||||
vmImage: $(vmImage)
|
||||
cancelTimeoutInMinutes: 30
|
||||
steps:
|
||||
- task: AzureCLI@1
|
||||
displayName: Get Azure Credentials for Terraform
|
||||
inputs:
|
||||
azureSubscription: $(serviceConnection)
|
||||
scriptLocation: inlineScript
|
||||
inlineScript: |
|
||||
set -eu
|
||||
subscriptionId=$(az account show --query id -o tsv)
|
||||
echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$servicePrincipalId"
|
||||
echo "##vso[task.setvariable variable=ARM_CLIENT_SECRET;issecret=true]$servicePrincipalKey"
|
||||
echo "##vso[task.setvariable variable=ARM_SUBSCRIPTION_ID;issecret=true]$subscriptionId"
|
||||
echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$tenantId"
|
||||
addSpnToEnvironment: true
|
||||
- task: Docker@2
|
||||
displayName: Build Terratest Docker Image
|
||||
inputs:
|
||||
command: build
|
||||
repository: $(dockerImage)
|
||||
dockerfile: '$(System.DefaultWorkingDirectory)/Dockerfile'
|
||||
buildContext: $(System.DefaultWorkingDirectory)
|
||||
arguments: --build-arg BUILD_ARM_SUBSCRIPTION_ID=$(ARM_SUBSCRIPTION_ID) --build-arg BUILD_ARM_CLIENT_ID=$(ARM_CLIENT_ID) --build-arg BUILD_ARM_CLIENT_SECRET=$(ARM_CLIENT_SECRET) --build-arg BUILD_ARM_TENANT_ID=$(ARM_TENANT_ID)
|
||||
tags: |
|
||||
$(Build.BuildId)
|
||||
- script: |
|
||||
docker run --rm \
|
||||
-e TF_VAR_azure_devops_org_name=$(AZDO_ORG_NAME) \
|
||||
-e TF_VAR_azure_devops_personal_access_token=$(AZDO_PAT) \
|
||||
-e TF_VAR_azure_devops_pool_name=$(AZDO_POOL_NAME) \
|
||||
$(dockerImage):$(Build.BuildId) /bin/bash -c "bundle install && rake build"
|
||||
displayName: Run validation tests
|
||||
- script: |
|
||||
docker run --rm \
|
||||
-e TF_VAR_azure_devops_org_name=$(AZDO_ORG_NAME) \
|
||||
-e TF_VAR_azure_devops_personal_access_token=$(AZDO_PAT) \
|
||||
-e TF_VAR_azure_devops_pool_name=$(AZDO_POOL_NAME) \
|
||||
$(dockerImage):$(Build.BuildId) /bin/bash -c "bundle install && rake full"
|
||||
displayName: Run full end to end tests
|
||||
condition: succeeded()
|
|
@ -0,0 +1,3 @@
|
|||
# Docker images for Azure DevOps agents
|
||||
|
||||
This folder contains Dockerfiles and instructions to build your own [Linux](linux/README.md) or [Windows](windows/README.md) Docker images.
|
|
@ -0,0 +1,25 @@
|
|||
FROM ubuntu:16.04
|
||||
|
||||
# To make it easier for build and release pipelines to run apt-get,
|
||||
# configure apt to not require confirmation (assume the -y argument by default)
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN echo "APT::Get::Assume-Yes \"true\";" > /etc/apt/apt.conf.d/90assumeyes
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
jq \
|
||||
git \
|
||||
iputils-ping \
|
||||
libcurl3 \
|
||||
libicu55 \
|
||||
libunwind8 \
|
||||
netcat
|
||||
|
||||
WORKDIR /azp
|
||||
|
||||
COPY ./start.sh .
|
||||
RUN chmod +x start.sh
|
||||
|
||||
CMD ["./start.sh"]
|
|
@ -0,0 +1,17 @@
|
|||
# Linux Agent Docker Image
|
||||
|
||||
This image is based on the [official documentation](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/docker?view=azure-devops#linux).
|
||||
|
||||
> Note: You can update the [Dockerfile](Dockerfile) to add any software that your require into the Azure DevOps agent, if you don't want to have to download the bits during all pipelines executions.
|
||||
|
||||
## Build it
|
||||
|
||||
```bash
|
||||
docker built -t YOUR_IMAGE_NAME:YOUR_IMAGE_TAG .
|
||||
```
|
||||
|
||||
## Push it
|
||||
|
||||
```bash
|
||||
docker push YOUR_IMAGE_NAME:YOUR_IMAGE_TAG
|
||||
```
|
|
@ -0,0 +1,98 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [ -z "$AZP_URL" ]; then
|
||||
echo 1>&2 "error: missing AZP_URL environment variable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$AZP_TOKEN_FILE" ]; then
|
||||
if [ -z "$AZP_TOKEN" ]; then
|
||||
echo 1>&2 "error: missing AZP_TOKEN environment variable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AZP_TOKEN_FILE=/azp/.token
|
||||
echo -n $AZP_TOKEN > "$AZP_TOKEN_FILE"
|
||||
fi
|
||||
|
||||
unset AZP_TOKEN
|
||||
|
||||
if [ -n "$AZP_WORK" ]; then
|
||||
mkdir -p "$AZP_WORK"
|
||||
fi
|
||||
|
||||
rm -rf /azp/agent
|
||||
mkdir /azp/agent
|
||||
cd /azp/agent
|
||||
|
||||
export AGENT_ALLOW_RUNASROOT="1"
|
||||
|
||||
cleanup() {
|
||||
if [ -e config.sh ]; then
|
||||
print_header "Cleanup. Removing Azure Pipelines agent..."
|
||||
|
||||
./config.sh remove --unattended \
|
||||
--auth PAT \
|
||||
--token $(cat "$AZP_TOKEN_FILE")
|
||||
fi
|
||||
}
|
||||
|
||||
print_header() {
|
||||
lightcyan='\033[1;36m'
|
||||
nocolor='\033[0m'
|
||||
echo -e "${lightcyan}$1${nocolor}"
|
||||
}
|
||||
|
||||
# Let the agent ignore the token env variables
|
||||
export VSO_AGENT_IGNORE=AZP_TOKEN,AZP_TOKEN_FILE
|
||||
|
||||
# ACI in private vnet require time to get access to Internet
|
||||
sleep 30
|
||||
|
||||
print_header "1. Determining matching Azure Pipelines agent..."
|
||||
|
||||
AZP_AGENT_RESPONSE=$(curl -LsS \
|
||||
-u user:$(cat "$AZP_TOKEN_FILE") \
|
||||
-H 'Accept:application/json;api-version=3.0-preview' \
|
||||
"$AZP_URL/_apis/distributedtask/packages/agent?platform=linux-x64")
|
||||
|
||||
if echo "$AZP_AGENT_RESPONSE" | jq . >/dev/null 2>&1; then
|
||||
AZP_AGENTPACKAGE_URL=$(echo "$AZP_AGENT_RESPONSE" \
|
||||
| jq -r '.value | map([.version.major,.version.minor,.version.patch,.downloadUrl]) | sort | .[length-1] | .[3]')
|
||||
fi
|
||||
|
||||
if [ -z "$AZP_AGENTPACKAGE_URL" -o "$AZP_AGENTPACKAGE_URL" == "null" ]; then
|
||||
echo 1>&2 "error: could not determine a matching Azure Pipelines agent - check that account '$AZP_URL' is correct and the token is valid for that account"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_header "2. Downloading and installing Azure Pipelines agent..."
|
||||
|
||||
curl -LsS $AZP_AGENTPACKAGE_URL | tar -xz & wait $!
|
||||
|
||||
source ./env.sh
|
||||
|
||||
trap 'cleanup; exit 130' INT
|
||||
trap 'cleanup; exit 143' TERM
|
||||
|
||||
print_header "3. Configuring Azure Pipelines agent..."
|
||||
|
||||
./config.sh --unattended \
|
||||
--agent "${AZP_AGENT_NAME:-$(hostname)}" \
|
||||
--url "$AZP_URL" \
|
||||
--auth PAT \
|
||||
--token $(cat "$AZP_TOKEN_FILE") \
|
||||
--pool "${AZP_POOL:-Default}" \
|
||||
--work "${AZP_WORK:-_work}" \
|
||||
--replace \
|
||||
--acceptTeeEula & wait $!
|
||||
|
||||
# remove the administrative token before accepting work
|
||||
rm $AZP_TOKEN_FILE
|
||||
|
||||
print_header "4. Running Azure Pipelines agent..."
|
||||
|
||||
# `exec` the node runtime so it's aware of TERM and INT signals
|
||||
# AgentService.js understands how to handle agent self-update and restart
|
||||
exec ./externals/node/bin/node ./bin/AgentService.js interactive
|
|
@ -0,0 +1,7 @@
|
|||
FROM mcr.microsoft.com/windows/servercore:ltsc2019
|
||||
|
||||
WORKDIR /azp
|
||||
|
||||
COPY start.ps1 .
|
||||
|
||||
CMD powershell .\start.ps1
|
|
@ -0,0 +1,17 @@
|
|||
# Windows Agent Docker Image
|
||||
|
||||
This image is based on the [official documentation](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/docker?view=azure-devops#windows).
|
||||
|
||||
> Note: You can update the [Dockerfile](Dockerfile) to add any software that your require into the Azure DevOps agent, if you don't want to have to download the bits during all pipelines executions.
|
||||
|
||||
## Build it
|
||||
|
||||
```bash
|
||||
docker built -t YOUR_IMAGE_NAME:YOUR_IMAGE_TAG .
|
||||
```
|
||||
|
||||
## Push it
|
||||
|
||||
```bash
|
||||
docker push YOUR_IMAGE_NAME:YOUR_IMAGE_TAG
|
||||
```
|
|
@ -0,0 +1,71 @@
|
|||
if (-not (Test-Path Env:AZP_URL)) {
|
||||
Write-Error "error: missing AZP_URL environment variable"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not (Test-Path Env:AZP_TOKEN_FILE)) {
|
||||
if (-not (Test-Path Env:AZP_TOKEN)) {
|
||||
Write-Error "error: missing AZP_TOKEN environment variable"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$Env:AZP_TOKEN_FILE = "\azp\.token"
|
||||
$Env:AZP_TOKEN | Out-File -FilePath $Env:AZP_TOKEN_FILE
|
||||
}
|
||||
|
||||
Remove-Item Env:AZP_TOKEN
|
||||
|
||||
if ($Env:AZP_WORK -and -not (Test-Path Env:AZP_WORK)) {
|
||||
New-Item $Env:AZP_WORK -ItemType directory | Out-Null
|
||||
}
|
||||
|
||||
New-Item "\azp\agent" -ItemType directory | Out-Null
|
||||
|
||||
# Let the agent ignore the token env variables
|
||||
$Env:VSO_AGENT_IGNORE = "AZP_TOKEN,AZP_TOKEN_FILE"
|
||||
|
||||
Set-Location agent
|
||||
|
||||
Write-Host "1. Determining matching Azure Pipelines agent..." -ForegroundColor Cyan
|
||||
|
||||
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$(Get-Content ${Env:AZP_TOKEN_FILE})"))
|
||||
$package = Invoke-RestMethod -Headers @{Authorization=("Basic $base64AuthInfo")} "$(${Env:AZP_URL})/_apis/distributedtask/packages/agent?platform=win-x64&`$top=1"
|
||||
$packageUrl = $package[0].Value.downloadUrl
|
||||
|
||||
Write-Host $packageUrl
|
||||
|
||||
Write-Host "2. Downloading and installing Azure Pipelines agent..." -ForegroundColor Cyan
|
||||
|
||||
$wc = New-Object System.Net.WebClient
|
||||
$wc.DownloadFile($packageUrl, "$(Get-Location)\agent.zip")
|
||||
|
||||
Expand-Archive -Path "agent.zip" -DestinationPath "\azp\agent"
|
||||
|
||||
try
|
||||
{
|
||||
Write-Host "3. Configuring Azure Pipelines agent..." -ForegroundColor Cyan
|
||||
|
||||
.\config.cmd --unattended `
|
||||
--agent "$(if (Test-Path Env:AZP_AGENT_NAME) { ${Env:AZP_AGENT_NAME} } else { ${Env:computername} })" `
|
||||
--url "$(${Env:AZP_URL})" `
|
||||
--auth PAT `
|
||||
--token "$(Get-Content ${Env:AZP_TOKEN_FILE})" `
|
||||
--pool "$(if (Test-Path Env:AZP_POOL) { ${Env:AZP_POOL} } else { 'Default' })" `
|
||||
--work "$(if (Test-Path Env:AZP_WORK) { ${Env:AZP_WORK} } else { '_work' })" `
|
||||
--replace
|
||||
|
||||
# remove the administrative token before accepting work
|
||||
Remove-Item $Env:AZP_TOKEN_FILE
|
||||
|
||||
Write-Host "4. Running Azure Pipelines agent..." -ForegroundColor Cyan
|
||||
|
||||
.\run.cmd
|
||||
}
|
||||
finally
|
||||
{
|
||||
Write-Host "Cleanup. Removing Azure Pipelines agent..." -ForegroundColor Cyan
|
||||
|
||||
.\config.cmd remove --unattended `
|
||||
--auth PAT `
|
||||
--token "$(Get-Content ${Env:AZP_TOKEN_FILE})"
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
resource "azurerm_resource_group" "rg" {
|
||||
# the resource group is created only if the flag create_resource_group is set to true
|
||||
count = var.create_resource_group ? 1 : 0
|
||||
name = var.resource_group_name
|
||||
location = var.location
|
||||
}
|
||||
|
||||
data "azurerm_resource_group" "rg" {
|
||||
# the resource group is imported only if the flag create_resource_group is set to false
|
||||
count = var.create_resource_group ? 0 : 1
|
||||
name = var.resource_group_name
|
||||
}
|
||||
|
||||
data "azurerm_subnet" "subnet" {
|
||||
# the subnet is imported only enable_vnet_integration is true
|
||||
count = var.enable_vnet_integration ? 1 : 0
|
||||
name = var.subnet_name
|
||||
virtual_network_name = var.vnet_name
|
||||
resource_group_name = var.vnet_resource_group_name
|
||||
}
|
||||
|
||||
# Linux Agents - deployed only if variable linux_agents_configuration.count > 0
|
||||
|
||||
resource "azurerm_network_profile" "linux_network_profile" {
|
||||
count = var.enable_vnet_integration ? var.linux_agents_configuration.count : 0
|
||||
name = "linuxnetprofile${count.index}"
|
||||
location = var.location
|
||||
resource_group_name = var.create_resource_group ? azurerm_resource_group.rg[0].name : data.azurerm_resource_group.rg[0].name
|
||||
|
||||
container_network_interface {
|
||||
name = "linuxnic${count.index}"
|
||||
|
||||
ip_configuration {
|
||||
name = "linuxip${count.index}"
|
||||
subnet_id = data.azurerm_subnet.subnet[0].id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_container_group" "linux-container-group" {
|
||||
count = var.linux_agents_configuration.count
|
||||
name = "${var.linux_agents_configuration.agent_name_prefix}-${count.index}"
|
||||
location = var.location
|
||||
resource_group_name = var.create_resource_group ? azurerm_resource_group.rg[0].name : data.azurerm_resource_group.rg[0].name
|
||||
ip_address_type = var.enable_vnet_integration ? "private" : "public"
|
||||
os_type = "linux"
|
||||
network_profile_id = var.enable_vnet_integration ? azurerm_network_profile.linux_network_profile[count.index].id : null
|
||||
|
||||
container {
|
||||
name = "${var.linux_agents_configuration.agent_name_prefix}-${count.index}"
|
||||
image = "${var.linux_agents_configuration.docker_image}:${var.linux_agents_configuration.docker_tag}"
|
||||
cpu = var.linux_agents_configuration.cpu
|
||||
memory = var.linux_agents_configuration.memory
|
||||
|
||||
# this field seems to be mandatory (error happens if not there). See https://github.com/terraform-providers/terraform-provider-azurerm/issues/1697#issuecomment-608669422
|
||||
ports {
|
||||
port = 80
|
||||
protocol = "TCP"
|
||||
}
|
||||
|
||||
environment_variables = {
|
||||
AZP_URL = "https://dev.azure.com/${var.azure_devops_org_name}"
|
||||
AZP_POOL = var.linux_agents_configuration.agent_pool_name
|
||||
AZP_TOKEN = var.azure_devops_personal_access_token
|
||||
AZP_AGENT_NAME = "${var.linux_agents_configuration.agent_name_prefix}-${count.index}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Windows Agents - deployed only if variable windows_agents_configuration.count > 0
|
||||
|
||||
resource "azurerm_network_profile" "windows_network_profile" {
|
||||
count = var.enable_vnet_integration ? var.windows_agents_configuration.count : 0
|
||||
name = "windowsnetprofile${count.index}"
|
||||
location = var.location
|
||||
resource_group_name = var.create_resource_group ? azurerm_resource_group.rg[0].name : data.azurerm_resource_group.rg[0].name
|
||||
|
||||
container_network_interface {
|
||||
name = "windowsnic${count.index}"
|
||||
|
||||
ip_configuration {
|
||||
name = "windowsip${count.index}"
|
||||
subnet_id = data.azurerm_subnet.subnet[0].id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_container_group" "windows-container-group" {
|
||||
count = var.windows_agents_configuration.count
|
||||
name = "${var.windows_agents_configuration.agent_name_prefix}-${count.index}"
|
||||
location = var.location
|
||||
resource_group_name = var.create_resource_group ? azurerm_resource_group.rg[0].name : data.azurerm_resource_group.rg[0].name
|
||||
ip_address_type = var.enable_vnet_integration ? "private" : "public"
|
||||
os_type = "windows"
|
||||
network_profile_id = var.enable_vnet_integration ? azurerm_network_profile.windows_network_profile[count.index].id : null
|
||||
|
||||
container {
|
||||
name = "${var.windows_agents_configuration.agent_name_prefix}-${count.index}"
|
||||
image = "${var.windows_agents_configuration.docker_image}:${var.windows_agents_configuration.docker_tag}"
|
||||
cpu = var.windows_agents_configuration.cpu
|
||||
memory = var.windows_agents_configuration.memory
|
||||
|
||||
# this field seems to be mandatory (error happens if not there). See https://github.com/terraform-providers/terraform-provider-azurerm/issues/1697#issuecomment-608669422
|
||||
ports {
|
||||
port = 80
|
||||
protocol = "TCP"
|
||||
}
|
||||
|
||||
environment_variables = {
|
||||
AZP_URL = "https://dev.azure.com/${var.azure_devops_org_name}"
|
||||
AZP_POOL = var.windows_agents_configuration.agent_pool_name
|
||||
AZP_TOKEN = var.azure_devops_personal_access_token
|
||||
AZP_AGENT_NAME = "${var.windows_agents_configuration.agent_name_prefix}-${count.index}"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
output "has_linux_agents" {
|
||||
value = length(azurerm_container_group.linux-container-group) > 0 ? true : false
|
||||
description = "A flag that indicates if Linux agents have been deployed with the current configuration."
|
||||
}
|
||||
|
||||
output "linux_agents_count" {
|
||||
value = length(azurerm_container_group.linux-container-group)
|
||||
description = "A number that indicates the number of Linux agents that have been deployed with the current configuration."
|
||||
}
|
||||
|
||||
output "linux_agents_names" {
|
||||
value = azurerm_container_group.linux-container-group.*.name
|
||||
description = "An array that contains the names of Linux agents that have been deployed with the current configuration."
|
||||
}
|
||||
|
||||
output "vnet_integration_enabled" {
|
||||
value = var.enable_vnet_integration
|
||||
description = "A flag that indicates if the vnet integration has been enabled with the current configuration."
|
||||
}
|
||||
|
||||
output "subnet_id" {
|
||||
value = var.enable_vnet_integration ? data.azurerm_subnet.subnet[0].id : ""
|
||||
description = "If the vnet integration is enabled, the id of the subnet in which the agents are deployed."
|
||||
}
|
||||
|
||||
output "has_windows_agents" {
|
||||
value = length(azurerm_container_group.windows-container-group) > 0 ? true : false
|
||||
description = "A flag that indicates if Windows agents have been deployed with the current configuration."
|
||||
}
|
||||
|
||||
output "windows_agents_count" {
|
||||
value = length(azurerm_container_group.windows-container-group)
|
||||
description = "A number that indicates the number of Windows agents that have been deployed with the current configuration."
|
||||
}
|
||||
|
||||
output "windows_agents_names" {
|
||||
value = azurerm_container_group.windows-container-group.*.name
|
||||
description = "An array that contains the names of Windows agents that have been deployed with the current configuration."
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
|
@ -0,0 +1,389 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gruntwork-io/terratest/modules/terraform"
|
||||
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
|
||||
"github.com/microsoft/azure-devops-go-api/azuredevops"
|
||||
"github.com/microsoft/azure-devops-go-api/azuredevops/taskagent"
|
||||
)
|
||||
|
||||
// This function tests the deployment of Azure DevOps Linux agents
|
||||
func TestDeployAzureDevOpsLinuxAgents(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fixtureFolder := "./fixture/linux-agents"
|
||||
|
||||
// generate a random suffix for the test
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
randomInt := rand.Intn(9999)
|
||||
randomSuffix := strconv.Itoa(randomInt)
|
||||
os.Setenv("TF_VAR_random_suffix", randomSuffix)
|
||||
|
||||
// randomize the agent pool name
|
||||
devopsPoolName := os.Getenv("TF_VAR_azure_devops_pool_name")
|
||||
testPoolName := fmt.Sprintf("%s-%s", devopsPoolName, randomSuffix)
|
||||
os.Setenv("TF_VAR_azure_devops_pool_name", testPoolName)
|
||||
|
||||
devopsOrganizationName := os.Getenv("TF_VAR_azure_devops_org_name")
|
||||
devopsPersonalAccessToken := os.Getenv("TF_VAR_azure_devops_personal_access_token")
|
||||
devopsOrganizationURL := fmt.Sprintf("https://dev.azure.com/%s", devopsOrganizationName)
|
||||
|
||||
defer deleteAzureDevOpsAgentTestPool(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
err := createAzureDevOpsAgentTestPool(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create Azure DevOps agent pool for the test: %v", err)
|
||||
}
|
||||
|
||||
// Deploy the example
|
||||
test_structure.RunTestStage(t, "setup", func() {
|
||||
terraformOptions := configureTerraformOptions(t, fixtureFolder)
|
||||
|
||||
// Save the options so later test stages can use them
|
||||
test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions)
|
||||
|
||||
// This will init and apply the resources and fail the test if there are any errors
|
||||
terraform.InitAndApply(t, terraformOptions)
|
||||
})
|
||||
|
||||
// Check whether the length of output meets the requirement
|
||||
test_structure.RunTestStage(t, "validate", func() {
|
||||
// add wait time for ACI to get connectivity
|
||||
time.Sleep(45 * time.Second)
|
||||
|
||||
// ensure deployment was successful
|
||||
expectedAgentsCount := 2
|
||||
actualAgentsCount, err := getAgentsCount(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot retrieve the number of agents that were deployed: %v", err)
|
||||
}
|
||||
|
||||
if expectedAgentsCount != actualAgentsCount {
|
||||
t.Fatalf("Test failed. Expected number of agents is %d. Actual number of agents is %d", expectedAgentsCount, actualAgentsCount)
|
||||
}
|
||||
})
|
||||
|
||||
// At the end of the test, clean up any resources that were created
|
||||
test_structure.RunTestStage(t, "teardown", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
|
||||
terraform.Destroy(t, terraformOptions)
|
||||
})
|
||||
}
|
||||
|
||||
// This function tests the deployment of Azure DevOps Linux agents into an existing virtual network
|
||||
func TestDeployAzureDevOpsLinuxAgentsInVirtualNetwork(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fixtureFolder := "./fixture/linux-agents-vnet"
|
||||
|
||||
// generate a random suffix for the test
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
randomInt := rand.Intn(9999)
|
||||
randomSuffix := strconv.Itoa(randomInt)
|
||||
os.Setenv("TF_VAR_random_suffix", randomSuffix)
|
||||
|
||||
// randomize the agent pool name
|
||||
devopsPoolName := os.Getenv("TF_VAR_azure_devops_pool_name")
|
||||
testPoolName := fmt.Sprintf("%s-%s", devopsPoolName, randomSuffix)
|
||||
os.Setenv("TF_VAR_azure_devops_pool_name", testPoolName)
|
||||
|
||||
devopsOrganizationName := os.Getenv("TF_VAR_azure_devops_org_name")
|
||||
devopsPersonalAccessToken := os.Getenv("TF_VAR_azure_devops_personal_access_token")
|
||||
devopsOrganizationURL := fmt.Sprintf("https://dev.azure.com/%s", devopsOrganizationName)
|
||||
|
||||
defer deleteAzureDevOpsAgentTestPool(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
err := createAzureDevOpsAgentTestPool(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create Azure DevOps agent pool for the test: %v", err)
|
||||
}
|
||||
|
||||
// Deploy the example
|
||||
test_structure.RunTestStage(t, "setup", func() {
|
||||
terraformOptions := configureTerraformOptions(t, fixtureFolder)
|
||||
|
||||
// Save the options so later test stages can use them
|
||||
test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions)
|
||||
|
||||
// This will init and apply the resources and fail the test if there are any errors
|
||||
terraform.InitAndApply(t, terraformOptions)
|
||||
})
|
||||
|
||||
// Check whether the length of output meets the requirement
|
||||
test_structure.RunTestStage(t, "validate", func() {
|
||||
// add wait time for ACI to get connectivity
|
||||
time.Sleep(45 * time.Second)
|
||||
|
||||
// ensure deployment was successful
|
||||
expectedAgentsCount := 2
|
||||
actualAgentsCount, err := getAgentsCount(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot retrieve the number of agents that were deployed: %v", err)
|
||||
}
|
||||
|
||||
if expectedAgentsCount != actualAgentsCount {
|
||||
t.Fatalf("Test failed. Expected number of agents is %d. Actual number of agents is %d", expectedAgentsCount, actualAgentsCount)
|
||||
}
|
||||
})
|
||||
|
||||
// At the end of the test, clean up any resources that were created
|
||||
test_structure.RunTestStage(t, "teardown", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
|
||||
terraform.Destroy(t, terraformOptions)
|
||||
})
|
||||
}
|
||||
|
||||
// This function tests the deployment of Azure DevOps Linux and Windows agents
|
||||
func TestDeployAzureDevOpsLinuxAndWindowsAgents(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fixtureFolder := "./fixture/linux-and-windows-agents"
|
||||
|
||||
// generate a random suffix for the test
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
randomInt := rand.Intn(9999)
|
||||
randomSuffix := strconv.Itoa(randomInt)
|
||||
os.Setenv("TF_VAR_random_suffix", randomSuffix)
|
||||
|
||||
// create random Linux agent pool name
|
||||
linuxTestPoolName := fmt.Sprintf("linux-e2e-agents-%s", randomSuffix)
|
||||
os.Setenv("TF_VAR_linux_azure_devops_pool_name", linuxTestPoolName)
|
||||
|
||||
// create random Windows agent pool name
|
||||
windowsTestPoolName := fmt.Sprintf("windows-e2e-agents-%s", randomSuffix)
|
||||
os.Setenv("TF_VAR_windows_azure_devops_pool_name", windowsTestPoolName)
|
||||
|
||||
devopsOrganizationName := os.Getenv("TF_VAR_azure_devops_org_name")
|
||||
devopsPersonalAccessToken := os.Getenv("TF_VAR_azure_devops_personal_access_token")
|
||||
devopsOrganizationURL := fmt.Sprintf("https://dev.azure.com/%s", devopsOrganizationName)
|
||||
|
||||
// create the Linux agents pool
|
||||
defer deleteAzureDevOpsAgentTestPool(linuxTestPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
err := createAzureDevOpsAgentTestPool(linuxTestPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create Azure DevOps Linux agent pool for the test: %v", err)
|
||||
}
|
||||
|
||||
// create the Windows agents pool
|
||||
defer deleteAzureDevOpsAgentTestPool(windowsTestPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
err = createAzureDevOpsAgentTestPool(windowsTestPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create Azure DevOps Linux agent pool for the test: %v", err)
|
||||
}
|
||||
|
||||
// Deploy the example
|
||||
test_structure.RunTestStage(t, "setup", func() {
|
||||
terraformOptions := configureTerraformOptions(t, fixtureFolder)
|
||||
|
||||
// Save the options so later test stages can use them
|
||||
test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions)
|
||||
|
||||
// This will init and apply the resources and fail the test if there are any errors
|
||||
terraform.InitAndApply(t, terraformOptions)
|
||||
})
|
||||
|
||||
// Check whether the length of output meets the requirement
|
||||
test_structure.RunTestStage(t, "validate", func() {
|
||||
// add wait time for ACI to get connectivity + pull Windows image
|
||||
time.Sleep(150 * time.Second)
|
||||
|
||||
// ensure deployment was successful for Linux agents
|
||||
expectedLinuxAgentsCount := 2
|
||||
actualLinuxAgentsCount, err := getAgentsCount(linuxTestPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot retrieve the number of Linux agents that were deployed: %v", err)
|
||||
}
|
||||
|
||||
if expectedLinuxAgentsCount != actualLinuxAgentsCount {
|
||||
t.Fatalf("Test failed. Expected number of Linux agents is %d. Actual number of Linux agents is %d", expectedLinuxAgentsCount, actualLinuxAgentsCount)
|
||||
}
|
||||
|
||||
// ensure deployment was successful for Windows agents
|
||||
expectedWindowsAgentsCount := 2
|
||||
actualWindowsAgentsCount, err := getAgentsCount(windowsTestPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot retrieve the number of Windows agents that were deployed: %v", err)
|
||||
}
|
||||
|
||||
if expectedWindowsAgentsCount != actualWindowsAgentsCount {
|
||||
t.Fatalf("Test failed. Expected number of Windows agents is %d. Actual number of Windows agents is %d", expectedWindowsAgentsCount, actualWindowsAgentsCount)
|
||||
}
|
||||
})
|
||||
|
||||
// At the end of the test, clean up any resources that were created
|
||||
test_structure.RunTestStage(t, "teardown", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
|
||||
terraform.Destroy(t, terraformOptions)
|
||||
})
|
||||
}
|
||||
|
||||
// This function tests the deployment of Azure DevOps Linux agents into an existing resource group
|
||||
func TestDeployAzureDevOpsLinuxAgentsIntoExistingRresourceGroup(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fixtureFolder := "./fixture/linux-agents-import-rg"
|
||||
|
||||
// generate a random suffix for the test
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
randomInt := rand.Intn(9999)
|
||||
randomSuffix := strconv.Itoa(randomInt)
|
||||
os.Setenv("TF_VAR_random_suffix", randomSuffix)
|
||||
|
||||
// randomize the agent pool name
|
||||
devopsPoolName := os.Getenv("TF_VAR_azure_devops_pool_name")
|
||||
testPoolName := fmt.Sprintf("%s-%s", devopsPoolName, randomSuffix)
|
||||
os.Setenv("TF_VAR_azure_devops_pool_name", testPoolName)
|
||||
|
||||
devopsOrganizationName := os.Getenv("TF_VAR_azure_devops_org_name")
|
||||
devopsPersonalAccessToken := os.Getenv("TF_VAR_azure_devops_personal_access_token")
|
||||
devopsOrganizationURL := fmt.Sprintf("https://dev.azure.com/%s", devopsOrganizationName)
|
||||
|
||||
defer deleteAzureDevOpsAgentTestPool(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
err := createAzureDevOpsAgentTestPool(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot create Azure DevOps agent pool for the test: %v", err)
|
||||
}
|
||||
|
||||
// Deploy the example
|
||||
test_structure.RunTestStage(t, "setup", func() {
|
||||
terraformOptions := configureTerraformOptions(t, fixtureFolder)
|
||||
|
||||
// Save the options so later test stages can use them
|
||||
test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions)
|
||||
|
||||
// This will init and apply the resources and fail the test if there are any errors
|
||||
terraform.InitAndApply(t, terraformOptions)
|
||||
})
|
||||
|
||||
// Check whether the length of output meets the requirement
|
||||
test_structure.RunTestStage(t, "validate", func() {
|
||||
// add wait time for ACI to get connectivity
|
||||
time.Sleep(45 * time.Second)
|
||||
|
||||
// ensure deployment was successful
|
||||
expectedAgentsCount := 2
|
||||
actualAgentsCount, err := getAgentsCount(testPoolName, devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Cannot retrieve the number of agents that were deployed: %v", err)
|
||||
}
|
||||
|
||||
if expectedAgentsCount != actualAgentsCount {
|
||||
t.Fatalf("Test failed. Expected number of agents is %d. Actual number of agents is %d", expectedAgentsCount, actualAgentsCount)
|
||||
}
|
||||
})
|
||||
|
||||
// At the end of the test, clean up any resources that were created
|
||||
test_structure.RunTestStage(t, "teardown", func() {
|
||||
terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder)
|
||||
terraform.Destroy(t, terraformOptions)
|
||||
})
|
||||
}
|
||||
|
||||
func configureTerraformOptions(t *testing.T, fixtureFolder string) *terraform.Options {
|
||||
|
||||
terraformOptions := &terraform.Options{
|
||||
// The path to where our Terraform code is located
|
||||
TerraformDir: fixtureFolder,
|
||||
|
||||
// Variables to pass to our Terraform code using -var options
|
||||
Vars: map[string]interface{}{},
|
||||
}
|
||||
|
||||
return terraformOptions
|
||||
}
|
||||
|
||||
func getAgentsCount(devopsPoolName string, devopsOrganizationURL string, devopsPersonalAccessToken string) (int, error) {
|
||||
ctx := context.Background()
|
||||
devopsConnection := azuredevops.NewPatConnection(devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
devopsTaskAgentClient, err := taskagent.NewClient(ctx, devopsConnection)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
agentPool, err := getAgentPool(ctx, devopsTaskAgentClient, devopsPoolName)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
getAgentsArgs := taskagent.GetAgentsArgs{
|
||||
PoolId: agentPool.Id,
|
||||
}
|
||||
|
||||
agents, err := devopsTaskAgentClient.GetAgents(ctx, getAgentsArgs)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return len(*agents), nil
|
||||
}
|
||||
|
||||
func createAzureDevOpsAgentTestPool(devopsPoolName string, devopsOrganizationURL string, devopsPersonalAccessToken string) error {
|
||||
ctx := context.Background()
|
||||
devopsConnection := azuredevops.NewPatConnection(devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
devopsTaskAgentClient, err := taskagent.NewClient(ctx, devopsConnection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addAgentPoolArgs := taskagent.AddAgentPoolArgs{
|
||||
Pool: &taskagent.TaskAgentPool{
|
||||
Name: &devopsPoolName,
|
||||
PoolType: &taskagent.TaskAgentPoolTypeValues.Automation,
|
||||
},
|
||||
}
|
||||
|
||||
_, err = devopsTaskAgentClient.AddAgentPool(ctx, addAgentPoolArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteAzureDevOpsAgentTestPool(devopsPoolName string, devopsOrganizationURL string, devopsPersonalAccessToken string) error {
|
||||
ctx := context.Background()
|
||||
devopsConnection := azuredevops.NewPatConnection(devopsOrganizationURL, devopsPersonalAccessToken)
|
||||
devopsTaskAgentClient, err := taskagent.NewClient(ctx, devopsConnection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
agentPoolToDelete, err := getAgentPool(ctx, devopsTaskAgentClient, devopsPoolName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deleteAgentPoolArgs := taskagent.DeleteAgentPoolArgs{
|
||||
PoolId: agentPoolToDelete.Id,
|
||||
}
|
||||
|
||||
return devopsTaskAgentClient.DeleteAgentPool(ctx, deleteAgentPoolArgs)
|
||||
}
|
||||
|
||||
func getAgentPool(ctx context.Context, devopsTaskAgentClient taskagent.Client, devopsPoolName string) (*taskagent.TaskAgentPool, error) {
|
||||
getAgentPoolsArgs := taskagent.GetAgentPoolsArgs{
|
||||
PoolName: &devopsPoolName,
|
||||
}
|
||||
|
||||
matchingAgentPools, err := devopsTaskAgentClient.GetAgentPools(ctx, getAgentPoolsArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if matchingAgentPools == nil || len(*matchingAgentPools) == 0 {
|
||||
return nil, fmt.Errorf("Cannot find an agent pool that matches name: %s", devopsPoolName)
|
||||
}
|
||||
|
||||
return &(*matchingAgentPools)[0], nil
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
resource "azurerm_resource_group" "rg" {
|
||||
name = "rg-terraform-azure-devops-agents-e2e-tests-${var.random_suffix}"
|
||||
location = var.location
|
||||
}
|
||||
|
||||
module "aci-devops-agent" {
|
||||
source = "../../../"
|
||||
enable_vnet_integration = false
|
||||
create_resource_group = false
|
||||
linux_agents_configuration = {
|
||||
agent_name_prefix = "linuxagent-${var.random_suffix}"
|
||||
count = var.agents_count
|
||||
docker_image = var.agent_docker_image
|
||||
docker_tag = var.agent_docker_tag
|
||||
agent_pool_name = var.azure_devops_pool_name
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
resource_group_name = azurerm_resource_group.rg.name
|
||||
location = azurerm_resource_group.rg.location
|
||||
azure_devops_org_name = var.azure_devops_org_name
|
||||
azure_devops_personal_access_token = var.azure_devops_personal_access_token
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
variable azure_devops_org_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps organization in which the containerized agents will be deployed (e.g. https://dev.azure.com/YOUR_ORGANIZATION_NAME, must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_pool_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps agent pool in which the containerized agents will be deployed (must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_personal_access_token {
|
||||
type = string
|
||||
description = "The personal access token to use to connect to Azure DevOps (see https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=azure-devops#permissions)"
|
||||
}
|
||||
|
||||
variable location {
|
||||
type = string
|
||||
description = "The Azure location to use"
|
||||
default = "westeurope"
|
||||
}
|
||||
|
||||
variable agent_docker_image {
|
||||
type = string
|
||||
description = "The Docker image to use for the Linux agent"
|
||||
default = "jcorioland/aci-devops-agent"
|
||||
}
|
||||
|
||||
variable agent_docker_tag {
|
||||
type = string
|
||||
description = "The Docker tag to use for the Linux agent"
|
||||
default = "0.2-linux"
|
||||
}
|
||||
|
||||
variable agents_count {
|
||||
type = number
|
||||
description = "The number of agents to create"
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable random_suffix {
|
||||
type = number
|
||||
description = "A random suffix for resources generated during the test"
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
resource "azurerm_resource_group" "vnet-rg" {
|
||||
name = "rg-aci-devops-network-${var.random_suffix}"
|
||||
location = var.location
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_network" "vnet" {
|
||||
name = "vnet-aci-devops-${var.random_suffix}"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
location = azurerm_resource_group.vnet-rg.location
|
||||
resource_group_name = azurerm_resource_group.vnet-rg.name
|
||||
}
|
||||
|
||||
resource "azurerm_subnet" "aci-subnet" {
|
||||
name = "aci-subnet-${var.random_suffix}"
|
||||
resource_group_name = azurerm_resource_group.vnet-rg.name
|
||||
virtual_network_name = azurerm_virtual_network.vnet.name
|
||||
address_prefixes = ["10.0.1.0/24"]
|
||||
|
||||
delegation {
|
||||
name = "acidelegation"
|
||||
|
||||
service_delegation {
|
||||
name = "Microsoft.ContainerInstance/containerGroups"
|
||||
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "aci-devops-agent" {
|
||||
source = "../../../"
|
||||
enable_vnet_integration = true
|
||||
create_resource_group = true
|
||||
vnet_resource_group_name = azurerm_resource_group.vnet-rg.name
|
||||
vnet_name = azurerm_virtual_network.vnet.name
|
||||
subnet_name = azurerm_subnet.aci-subnet.name
|
||||
linux_agents_configuration = {
|
||||
agent_name_prefix = "linuxagent-${var.random_suffix}"
|
||||
count = var.agents_count
|
||||
docker_image = var.agent_docker_image
|
||||
docker_tag = var.agent_docker_tag
|
||||
agent_pool_name = var.azure_devops_pool_name
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
resource_group_name = "rg-terraform-azure-devops-agents-e2e-tests-${var.random_suffix}"
|
||||
location = var.location
|
||||
azure_devops_org_name = var.azure_devops_org_name
|
||||
azure_devops_personal_access_token = var.azure_devops_personal_access_token
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
variable azure_devops_org_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps organization in which the containerized agents will be deployed (e.g. https://dev.azure.com/YOUR_ORGANIZATION_NAME, must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_pool_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps agent pool in which the containerized agents will be deployed (must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_personal_access_token {
|
||||
type = string
|
||||
description = "The personal access token to use to connect to Azure DevOps (see https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=azure-devops#permissions)"
|
||||
}
|
||||
|
||||
variable location {
|
||||
type = string
|
||||
description = "The Azure location to use"
|
||||
default = "westus"
|
||||
}
|
||||
|
||||
variable agent_docker_image {
|
||||
type = string
|
||||
description = "The Docker image to use for the Linux agent"
|
||||
default = "jcorioland/aci-devops-agent"
|
||||
}
|
||||
|
||||
variable agent_docker_tag {
|
||||
type = string
|
||||
description = "The Docker tag to use for the Linux agent"
|
||||
default = "0.2-linux"
|
||||
}
|
||||
|
||||
variable agents_count {
|
||||
type = number
|
||||
description = "The number of agents to create"
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable random_suffix {
|
||||
type = number
|
||||
description = "A random suffix for resources generated during the test"
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
module "aci-devops-agent" {
|
||||
source = "../../../"
|
||||
enable_vnet_integration = false
|
||||
create_resource_group = true
|
||||
linux_agents_configuration = {
|
||||
agent_name_prefix = "linuxagent-${var.random_suffix}"
|
||||
count = var.agents_count
|
||||
docker_image = var.agent_docker_image
|
||||
docker_tag = var.agent_docker_tag
|
||||
agent_pool_name = var.azure_devops_pool_name
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
resource_group_name = "rg-terraform-azure-devops-agents-e2e-tests-${var.random_suffix}"
|
||||
location = var.location
|
||||
azure_devops_org_name = var.azure_devops_org_name
|
||||
azure_devops_personal_access_token = var.azure_devops_personal_access_token
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
variable azure_devops_org_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps organization in which the containerized agents will be deployed (e.g. https://dev.azure.com/YOUR_ORGANIZATION_NAME, must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_pool_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps agent pool in which the containerized agents will be deployed (must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_personal_access_token {
|
||||
type = string
|
||||
description = "The personal access token to use to connect to Azure DevOps (see https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=azure-devops#permissions)"
|
||||
}
|
||||
|
||||
variable location {
|
||||
type = string
|
||||
description = "The Azure location to use"
|
||||
default = "westeurope"
|
||||
}
|
||||
|
||||
variable agent_docker_image {
|
||||
type = string
|
||||
description = "The Docker image to use for the Linux agent"
|
||||
default = "jcorioland/aci-devops-agent"
|
||||
}
|
||||
|
||||
variable agent_docker_tag {
|
||||
type = string
|
||||
description = "The Docker tag to use for the Linux agent"
|
||||
default = "0.2-linux"
|
||||
}
|
||||
|
||||
variable agents_count {
|
||||
type = number
|
||||
description = "The number of agents to create"
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable random_suffix {
|
||||
type = number
|
||||
description = "A random suffix for resources generated during the test"
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
module "aci-devops-agent" {
|
||||
source = "../../../"
|
||||
enable_vnet_integration = false
|
||||
create_resource_group = true
|
||||
linux_agents_configuration = {
|
||||
agent_name_prefix = "linux-agent-${var.random_suffix}"
|
||||
count = 2,
|
||||
docker_image = var.linux_agent_docker_image
|
||||
docker_tag = var.linux_agent_docker_tag
|
||||
agent_pool_name = var.linux_azure_devops_pool_name
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
windows_agents_configuration = {
|
||||
agent_name_prefix = "windows-agent-${var.random_suffix}"
|
||||
count = 2,
|
||||
docker_image = var.windows_agent_docker_image
|
||||
docker_tag = var.windows_agent_docker_tag
|
||||
agent_pool_name = var.windows_azure_devops_pool_name
|
||||
cpu = 1
|
||||
memory = 4
|
||||
}
|
||||
resource_group_name = "rg-terraform-azure-devops-agents-e2e-tests-${var.random_suffix}"
|
||||
location = var.location
|
||||
azure_devops_org_name = var.azure_devops_org_name
|
||||
azure_devops_personal_access_token = var.azure_devops_personal_access_token
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
variable azure_devops_org_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps organization in which the containerized agents will be deployed (e.g. https://dev.azure.com/YOUR_ORGANIZATION_NAME, must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_personal_access_token {
|
||||
type = string
|
||||
description = "The personal access token to use to connect to Azure DevOps (see https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=azure-devops#permissions)"
|
||||
}
|
||||
|
||||
variable linux_azure_devops_pool_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps agent pool in which the linux containerized agents will be deployed (must exist)"
|
||||
default = "linux-e2e-agents"
|
||||
}
|
||||
|
||||
variable windows_azure_devops_pool_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps agent pool in which the windows containerized agents will be deployed (must exist)"
|
||||
default = "windows-e2e-agents"
|
||||
}
|
||||
|
||||
variable location {
|
||||
type = string
|
||||
description = "The Azure location to use"
|
||||
default = "westeurope"
|
||||
}
|
||||
|
||||
variable linux_agent_docker_image {
|
||||
type = string
|
||||
description = "The Docker image to use for the Linux agent"
|
||||
default = "jcorioland/aci-devops-agent"
|
||||
}
|
||||
|
||||
variable linux_agent_docker_tag {
|
||||
type = string
|
||||
description = "The Docker tag to use for the Linux agent"
|
||||
default = "0.2-linux"
|
||||
}
|
||||
|
||||
variable windows_agent_docker_image {
|
||||
type = string
|
||||
description = "The Docker image to use for the Windows agent"
|
||||
default = "jcorioland/aci-devops-agent"
|
||||
}
|
||||
|
||||
variable windows_agent_docker_tag {
|
||||
type = string
|
||||
description = "The Docker tag to use for the Windows agent"
|
||||
default = "0.2-win"
|
||||
}
|
||||
|
||||
variable agents_count {
|
||||
type = number
|
||||
description = "The number of agents to create"
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable random_suffix {
|
||||
type = number
|
||||
description = "A random suffix for resources generated during the test"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module test
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/gruntwork-io/terratest v0.27.2
|
||||
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b1
|
||||
)
|
|
@ -0,0 +1,93 @@
|
|||
variable resource_group_name {
|
||||
type = string
|
||||
description = "The name of the resource group in which the containerized agents will be deployed"
|
||||
}
|
||||
|
||||
variable location {
|
||||
type = string
|
||||
description = "The Azure location to use for deployment"
|
||||
}
|
||||
|
||||
variable create_resource_group {
|
||||
type = bool
|
||||
default = true
|
||||
description = "(Optional) A flag that indicates if the resource group in which the agents will be deployed must be created (true) or imported (false)."
|
||||
}
|
||||
|
||||
variable enable_vnet_integration {
|
||||
type = bool
|
||||
default = false
|
||||
description = "(Optional) A flag that indicates if the containerized agents must be deployed into an existing virtual network"
|
||||
}
|
||||
|
||||
variable vnet_resource_group_name {
|
||||
type = string
|
||||
default = ""
|
||||
description = "(Optional) The name of the resource group that contains the virtual network in which the containerized agents will be deployed"
|
||||
}
|
||||
|
||||
variable vnet_name {
|
||||
type = string
|
||||
default = ""
|
||||
description = "(Optional) The name of the virtual network in which the containerized agents will be deployed"
|
||||
}
|
||||
|
||||
variable subnet_name {
|
||||
type = string
|
||||
default = ""
|
||||
description = "(Optional) The name of the subnet of the vnet in which the containerized agents will be deployed"
|
||||
}
|
||||
|
||||
variable azure_devops_org_name {
|
||||
type = string
|
||||
description = "The name of the Azure DevOps organization in which the containerized agents will be deployed (e.g. https://dev.azure.com/YOUR_ORGANIZATION_NAME, must exist)"
|
||||
}
|
||||
|
||||
variable azure_devops_personal_access_token {
|
||||
type = string
|
||||
description = "The personal access token to use to connect to Azure DevOps (see https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows?view=azure-devops#permissions)"
|
||||
}
|
||||
|
||||
variable linux_agents_configuration {
|
||||
type = object({
|
||||
count = string,
|
||||
docker_image = string,
|
||||
docker_tag = string,
|
||||
agent_name_prefix = string,
|
||||
agent_pool_name = string,
|
||||
cpu = string,
|
||||
memory = string
|
||||
})
|
||||
description = "(Optional) The configuration of the Linux agents to deploy"
|
||||
default = {
|
||||
count = 0,
|
||||
docker_image = "",
|
||||
docker_tag = "",
|
||||
agent_name_prefix = "",
|
||||
agent_pool_name = "",
|
||||
cpu = "1",
|
||||
memory = "2"
|
||||
}
|
||||
}
|
||||
|
||||
variable windows_agents_configuration {
|
||||
type = object({
|
||||
count = string,
|
||||
docker_image = string,
|
||||
docker_tag = string,
|
||||
agent_name_prefix = string,
|
||||
agent_pool_name = string,
|
||||
cpu = string,
|
||||
memory = string
|
||||
})
|
||||
description = "(Optional) The configuration of the Windows agents to deploy"
|
||||
default = {
|
||||
count = 0,
|
||||
docker_image = "",
|
||||
docker_tag = "",
|
||||
agent_name_prefix = "",
|
||||
agent_pool_name = "",
|
||||
cpu = "1",
|
||||
memory = "2"
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче