Skip to content

Commit

Permalink
Merge pull request #14 from pablo19sc/main
Browse files Browse the repository at this point in the history
Adding aws_networkmanager_core_network_policy_attachment resource and base_policy attribute
  • Loading branch information
pablo19sc authored Mar 4, 2023
2 parents b9bd88e + f369ed3 commit b1838b6
Show file tree
Hide file tree
Showing 24 changed files with 326 additions and 141 deletions.
69 changes: 16 additions & 53 deletions .header.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ The example below builds a Network Manager Global Network and a Cloud WAN Core N

```hcl
module "cloudwan" {
source = "aws-ia/cloudwan"
source = "aws-ia/cloudwan/aws"
version = "2.x.x"
global_network = {
create = true
Expand All @@ -29,7 +30,8 @@ If you already have a Network Manager Global Network created, you can pass the I

```hcl
module "cloudwan" {
source = "aws-ia/cloudwan/aws"
source = "aws-ia/cloudwan/aws"
version = "2.x.x"
global_network = {
create = false
Expand Down Expand Up @@ -92,62 +94,23 @@ data "aws_networkmanager_core_network_policy_document" "policy" {
}
```

## What if I was using a version 0.x?
## When do I need to create the *base_policy*?

If you are using a version 0.x of this module and want to move to a version 1.x, you will find that we have migrated from using the [AWSCC]() provider to [AWS]() provider for the Global and Core Network resources. If you want to udpate the version without re-creating the resources, you need to proceed as follows:
You will see that one of the attributes of the Core Network is *base_policy_regions*, that it is used in the module to define the *base_policy* and *base_policy_regions* attributes in the `aws_networkmanager_core_network` resource. But... why do we need the *base_policy*?

* First, add in your main.tf (or similar file) a new module definition. In this new definition you need to pass the current Global Network without creating a new one.
First of all, let's start explaining why we use the `aws_networkmanager_core_network_policy_attachment` resource. When adding an inspection layer to AWS Cloud WAN, a static route is needed - from any of the segments pointing to an Inspection VPC. As you need to reference the attachmend ID of the Inspection VPC(s), a circular dependency is created. To avoid this circular dependency, the `aws_networkmanager_core_network_policy_attachment` was created to decouple the creation of the Core Network to the policy document attachment, so when you deploy from scratch your architecture it proceeds as follows:

```hcl
module "cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "0.x"
* Creation of Global Network (if not done already) and Core Network.
* Creation of Core Network attachments.
* Attachment of the policy document - generation of the network.

global_network = {
create = true
description = "Global Network - AWS CloudWAN Module"
}
core_network = {
description = "Core Network - AWS CloudWAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
}
**Important to note** that to get this behaviour you need to use the `aws_networkmanager_core_network_policy_document` data source.

tags = {
Name = "create-global-network"
}
}
However, there's still one challenge to overcome: you cannot attach resources to the Core Network without an active policy. And it makes sense, as in the policy you indicate the AWS Regions in which you want to create CNEs (Core Network Edges). Without policy, there are no CNEs and it's impossible to attach anything. Here is where *base_policy* is going to help us: a temporal policy document is generated (in the AWS Regions you indicate in *base_policy_regions*) so the attachments can be created before applying the policy document where you reference some of those attachment IDs.

module "new_cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "1.x"
**What happens when adding new attachments to a current Core Network with a live policy?** If any of these attachmens are referenced in the policy document, those are going to be created first and then the policy is going to be updated. The *base_policy* attribute won't do anything, as there's a current live policy - we don't need this temporal policy.

global_network = {
create = false
id = "global-network-XXX"
}
core_network = {
description = "Core Network - AWS CloudWAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
}
tags = {
Name = "create-global-network"
}
}
```

* Next, do a Terraform import for the new Global and Core Network resources.

```
terraform import module.new_cloudwan.aws_networkmanager_global_network.global_network[0] global-network-XXX
terraform import module.new_cloudwan.aws_networkmanager_core_network.core_network core-network-XXX
```

* Now you can remove from the Terraform state the old resources

```
terraform state rm module.cloudwan.awscc_networkmanager_global_network.global_network[0]
terraform state rm module.new_cloudwan.awscc_networkmanager_core_network.core_network
```
**What happens when adding new AWS Regions to a current Core Network with a live policy?** The *base_policy* won't help us here, as creating a temporal policy with the new AWS Region will create a network disruption - as we already have a network configuration applied. That's why, when adding new AWS Regions, we need a two-step deployment:

* Finally, you can remove the definition of the old module (the one using version 0.x) from your main.tf file (or similar)
* Step 1: Update and apply the policy document with the new AWS Region(s).
* Step 2: Create the new attachment(s) and update the policy document if any static route is needed.
3 changes: 2 additions & 1 deletion .terraform-docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ settings:
required: true
sensitive: true
type: true
lockfile: false

sort:
enabled: true
by: required

output:
file: README.md
mode: replace
mode: replace
78 changes: 21 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ The example below builds a Network Manager Global Network and a Cloud WAN Core N

```hcl
module "cloudwan" {
source = "aws-ia/cloudwan"
source = "aws-ia/cloudwan/aws"
version = "2.x.x"
global_network = {
create = true
Expand All @@ -30,7 +31,8 @@ If you already have a Network Manager Global Network created, you can pass the I

```hcl
module "cloudwan" {
source = "aws-ia/cloudwan/aws"
source = "aws-ia/cloudwan/aws"
version = "2.x.x"
global_network = {
create = false
Expand Down Expand Up @@ -93,78 +95,39 @@ data "aws_networkmanager_core_network_policy_document" "policy" {
}
```

## What if I was using a version 0.x?
## When do I need to create the *base\_policy*?

If you are using a version 0.x of this module and want to move to a version 1.x, you will find that we have migrated from using the [AWSCC]() provider to [AWS]() provider for the Global and Core Network resources. If you want to udpate the version without re-creating the resources, you need to proceed as follows:
You will see that one of the attributes of the Core Network is *base\_policy\_regions*, that it is used in the module to define the *base\_policy* and *base\_policy\_regions* attributes in the `aws_networkmanager_core_network` resource. But... why do we need the *base\_policy*?

* First, add in your main.tf (or similar file) a new module definition. In this new definition you need to pass the current Global Network without creating a new one.
First of all, let's start explaining why we use the `aws_networkmanager_core_network_policy_attachment` resource. When adding an inspection layer to AWS Cloud WAN, a static route is needed - from any of the segments pointing to an Inspection VPC. As you need to reference the attachmend ID of the Inspection VPC(s), a circular dependency is created. To avoid this circular dependency, the `aws_networkmanager_core_network_policy_attachment` was created to decouple the creation of the Core Network to the policy document attachment, so when you deploy from scratch your architecture it proceeds as follows:

```hcl
module "cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "0.x"
* Creation of Global Network (if not done already) and Core Network.
* Creation of Core Network attachments.
* Attachment of the policy document - generation of the network.

global_network = {
create = true
description = "Global Network - AWS CloudWAN Module"
}
core_network = {
description = "Core Network - AWS CloudWAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
}
**Important to note** that to get this behaviour you need to use the `aws_networkmanager_core_network_policy_document` data source.

tags = {
Name = "create-global-network"
}
}
However, there's still one challenge to overcome: you cannot attach resources to the Core Network without an active policy. And it makes sense, as in the policy you indicate the AWS Regions in which you want to create CNEs (Core Network Edges). Without policy, there are no CNEs and it's impossible to attach anything. Here is where *base\_policy* is going to help us: a temporal policy document is generated (in the AWS Regions you indicate in *base\_policy\_regions*) so the attachments can be created before applying the policy document where you reference some of those attachment IDs.

module "new_cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "1.x"
**What happens when adding new attachments to a current Core Network with a live policy?** If any of these attachmens are referenced in the policy document, those are going to be created first and then the policy is going to be updated. The *base\_policy* attribute won't do anything, as there's a current live policy - we don't need this temporal policy.

global_network = {
create = false
id = "global-network-XXX"
}
core_network = {
description = "Core Network - AWS CloudWAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
}
tags = {
Name = "create-global-network"
}
}
```

* Next, do a Terraform import for the new Global and Core Network resources.

```
terraform import module.new_cloudwan.aws_networkmanager_global_network.global_network[0] global-network-XXX
terraform import module.new_cloudwan.aws_networkmanager_core_network.core_network core-network-XXX
```

* Now you can remove from the Terraform state the old resources

```
terraform state rm module.cloudwan.awscc_networkmanager_global_network.global_network[0]
terraform state rm module.new_cloudwan.awscc_networkmanager_core_network.core_network
```
**What happens when adding new AWS Regions to a current Core Network with a live policy?** The *base\_policy* won't help us here, as creating a temporal policy with the new AWS Region will create a network disruption - as we already have a network configuration applied. That's why, when adding new AWS Regions, we need a two-step deployment:

* Finally, you can remove the definition of the old module (the one using version 0.x) from your main.tf file (or similar)
* Step 1: Update and apply the policy document with the new AWS Region(s).
* Step 2: Create the new attachment(s) and update the policy document if any static route is needed.

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.50.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.57.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.50.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.57.0 |

## Modules

Expand All @@ -177,15 +140,16 @@ terraform state rm module.new_cloudwan.awscc_networkmanager_core_network.core_ne
| Name | Type |
|------|------|
| [aws_networkmanager_core_network.core_network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkmanager_core_network) | resource |
| [aws_networkmanager_core_network_policy_attachment.policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkmanager_core_network_policy_attachment) | resource |
| [aws_networkmanager_global_network.global_network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkmanager_global_network) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_core_network"></a> [core\_network](#input\_core\_network) | Core Network definition. The following attributes are required:<br>- `description` = (string) Core Network's description.<br>- `policy_document` = (any) Core Network's policy in JSON format. It is recommended the use of the [Core Network Document data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/networkmanager_core_network_policy_document)<pre></pre> | <pre>object({<br> description = string<br> policy_document = any<br> })</pre> | n/a | yes |
| <a name="input_core_network"></a> [core\_network](#input\_core\_network) | Core Network definition. The following attributes are required:<br>- `description` = (string) Core Network's description.<br>- `policy_document` = (any) Core Network's policy in JSON format. It is recommended the use of the [Core Network Document data source](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/networkmanager_core_network_policy_document)<br>- `base_policy_regions` = (optional\|list(string)) List of AWS Regions to create the base policy in the Core Network. For more information about the need of the base policy, check the README document.<pre></pre> | <pre>object({<br> description = string<br> policy_document = any<br> base_policy_regions = optional(list(string))<br> })</pre> | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to all resources. | `map(string)` | n/a | yes |
| <a name="input_global_network"></a> [global\_network](#input\_global\_network) | Global Network definition. This variable expects the following attributes:<br>- `create = (Required|string) Indicating if a Global Network should be created or not. Default to `true`.<br>- `id` = (Optional|string) ID of a current Global Network created outside the module. Attribute required when `var.create\_global\_network` is **false**.<br>- `description` = (Optional|string) Description of the new Global Network to create. Attribute required when `var.create\_global\_network` is **true**.<br>`<pre></pre> | <pre>object({<br> create = bool<br> id = optional(string)<br> description = optional(string)<br> })</pre> | <pre>{<br> "create": true<br>}</pre> | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to all resources. | `map(string)` | `{}` | no |

## Outputs

Expand Down
59 changes: 59 additions & 0 deletions UPGRADE-GUIDE-1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Changes from 0.x to 1.x

If you are using a version 0.x of this module and want to move to a version 1.x, you will find that we have migrated from using the [AWSCC](https://registry.terraform.io/providers/hashicorp/awscc/latest) provider to [AWS](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) provider for the Global and Core Network resources. If you want to udpate the version without re-creating the resources, you need to proceed as follows:

* First, add in your main.tf (or similar file) a new module definition. In this new definition you need to pass the current Global Network without creating a new one.

```hcl
module "cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "0.x.x"
global_network = {
create = true
description = "Global Network - AWS CloudWAN Module"
}
core_network = {
description = "Core Network - AWS CloudWAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
}
tags = {
Name = "create-global-network"
}
}
module "new_cloudwan" {
source = "aws-ia/cloudwan/aws"
version = "1.x.x"
global_network = {
create = false
id = "global-network-XXX"
}
core_network = {
description = "Core Network - AWS CloudWAN Module"
policy_document = data.aws_networkmanager_core_network_policy_document.main.json
}
tags = {
Name = "create-global-network"
}
}
```

* Next, do a Terraform import for the new Global and Core Network resources.

```
terraform import module.new_cloudwan.aws_networkmanager_global_network.global_network[0] global-network-XXX
terraform import module.new_cloudwan.aws_networkmanager_core_network.core_network core-network-XXX
```

* Now you can remove from the Terraform state the old resources

```
terraform state rm module.cloudwan.awscc_networkmanager_global_network.global_network[0]
terraform state rm module.new_cloudwan.awscc_networkmanager_core_network.core_network
```

* Finally, you can remove the definition of the old module (the one using version 0.x) from your main.tf file (or similar)
15 changes: 15 additions & 0 deletions UPGRADE-GUIDE-2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changes from 1.x to 2.x

Changes from version 1 to version 2 of this module are minimal, and **don't entail any downtime**. However, check this guide to understand the new behavior.

There's a new resource added - `aws_networkmanager_core_network_policy_attachment`- that doesn't create new resources, rather it decouples the creation of the Core Network to the policy document attachment. This is used to avoid circular dependencies when you reference Core Network attachment IDs in the policy document.

So, if you move from version 1.x.x to 2.x.x and you do a `terraform plan`, you will see 1 new resource to be created. When doing a `terraform apply`, it will generate a new policy version in the Core Network containing the same policy you currently have (unless you apply changes). You won't have any disruption.

If you want to avoid the creation of this resource and the generation of the new policy version, you can import the resource by doing:

```
terraform import module.cloudwan.aws_networkmanager_core_network_policy_attachment.policy_attachment core-network-XXX
```

If you do a `terraform plan`, you won't see any changes in the infrastructure.
9 changes: 9 additions & 0 deletions examples/base_policy/.header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# AWS Cloud WAN Module - Example with base_policy

This example creates a Network Manager Global Network and Cloud WAN Core Network from scratch, using the base_policy attribute.

## Usage

- Initialize Terraform using `terraform init`.
- Now you can deploy the rest of the infrastructure using `terraform apply`.
- To delete everything, use `terraform destroy`.
20 changes: 20 additions & 0 deletions examples/base_policy/.terraform-docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
formatter: markdown
header-from: .header.md
settings:
anchor: true
color: true
default: true
escape: true
html: true
indent: 2
required: true
sensitive: true
type: true

sort:
enabled: true
by: required

output:
file: README.md
mode: replace
Loading

0 comments on commit b1838b6

Please sign in to comment.