Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adding Azure Recovery Services module (#640)
* recovery services module * update doc and comments * chg terraform prefix for resources * move unit test * rm azure ref * rm var for policy * refactor test vars * refactor test vars * update mod ex * comments * revert * rm space * add comment * update nits * per pr * return empty map * map unit test to fault * fix 4 linter * move comments * refactor exists * minor edits * switch return from empty map to nil in error condition. Co-authored-by: wmattlong <malong@microsoft.com> Co-authored-by: richard guthrie <richardguthrie@MININT-A10U6Q6.fareast.corp.microsoft.com> Co-authored-by: richard guthrie <richardguthrie@MacBook-Pro.local>
- Loading branch information
1 parent
f178b8d
commit b13ada2
Showing
7 changed files
with
399 additions
and
0 deletions.
There are no files selected for viewing
40 changes: 40 additions & 0 deletions
40
examples/azure/terraform-azure-recoveryservices-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,40 @@ | ||
# Terraform Azure Recovery Services 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 a Recovery Services Vault with one backup virtual machine policy. | ||
|
||
- A [Recovery Services](https://azure.microsoft.com/services/backup/) that gives the module the following: | ||
- [Backup Vault](https://docs.microsoft.com/azure/backup/backup-azure-recovery-services-vault-overview) with the value specified in the `recovery_service_vault_name` output variable. | ||
- [Backup VM Policy](https://azure.microsoft.com/en-in/updates/azure-vm-backup-policy-management/) with the value specified in the `backup_policy_vm_name` output variable. | ||
|
||
Check out [test/azure/terraform_azure_recoveryservices_example_test.go](/test/azure/terraform_azure_recoveryservices_example_test.go) to see how you can write | ||
automated tests for this module. | ||
|
||
Note that the Recovery Services Vault and backup virtual machine policy in this module don't actually do anything; it just runs the resources for | ||
demonstration purposes. | ||
|
||
**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/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. Configure your Terratest [Go test environment](../README.md) | ||
1. `cd test/azure` | ||
1. `go build terraform_azure_recoveryservices_example_test.go` | ||
1. `go test -v -run TestTerraformAzureRecoveryServicesExample` |
78 changes: 78 additions & 0 deletions
78
examples/azure/terraform-azure-recoveryservices-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,78 @@ | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY AN AZURE AVAILABILITY SET | ||
# This is an example of how to deploy an Azure Availability Set with a Virtual Machine in the availability set | ||
# and the minimum network resources for the VM. | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
# See test/azure/terraform_azure_availabilityset_example_test.go for how to write automated tests for this code. | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
provider "azurerm" { | ||
version = "~> 2.20" | ||
features {} | ||
} | ||
|
||
terraform { | ||
# This module is now only being tested with Terraform 0.13.x. However, to make upgrading easier, we are setting | ||
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it | ||
# forwards compatible with 0.13.x code. | ||
required_version = ">= 0.12.26" | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY A RESOURCE GROUP | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_resource_group" "resource_group" { | ||
name = "terratest-ars-rg-${var.postfix}" | ||
location = var.location | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY A RECOVERY SERVICES VAULT | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_recovery_services_vault" "vault" { | ||
name = "rsvault${var.postfix}" | ||
location = azurerm_resource_group.resource_group.location | ||
resource_group_name = azurerm_resource_group.resource_group.name | ||
sku = "Standard" | ||
} | ||
|
||
# --------------------------------------------------------------------------------------------------------------------- | ||
# DEPLOY A BACKUP POLICY | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
|
||
resource "azurerm_backup_policy_vm" "vm_policy" { | ||
name = "vmpolicy-${var.postfix}" | ||
resource_group_name = azurerm_resource_group.resource_group.name | ||
recovery_vault_name = azurerm_recovery_services_vault.vault.name | ||
|
||
timezone = "UTC" | ||
|
||
backup { | ||
frequency = "Daily" | ||
time = "23:00" | ||
} | ||
|
||
retention_daily { | ||
count = 10 | ||
} | ||
|
||
retention_weekly { | ||
count = 42 | ||
weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] | ||
} | ||
|
||
retention_monthly { | ||
count = 7 | ||
weekdays = ["Sunday", "Wednesday"] | ||
weeks = ["First", "Last"] | ||
} | ||
|
||
retention_yearly { | ||
count = 77 | ||
weekdays = ["Sunday"] | ||
weeks = ["Last"] | ||
months = ["January"] | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
examples/azure/terraform-azure-recoveryservices-example/outputs.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,11 @@ | ||
output "resource_group_name" { | ||
value = azurerm_resource_group.resource_group.name | ||
} | ||
|
||
output "recovery_service_vault_name" { | ||
value = azurerm_recovery_services_vault.vault.name | ||
} | ||
|
||
output "backup_policy_vm_name" { | ||
value = azurerm_backup_policy_vm.vm_policy.name | ||
} |
33 changes: 33 additions & 0 deletions
33
examples/azure/terraform-azure-recoveryservices-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,33 @@ | ||
# --------------------------------------------------------------------------------------------------------------------- | ||
# 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 location to set for the storage account." | ||
type = string | ||
default = "East US" | ||
} | ||
|
||
variable "postfix" { | ||
description = "A postfix string to centrally mitigate resource name collisions" | ||
type = string | ||
default = "resource" | ||
} | ||
|
||
|
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,151 @@ | ||
package azure | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2016-06-01/recoveryservices" | ||
"github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2020-02-02/backup" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// RecoveryServicesVaultExists indicates whether a recovery services vault exists; otherwise false. | ||
// This function would fail the test if there is an error. | ||
func RecoveryServicesVaultExists(t *testing.T, vaultName, resourceGroupName, subscriptionID string) bool { | ||
exists, err := RecoveryServicesVaultExistsE(vaultName, resourceGroupName, subscriptionID) | ||
require.NoError(t, err) | ||
return exists | ||
} | ||
|
||
// GetRecoveryServicesVaultBackupPolicyList returns a list of backup policies for the given vault. | ||
// This function would fail the test if there is an error. | ||
func GetRecoveryServicesVaultBackupPolicyList(t *testing.T, vaultName, resourceGroupName, subscriptionID string) map[string]backup.ProtectionPolicyResource { | ||
list, err := GetRecoveryServicesVaultBackupPolicyListE(vaultName, resourceGroupName, subscriptionID) | ||
require.NoError(t, err) | ||
return list | ||
} | ||
|
||
// GetRecoveryServicesVaultBackupProtectedVMList returns a list of protected VM's on the given vault/policy. | ||
// This function would fail the test if there is an error. | ||
func GetRecoveryServicesVaultBackupProtectedVMList(t *testing.T, policyName, vaultName, resourceGroupName, subscriptionID string) map[string]backup.AzureIaaSComputeVMProtectedItem { | ||
list, err := GetRecoveryServicesVaultBackupProtectedVMListE(policyName, vaultName, resourceGroupName, subscriptionID) | ||
require.NoError(t, err) | ||
return list | ||
} | ||
|
||
// RecoveryServicesVaultExists indicates whether a recovery services vault exists; otherwise false or error. | ||
func RecoveryServicesVaultExistsE(vaultName, resourceGroupName, subscriptionID string) (bool, error) { | ||
_, err := GetRecoveryServicesVaultE(vaultName, resourceGroupName, subscriptionID) | ||
if err != nil { | ||
if ResourceNotFoundErrorExists(err) { | ||
return false, nil | ||
} | ||
return false, err | ||
} | ||
return true, nil | ||
} | ||
|
||
// GetRecoveryServicesVaultE returns a vault instance. | ||
func GetRecoveryServicesVaultE(vaultName, resourceGroupName, subscriptionID string) (*recoveryservices.Vault, error) { | ||
subscriptionID, err := getTargetAzureSubscription(subscriptionID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resourceGroupName, err2 := getTargetAzureResourceGroupName((resourceGroupName)) | ||
if err2 != nil { | ||
return nil, err2 | ||
} | ||
|
||
client := recoveryservices.NewVaultsClient(subscriptionID) | ||
// setup auth and create request params | ||
authorizer, err := NewAuthorizer() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
client.Authorizer = *authorizer | ||
vault, err := client.Get(context.Background(), resourceGroupName, vaultName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &vault, nil | ||
} | ||
|
||
// GetRecoveryServicesVaultBackupPolicyListE returns a list of backup policies for the given vault. | ||
func GetRecoveryServicesVaultBackupPolicyListE(vaultName, resourceGroupName, subscriptionID string) (map[string]backup.ProtectionPolicyResource, error) { | ||
subscriptionID, err := getTargetAzureSubscription(subscriptionID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resourceGroupName, err2 := getTargetAzureResourceGroupName(resourceGroupName) | ||
if err2 != nil { | ||
return nil, err2 | ||
} | ||
|
||
client := backup.NewPoliciesClient(subscriptionID) | ||
// setup authorizer | ||
authorizer, err := NewAuthorizer() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
client.Authorizer = *authorizer | ||
listIter, err := client.ListComplete(context.Background(), vaultName, resourceGroupName, "") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
policyMap := make(map[string]backup.ProtectionPolicyResource) | ||
for listIter.NotDone() { | ||
v := listIter.Value() | ||
policyMap[*v.Name] = v | ||
err := listIter.NextWithContext(context.Background()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
} | ||
return policyMap, nil | ||
} | ||
|
||
// GetRecoveryServicesVaultBackupProtectedVMListE returns a list of protected VM's on the given vault/policy. | ||
func GetRecoveryServicesVaultBackupProtectedVMListE(policyName, vaultName, resourceGroupName, subscriptionID string) (map[string]backup.AzureIaaSComputeVMProtectedItem, error) { | ||
subscriptionID, err := getTargetAzureSubscription(subscriptionID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resourceGroupName, err2 := getTargetAzureResourceGroupName(resourceGroupName) | ||
if err != nil { | ||
return nil, err2 | ||
} | ||
|
||
client := backup.NewProtectedItemsGroupClient(subscriptionID) | ||
// setup authorizer | ||
authorizer, err := NewAuthorizer() | ||
if err != nil { | ||
return nil, err | ||
} | ||
client.Authorizer = *authorizer | ||
// Build a filter string to narrow down results to just VM's | ||
filter := fmt.Sprintf("backupManagementType eq 'AzureIaasVM' and itemType eq 'VM' and policyName eq '%s'", policyName) | ||
listIter, err := client.ListComplete(context.Background(), vaultName, resourceGroupName, filter, "") | ||
if err != nil { | ||
return nil, err | ||
} | ||
// Prep the return container | ||
vmList := make(map[string]backup.AzureIaaSComputeVMProtectedItem) | ||
// First iterator check | ||
for listIter.NotDone() { | ||
currentVM, _ := listIter.Value().Properties.AsAzureIaaSComputeVMProtectedItem() | ||
vmList[*currentVM.FriendlyName] = *currentVM | ||
err := listIter.NextWithContext(context.Background()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
return vmList, 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,32 @@ | ||
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 methods to create and delete recovery services resources are added, these tests can be extended. | ||
*/ | ||
|
||
func TestRecoveryServicesVaultName(t *testing.T) { | ||
_, err := GetRecoveryServicesVaultE("", "", "") | ||
require.Error(t, err, "vault") | ||
} | ||
|
||
func TestRecoveryServicesVaultExists(t *testing.T) { | ||
_, err := RecoveryServicesVaultExistsE("", "", "") | ||
require.Error(t, err, "vault exists") | ||
} | ||
|
||
func TestRecoveryServicesVaultBackupPolicyList(t *testing.T) { | ||
_, err := GetRecoveryServicesVaultBackupPolicyListE("", "", "") | ||
require.Error(t, err, "Backup policy list not faulted") | ||
} | ||
|
||
func TestRecoveryServicesVaultBackupProtectedVMList(t *testing.T) { | ||
_, err := GetRecoveryServicesVaultBackupProtectedVMListE("", "", "", "") | ||
require.Error(t, err, "Backup policy protected vm list not faulted") | ||
} |
Oops, something went wrong.