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

virtual network manager - New Terraform Template - Quickstart Create virtual network manager with Management Group Scope #298

Merged
merged 4 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Create the Resource Group

resource "random_pet" "rg_name" {
prefix = var.resource_group_name_prefix
}

resource "azurerm_resource_group" "rg" {
location = var.resource_group_location
name = random_pet.rg_name.id
mbender-ms marked this conversation as resolved.
Show resolved Hide resolved
}

# Create three virtual networks
resource "random_string" "prefix" {
length = 4
special = false
upper = false
}

resource "random_pet" "virtual_network_name" {
prefix = "vnet-${random_string.prefix.result}"
}
resource "azurerm_virtual_network" "vnet" {
count = 3

name = "${random_pet.virtual_network_name.id}-0${count.index}"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
address_space = ["10.${count.index}.0.0/16"]
}

# Add a subnet to each virtual network

resource "azurerm_subnet" "subnet_vnet" {
count = 3

name = "default"
virtual_network_name = azurerm_virtual_network.vnet[count.index].name
resource_group_name = azurerm_resource_group.rg.name
address_prefixes = ["10.${count.index}.0.0/24"]
}

data "azurerm_subscription" "current" {
}

# Create a Management Group

resource "random_pet" "management_group_name" {
prefix = "AVNM-management-group"
}

resource "azurerm_management_group" "mg" {
display_name = random_pet.management_group_name.id

subscription_ids = [
data.azurerm_subscription.current.subscription_id,
]
}

data "azurerm_client_config" "this" {}

resource "azurerm_role_assignment" "management_group_owner" {
principal_id = coalesce(var.msi_id, data.azurerm_client_config.this.object_id)
scope = azurerm_management_group.mg.id
role_definition_name = "Contributor"
}

# register Microsoft.Network to the Management Group

resource "null_resource" "register_rp_to_mg" {
provisioner "local-exec" {
command = "az provider register --namespace Microsoft.Network -m ${azurerm_management_group.mg.name}"
}
depends_on = [azurerm_role_assignment.management_group_owner]
}

resource "time_sleep" "wait_5_seconds" {
create_duration = "5s"
depends_on = [null_resource.register_rp_to_mg]
}

# Create a Virtual Network Manager instance

resource "azurerm_network_manager" "network_manager_instance" {
name = "network-manager"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
scope_accesses = ["Connectivity"]
description = "example network manager"
scope {
management_group_ids = [azurerm_management_group.mg.id]
}
depends_on = [time_sleep.wait_5_seconds]
}

# Create a network group

resource "azurerm_network_manager_network_group" "network_group" {
name = "network-group"
network_manager_id = azurerm_network_manager.network_manager_instance.id
}

# Add three virtual networks to a network group as dynamic members with Azure Policy

resource "random_pet" "network_group_policy_name" {
prefix = "network-group-policy"
}

resource "azurerm_policy_definition" "network_group_policy" {
name = random_pet.network_group_policy_name.id
policy_type = "Custom"
mode = "Microsoft.Network.Data"
display_name = "Policy Definition for Network Group"

metadata = <<METADATA
{
"category": "Azure Virtual Network Manager"
}
METADATA

policy_rule = <<POLICY_RULE
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"allOf": [
{
"field": "Name",
"contains": "${random_pet.virtual_network_name.id}"
}
]
}
]
},
"then": {
"effect": "addToNetworkGroup",
"details": {
"networkGroupId": "${azurerm_network_manager_network_group.network_group.id}"
}
}
}
POLICY_RULE
}

resource "azurerm_subscription_policy_assignment" "azure_policy_assignment" {
name = "${random_pet.network_group_policy_name.id}-policy-assignment"
policy_definition_id = azurerm_policy_definition.network_group_policy.id
subscription_id = data.azurerm_subscription.current.id
}

# Create a connectivity configuration

resource "azurerm_network_manager_connectivity_configuration" "connectivity_config" {
name = "connectivity-config"
network_manager_id = azurerm_network_manager.network_manager_instance.id
connectivity_topology = "Mesh"
applies_to_group {
group_connectivity = "None"
network_group_id = azurerm_network_manager_network_group.network_group.id
}
}


# Commit deployment

resource "azurerm_network_manager_deployment" "commit_deployment" {
network_manager_id = azurerm_network_manager.network_manager_instance.id
location = azurerm_resource_group.rg.location
scope_access = "Connectivity"
configuration_ids = [azurerm_network_manager_connectivity_configuration.connectivity_config.id]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
output "resource_group_name" {
value = azurerm_resource_group.rg.name
}

output "virtual_network_names" {
value = azurerm_virtual_network.vnet[*].name
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
terraform {
required_version = ">=1.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.56.0, < 4.0"
}
random = {
source = "hashicorp/random"
version = "~>3.0"
}
}
}
provider "azurerm" {
features {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Azure Virtual Network Manager with management group scope

This template deploys an Azure Virtual Network Manager instance with a connectivity configuration for a Mesh topology using a management group scope. It includes resources including virtual networks, subnets, and more.

## Terraform resource types

- [random_pet](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet)
- [random_string](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string)
- [azurerm_resource_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group)
- [azurerm_virtual_network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network)
- [azurerm_subnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet)
- [azurerm_virtual_network_manager](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_manager)
- [azurerm_network_manager_network_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_manager_network_group)
- [azurerm_policy_definition](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/policy_definition)
- [azurerm_subscription_policy_assignment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subscription_policy_assignment)
- [azurerm_network_manager_connectivity_configuration](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_manager_connectivity_configuration)
- [azurerm_network_manager_deployment](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_manager_deployment)
- [azurerm_management_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/management_group)

## Variables

| **Name** | **Description** | **Default** |
|---|---|---|
| `resource_group_name_prefix` | Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription. | rg |
| `resource_group_location` | Location of the resource group. | eastus |

## Example

To see how to run this example, see [Quickstart: Deploy a Virtual Network Manager in Azure using Terraform](https://learn.microsoft.com/azure/virtual-network-manager/create-virtual-network-manager-terraform).
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
variable "resource_group_location" {
type = string
default = "eastus"
description = "Location of the resource group."
}

variable "resource_group_name_prefix" {
type = string
description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
default = "rg"
}

variable "msi_id" {
type = string
description = "(Optional) Manage identity id that be used as authentication method. Defaults to `null`."
default = null
}
11 changes: 11 additions & 0 deletions test/e2e/discard_writer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package e2e

import "io"

var discardWriter io.Writer = discard{}

type discard struct{}

func (d discard) Write(p []byte) (n int, err error) {
return len(p), nil
}
34 changes: 33 additions & 1 deletion test/e2e/quickstart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package e2e
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
Expand All @@ -17,7 +18,8 @@ import (
)

var speicalTests = map[string]func(*testing.T){
"quickstart/201-vmss-packer-jumpbox": test201VmssPackerJumpbox,
"quickstart/201-vmss-packer-jumpbox": test201VmssPackerJumpbox,
"quickstart/101-virtual-network-manager-create-management-group-scope": test101VirtualNetworkManagerCreateManagementGroupScope,
}

func Test_Quickstarts(t *testing.T) {
Expand Down Expand Up @@ -141,6 +143,36 @@ func test201VmssPackerJumpbox(t *testing.T) {
}, nil)
}

func test101VirtualNetworkManagerCreateManagementGroupScope(t *testing.T) {
rootPath := filepath.Join("..", "..")
f := filepath.Join("quickstart", "101-virtual-network-manager-create-management-group-scope")
tenantId := os.Getenv("ARM_TENANT_ID")
clientId := os.Getenv("ARM_CLIENT_ID")
clientSecret := os.Getenv("ARM_CLIENT_SECRET")
msiId := os.Getenv("MSI_ID")
var cmd *exec.Cmd
if tenantId != "" && clientId != "" && clientSecret != "" {
cmd = exec.Command("az", "login", "--service-principal", "-u", clientId, "-p", clientSecret, "--tenant", tenantId)
err := cmd.Run()
require.NoError(t, err, "cannot login via service principal: %+v", err)
} else if msiId != "" {
cmd = exec.Command("az", "login", "--identity", "--username", msiId)
err := cmd.Run()
require.NoError(t, err, "cannot login via identity: %+v", err)
} else {
t.Fatalf("To test `quickstart/101-virtual-network-manager-create-management-group-scope` you must set `ARM_TENANT_ID`, `ARM_CLIENT_ID`, `ARM_CLIENT_SECRET`, or set `MSI_ID` so we can run `az login`.")
}
cmd.Stdout = discardWriter
defer func() {
cmd := exec.Command("az", "logout")
cmd.Stdout = discardWriter
_ = cmd.Run()
}()
helper.RunE2ETest(t, rootPath, f, terraform.Options{
Upgrade: true,
}, nil)
}

func removeDuplicates(s []string) []string {
m := make(map[string]struct{})
result := []string{}
Expand Down