-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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: add Azure FunctionApp Module #591
Merged
yorinasub17
merged 10 commits into
gruntwork-io:master
from
polatengin:feature/azure-functionapp
Jul 16, 2021
Merged
Changes from 9 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
e4f49e7
Azure FunctionApp Module
polatengin 70568ad
Merge remote-tracking branch 'upstream/master' into feature/azure-fun…
HadwaAbdelhalem 3a2ab69
Merge remote-tracking branch 'upstream/master' into feature/azure-fun…
HadwaAbdelhalem 3ccbbab
Update Azure fucntions example
HadwaAbdelhalem dbdc8e8
add appservice module and test
HadwaAbdelhalem 348ae77
update azurefunction test
HadwaAbdelhalem ca689ea
Merge branch 'gruntwork-io:master' into feature/azure-functionapp
HadwaAbdelhalem 49446d7
fix appservice_tests
HadwaAbdelhalem 365d8f2
fix TestGetAppServiceClientE test
HadwaAbdelhalem d7fea7a
fix typo
HadwaAbdelhalem File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
examples/azure/terraform-azure-functionapp-example/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Terraform Azure Function App Example | ||
|
||
This folder contains a Terraform module that deploys a Function App 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 [Azure Storage](https://azure.microsoft.com/en-us/services/storage/), [Azure Function App](https://azure.microsoft.com/en-us/services/functions/), [Azure Function App](https://azure.microsoft.com/en-us/services/functions/). | ||
|
||
Check out [test/azure/terraform_azure_functionapp_example_test.go](/test/azure/terraform_azure_functionapp_example_test.go) to see how you can write automated tests for this module and validate the configuration of the parameters and options. | ||
|
||
**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/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/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. Ensure [environment variables](../README.md#review-environment-variables) are available | ||
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/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. Configure your Terratest [Go test environment](../README.md) | ||
1. `cd test/azure` | ||
1. `go build terraform_azure_functionapp_example_test.go` | ||
1. `go test -v -run TestTerraformAzureFunctionAppExample` |
81 changes: 81 additions & 0 deletions
81
examples/azure/terraform-azure-functionapp-example/main.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
# Deploy an Azure storage account, service plan, function app, and application insights | ||
# This is an example of how to deploy an Azure function app. | ||
# See test/terraform_azure_functionapp_example_test.go for how to write automated tests for this code. | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# CONFIGURE OUR AZURE CONNECTION | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
provider "azurerm" { | ||
version = "~>2.29.0" | ||
features {} | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY THE RESOURCE GROUP | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_resource_group" "app_rg" { | ||
name = "terratest-functionapp-rg-${var.postfix}" | ||
location = var.location | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY THE AZURE STORAGE ACCOUNT | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_storage_account" "storage" { | ||
name = "storageaccount${var.postfix}" | ||
resource_group_name = azurerm_resource_group.app_rg.name | ||
location = azurerm_resource_group.app_rg.location | ||
account_tier = "Standard" | ||
account_replication_type = "LRS" | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY THE APP SERVICE PLAN | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_app_service_plan" "app_service_plan" { | ||
name = "appservice-plan-${var.postfix}" | ||
location = azurerm_resource_group.app_rg.location | ||
resource_group_name = azurerm_resource_group.app_rg.name | ||
kind = "FunctionApp" | ||
|
||
sku { | ||
tier = "Standard" | ||
size = "S1" | ||
} | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY THE APPLICATION INSIGHTS | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_application_insights" "application_insights" { | ||
name = "appinsights-${var.postfix}" | ||
location = azurerm_resource_group.app_rg.location | ||
resource_group_name = azurerm_resource_group.app_rg.name | ||
application_type = "web" | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY THE AZURE FUNCTION APP | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_function_app" "function_app" { | ||
name = "functionapp-${var.postfix}" | ||
location = azurerm_resource_group.app_rg.location | ||
resource_group_name = azurerm_resource_group.app_rg.name | ||
app_service_plan_id = azurerm_app_service_plan.app_service_plan.id | ||
storage_account_name = azurerm_storage_account.storage.name | ||
storage_account_access_key = azurerm_storage_account.storage.primary_access_key | ||
|
||
|
||
app_settings = { | ||
"APPINSIGHTS_INSTRUMENTATIONKEY" = azurerm_application_insights.application_insights.instrumentation_key | ||
"APPLICATIONINSIGHTS_CONNECTION_STRING" = "InstrumentationKey=${azurerm_application_insights.application_insights.instrumentation_key}" | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
examples/azure/terraform-azure-functionapp-example/output.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
output "resource_group_name" { | ||
value = azurerm_resource_group.app_rg.name | ||
} | ||
|
||
output "function_app_id" { | ||
value = azurerm_function_app.function_app.id | ||
} | ||
|
||
output "default_hostname" { | ||
value = azurerm_function_app.function_app.default_hostname | ||
} | ||
|
||
output "function_app_kind" { | ||
value = azurerm_function_app.function_app.kind | ||
} | ||
|
||
output "function_app_name" { | ||
value = azurerm_function_app.function_app.name | ||
} |
31 changes: 31 additions & 0 deletions
31
examples/azure/terraform-azure-functionapp-example/variables.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
# ENVIRONMENT VARIABLES | ||
# Define these secrets as environment variables | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
# ARM_CLIENT_ID | ||
# ARM_CLIENT_SECRET | ||
# ARM_SUBSCRIPTION_ID | ||
# ARM_TENANT_ID | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# REQUIRED PARAMETERS | ||
# You must provide a value for each of these parameters. | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# OPTIONAL PARAMETERS | ||
# These parameters have reasonable defaults. | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
variable "location" { | ||
description = "The supported azure location where the resource exists" | ||
type = string | ||
default = "West US2" | ||
} | ||
|
||
variable "postfix" { | ||
description = "A postfix string to centrally mitigate resource name collisions." | ||
type = string | ||
default = "1276" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package azure | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2019-08-01/web" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// AppExistsE indicates whether the specified application exists. | ||
// This function would fail the test if there is an error. | ||
func AppExists(t *testing.T, appName string, resourceGroupName string, subscriptionID string) bool { | ||
exists, err := AppExistsE(appName, resourceGroupName, subscriptionID) | ||
require.NoError(t, err) | ||
|
||
return exists | ||
} | ||
|
||
// AppExistsE indicates whether the specified application exists. | ||
func AppExistsE(appName string, resourceGroupName string, subscriptionID string) (bool, error) { | ||
_, err := GetAppServiceE(appName, resourceGroupName, subscriptionID) | ||
if err != nil { | ||
if ResourceNotFoundErrorExists(err) { | ||
return false, nil | ||
} | ||
return false, err | ||
} | ||
return true, nil | ||
} | ||
|
||
// GetAppService gets the App service object | ||
// This function would fail the test if there is an error. | ||
func GetAppService(t *testing.T, appName string, resGroupName string, subscriptionID string) *web.Site { | ||
site, err := GetAppServiceE(appName, resGroupName, subscriptionID) | ||
require.NoError(t, err) | ||
|
||
return site | ||
} | ||
|
||
// GetAppServiceE gets the App service object | ||
func GetAppServiceE(appName string, resGroupName string, subscriptionID string) (*web.Site, error) { | ||
rgName, err := getTargetAzureResourceGroupName(resGroupName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
client, err := GetAppServiceClientE(subscriptionID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resource, err := client.Get(context.Background(), rgName, appName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &resource, nil | ||
} | ||
|
||
func GetAppServiceClientE(subscriptionID string) (*web.AppsClient, error) { | ||
// Create an Apps client | ||
appsClient, err := CreateAppServiceClientE(subscriptionID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Create an authorizer | ||
authorizer, err := NewAuthorizer() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Attach authorizer to the client | ||
appsClient.Authorizer = *authorizer | ||
return appsClient, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// +build azure | ||
|
||
// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for | ||
// CircleCI. | ||
|
||
package azure | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
/* | ||
The below tests are currently stubbed out, with the expectation that they will throw errors. | ||
If/when CRUD methods are introduced for Azure MySQL server and database, these tests can be extended | ||
*/ | ||
|
||
func TestAppExistsE(t *testing.T) { | ||
t.Parallel() | ||
|
||
resGroupName := "" | ||
appName := "" | ||
subscriptionID := "" | ||
|
||
_, err := AppExistsE(appName, resGroupName, subscriptionID) | ||
require.Error(t, err) | ||
} | ||
|
||
func TestGetAppServiceE(t *testing.T) { | ||
t.Parallel() | ||
|
||
resGroupName := "" | ||
appName := "" | ||
subscriptionID := "" | ||
|
||
_, err := GetAppServiceE(appName, resGroupName, subscriptionID) | ||
require.Error(t, err) | ||
} | ||
|
||
func TestGetAppServiceClientE(t *testing.T) { | ||
t.Parallel() | ||
|
||
subscriptionID := "" | ||
|
||
_, err := GetAppServiceClientE(subscriptionID) | ||
require.NoError(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// +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 ( | ||
"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 TestTerraformAzureFunctionAppExample(t *testing.T) { | ||
t.Parallel() | ||
|
||
//_random := strings.ToLower(random.UniqueId()) | ||
uniquePostfix := strings.ToLower(random.UniqueId()) | ||
|
||
// website::tag::1:: Configure Terraform setting up a path to Terraform code. | ||
terraformOptions := &terraform.Options{ | ||
TerraformDir: "../../examples/azure/terraform-azure-functionapp-example", | ||
Vars: map[string]interface{}{ | ||
"postfix": uniquePostfix, | ||
}, | ||
} | ||
// website::tag::5:: At the end of the test, run `terraform destroy` to clean up any resources that were created | ||
defer terraform.Destroy(t, terraformOptions) | ||
|
||
// website::tag::2:: Run `terraform init` and `terraform apply`. Fail the test if there are any errors. | ||
terraform.InitAndApply(t, terraformOptions) | ||
|
||
// website::tag::3:: Run `terraform output` to get the values of output variables | ||
resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") | ||
appName := terraform.Output(t, terraformOptions, "function_app_name") | ||
|
||
appId := terraform.Output(t, terraformOptions, "function_app_id") | ||
appDefaultHostName := terraform.Output(t, terraformOptions, "default_hostname") | ||
appKind := terraform.Output(t, terraformOptions, "function_app_kind") | ||
|
||
// website::tag::4:: Assert | ||
assert.True(t, azure.AppExists(t, appName, resourceGroupName, "")) | ||
site := azure.GetAppService(t, appName, resourceGroupName, "") | ||
|
||
assert.Equal(t, appId, *site.ID) | ||
assert.Equal(t, appDefaultHostName, *site.DefaultHostName) | ||
assert.Equal(t, appKind, *site.Kind) | ||
|
||
assert.NotEmpty(t, *site.OutboundIPAddresses) | ||
assert.Equal(t, "Running", *site.State) | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed