Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding Azure Container Instances module #593

Merged
merged 8 commits into from
Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions examples/azure/terraform-azure-aci-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Terraform Azure Example

This folder contains a simple Terraform module that deploys resources in [Azure](https://azure.microsoft.com/) to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an [Azure Container Instance](https://azure.microsoft.com/en-us/services/container-instances/).

Check out [test/azure/terraform_azure_aci_example_test.go](/test/azure/terraform_azure_aci_example_test.go) to see how you can write
automated tests for this module.

**WARNING**: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the [Azure Free Account](https://azure.microsoft.com/en-us/free/), so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

## Running this module manually

1. Sign up for [Azure](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. [Review environment variables](#review-environment-variables).
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. Make sure [the azure-sdk-for-go versions match](#check-go-dependencies) in [/test/go.mod](/test/go.mod) and in [test/azure/terraform_azure_aci_example_test.go](/test/azure/terraform_azure_aci_example_test.go).
1. `go build terraform_azure_aci_example_test.go`
1. `go test -v -run TestTerraformAzureACIExample`

## Check Go Dependencies

Check that the `github.com/Azure/azure-sdk-for-go` version in your generated `go.mod` for this test matches the version in the terratest [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) file.

> This was tested with **go1.14.1**.

### Check Azure-sdk-for-go version

Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v38.1.0):

```go
require (
...
github.com/Azure/azure-sdk-for-go v38.1.0+incompatible
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump to 46

...
)
```

If we make changes to either the **go.mod** or the **go test file**, we should make sure that the go build command works still.

```powershell
go build terraform_azure_aci_example_test.go
```

## Review Environment Variables

As part of configuring terraform for Azure, we'll want to check that we have set the appropriate [credentials](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/en-us/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-environment-variables) on the testing host.

```bash
export ARM_CLIENT_ID=your_app_id
export ARM_CLIENT_SECRET=your_password
export ARM_SUBSCRIPTION_ID=your_subscription_id
export ARM_TENANT_ID=your_tenant_id
```

Note, in a Windows environment, these should be set as **system environment variables**. We can use a PowerShell console with administrative rights to update these environment variables:

```powershell
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine)
```
55 changes: 55 additions & 0 deletions examples/azure/terraform-azure-aci-example/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# ---------------------------------------------------------------------------------------------------------------------
# DEPLOY AN AZURE CONTAINER REGISTRY
# This is an example of how to deploy an Azure Container Registry
# ---------------------------------------------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
# CONFIGURE OUR AZURE CONNECTION
# ------------------------------------------------------------------------------

provider "azurerm" {
version = "=2.22.0"
features {}
}

# ---------------------------------------------------------------------------------------------------------------------
# DEPLOY A RESOURCE GROUP
# ---------------------------------------------------------------------------------------------------------------------

resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.location
}

# ---------------------------------------------------------------------------------------------------------------------
# DEPLOY AN AZURE CONTAINER INSTANCE
# ---------------------------------------------------------------------------------------------------------------------

data "azurerm_client_config" "current" {
}

resource "azurerm_container_group" "aci" {
name = var.aci_name
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name

ip_address_type = "public"
dns_name_label = var.aci_name
os_type = "Linux"

container {
name = "hello-world"
image = "microsoft/aci-helloworld:latest"
cpu = "0.5"
memory = "1.5"

ports {
port = 443
protocol = "TCP"
}
}

tags = {
Environment = "Development"
}
}
11 changes: 11 additions & 0 deletions examples/azure/terraform-azure-aci-example/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "ip_address" {
value = azurerm_container_group.aci.ip_address
}

output "fqdn" {
value = azurerm_container_group.aci.fqdn
}

output "subscription_id" {
value = data.azurerm_client_config.current.subscription_id
}
31 changes: 31 additions & 0 deletions examples/azure/terraform-azure-aci-example/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ---------------------------------------------------------------------------------------------------------------------
# REQUIRED PARAMETERS
# You must provide a value for each of these parameters.
# ---------------------------------------------------------------------------------------------------------------------

variable "client_id" {
description = "The Service Principal Client Id for AKS to modify Azure resources."
}
variable "client_secret" {
description = "The Service Principal Client Password for AKS to modify Azure resources."
}

# ---------------------------------------------------------------------------------------------------------------------
# OPTIONAL PARAMETERS
# These parameters have reasonable defaults.
# ---------------------------------------------------------------------------------------------------------------------

variable "aci_name" {
description = "The name to set for the ACI."
default = "acitest"
}

variable "resource_group_name" {
description = "The name to set for the resource group."
default = "aci-rg"
}

variable "location" {
description = "The location to set for the ACR."
default = "Central US"
}
46 changes: 46 additions & 0 deletions modules/azure/aci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package azure

import (
"context"
"testing"

"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"

"github.com/stretchr/testify/require"
)

// GetACIClient is a helper function that will setup an Azure Container Instances client on your behalf
// resourceName - required to find the Function App
// resGroupName - use an empty string if you have the AZURE_RES_GROUP_NAME environment variable set
// subscriptionId - use an empty string if you have the ARM_SUBSCRIPTION_ID environment variable set
func GetACIClient(t *testing.T, resourceName string, resGroupName string, subscriptionID string) *containerinstance.ContainerGroup {
resource, err := getACIClientE(resourceName, resGroupName, subscriptionID)

require.NoError(t, err)

return resource
}

func getACIClientE(resourceName string, resGroupName string, subscriptionID string) (*containerinstance.ContainerGroup, error) {
// Validate Azure subscription ID
subscriptionID, err := getTargetAzureSubscription(subscriptionID)
if err != nil {
return nil, err
}

managedServicesClient := containerinstance.NewContainerGroupsClient(subscriptionID)
authorizer, err := NewAuthorizer()

if err != nil {
return nil, err
}

managedServicesClient.Authorizer = *authorizer

resource, err := managedServicesClient.Get(context.Background(), resGroupName, resourceName)
if err != nil {
return nil, err
}

return &resource, nil
}
50 changes: 50 additions & 0 deletions test/azure/terraform_azure_aci_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// +build azure

// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for
// CircleCI.

package test

import (
"fmt"
"strings"

"testing"

"github.com/gruntwork-io/terratest/modules/azure"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)

func TestTerraformAzureACIExample(t *testing.T) {
t.Parallel()

_random := strings.ToLower(random.UniqueId())

expectedResourceName := fmt.Sprintf("tmpaci%s", _random)
expectedResourceGroupName := fmt.Sprintf("tmp-rg-%s", _random)

terraformOptions := &terraform.Options{
TerraformDir: "../../examples/terraform-azure-aci-example",
Vars: map[string]interface{}{
"aci_name": expectedResourceName,
"resource_group_name": expectedResourceGroupName,
},
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)

// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)

client := azure.GetACIClient(t, expectedResourceName, expectedResourceGroupName, "")

assert := assert.New(t)

assert.NotEmpty(*client.Name)

assert.NotEmpty(*client.IPAddress.Fqdn)

assert.NotEmpty(*client.IPAddress.IP)
}