Skip to content

Commit

Permalink
HCCP-91 HVN route resource (#122)
Browse files Browse the repository at this point in the history
* added create, scaffolded read and delete for hvn route resource

* Adds delete for HVN route resource

* Adds hvn route import function

* Handle both peering and tgw attachment resource types in HVN route resources

* Regenerate docs, add example s for hvn route resource

* Re-run go generate after adding  example

* ACreate hvn route function checks for target existence before proceeding

* Add peering to example for hvn route, regenerate docs

* Resolves comments - better logging and commenting for HVN route resource

* removed unnecessary validation

* removed todos

* removed tgw attachment from hvn route example

* added examples of the hvn route target

* moved hvn route creation into clients

* simplified parsing target_link for the hvn route resource

* dropped checking for hvn route existance

* fixed hvn routes import

* gofmt hvn_route.go

* redo hvn route import to use route ID

* go mod tidy

* redo hvn route datasource to use route ID

* renamed hvn -> hvn_link

* refactored WaitForHVNRouteToBeActive

* unified hvn route errors/logs

* small refactoring

* improved logs

* messages improvements

Co-authored-by: Brenna Hewer-Darroch <21015366+bcmdarroch@users.noreply.github.com>

* regenarated docs

Co-authored-by: Anton Panferov <smaant@gmail.com>
Co-authored-by: Brenna Hewer-Darroch <21015366+bcmdarroch@users.noreply.github.com>
  • Loading branch information
3 people committed Jun 4, 2021
1 parent 7304bc1 commit 738758b
Show file tree
Hide file tree
Showing 14 changed files with 575 additions and 43 deletions.
9 changes: 5 additions & 4 deletions docs/data-sources/hvn_route.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ The HVN route data source provides information about an existing HVN route.

```terraform
data "hcp_hvn_route" "example" {
hvn = var.hvn
destination_cidr = var.destination_cidr
hvn_link = var.hvn_link
destination_cidr = var.hvn_route_id
}
```

Expand All @@ -25,8 +25,8 @@ data "hcp_hvn_route" "example" {

### Required

- **destination_cidr** (String) The destination CIDR of the HVN route
- **hvn** (String) The `self_link` of the HashiCorp Virtual Network (HVN).
- **hvn_link** (String) The `self_link` of the HashiCorp Virtual Network (HVN).
- **hvn_route_id** (String) The ID of the HVN route.

### Optional

Expand All @@ -36,6 +36,7 @@ data "hcp_hvn_route" "example" {
### Read-Only

- **created_at** (String) The time that the HVN route was created.
- **destination_cidr** (String) The destination CIDR of the HVN route.
- **self_link** (String) A unique URL identifying the HVN route.
- **state** (String) The state of the HVN route.
- **target_link** (String) A unique URL identifying the target of the HVN route.
Expand Down
89 changes: 89 additions & 0 deletions docs/resources/hvn_route.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "hcp_hvn_route Resource - terraform-provider-hcp"
subcategory: ""
description: |-
The HVN route resource allows you to manage an HVN route.
---

# hcp_hvn_route (Resource)

The HVN route resource allows you to manage an HVN route.

## Example Usage

```terraform
provider "aws" {
region = "us-west-2"
}
resource "hcp_hvn" "main" {
hvn_id = "main-hvn"
cloud_provider = "aws"
region = "us-west-2"
cidr_block = "172.25.16.0/20"
}
// Creating a peering and a route for it.
resource "aws_vpc" "peer" {
cidr_block = "192.168.0.0/20"
}
resource "hcp_aws_network_peering" "example" {
peering_id = "peer-example"
hvn_id = hcp_hvn.main.hvn_id
peer_vpc_id = aws_vpc.peer.id
peer_account_id = aws_vpc.peer.owner_id
peer_vpc_region = "us-west-2"
}
resource "aws_vpc_peering_connection_accepter" "peer" {
vpc_peering_connection_id = hcp_aws_network_peering.example.provider_peering_id
auto_accept = true
}
resource "hcp_hvn_route" "example-peering-route" {
hvn_link = hcp_hvn.main.self_link
hvn_route_id = "peering-route"
destination_cidr = aws_vpc.peer.cidr_block
target_link = hcp_aws_network_peering.example.self_link
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- **destination_cidr** (String) The destination CIDR of the HVN route.
- **hvn_link** (String) The `self_link` of the HashiCorp Virtual Network (HVN).
- **hvn_route_id** (String) The ID of the HVN route.
- **target_link** (String) A unique URL identifying the target of the HVN route. Examples of the target: [`aws_network_peering`](aws_network_peering.md), [`aws_transit_gateway_attachment`](aws_transit_gateway_attachment.md)

### Optional

- **id** (String) The ID of this resource.
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

### Read-Only

- **created_at** (String) The time that the HVN route was created.
- **self_link** (String) A unique URL identifying the HVN route.
- **state** (String) The state of the HVN route.

<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

Optional:

- **create** (String)
- **default** (String)

## Import

Import is supported using the following syntax:

```shell
# The import ID is {hvn_id}:{hvn_route_id}
terraform import hcp_hvn_route.example main-hvn:example-hvn-route
```
4 changes: 2 additions & 2 deletions examples/data-sources/hcp_hvn_route/data-source.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
data "hcp_hvn_route" "example" {
hvn = var.hvn
destination_cidr = var.destination_cidr
hvn_link = var.hvn_link
destination_cidr = var.hvn_route_id
}
6 changes: 3 additions & 3 deletions examples/data-sources/hcp_hvn_route/variables.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
variable "hvn" {
variable "hvn_link" {
description = "The `self_link` of the HashiCorp Virtual Network (HVN)."
type = string
}

variable "destination_cidr" {
description = "The destination CIDR of the HVN route."
variable "hvn_route_id" {
description = "The ID of the HVN route ID."
type = string
}
2 changes: 2 additions & 0 deletions examples/resources/hcp_hvn_route/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The import ID is {hvn_id}:{hvn_route_id}
terraform import hcp_hvn_route.example main-hvn:example-hvn-route
35 changes: 35 additions & 0 deletions examples/resources/hcp_hvn_route/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
provider "aws" {
region = "us-west-2"
}

resource "hcp_hvn" "main" {
hvn_id = "main-hvn"
cloud_provider = "aws"
region = "us-west-2"
cidr_block = "172.25.16.0/20"
}

// Creating a peering and a route for it.
resource "aws_vpc" "peer" {
cidr_block = "192.168.0.0/20"
}

resource "hcp_aws_network_peering" "example" {
peering_id = "peer-example"
hvn_id = hcp_hvn.main.hvn_id
peer_vpc_id = aws_vpc.peer.id
peer_account_id = aws_vpc.peer.owner_id
peer_vpc_region = "us-west-2"
}

resource "aws_vpc_peering_connection_accepter" "peer" {
vpc_peering_connection_id = hcp_aws_network_peering.example.provider_peering_id
auto_accept = true
}

resource "hcp_hvn_route" "example-peering-route" {
hvn_link = hcp_hvn.main.self_link
hvn_route_id = "peering-route"
destination_cidr = aws_vpc.peer.cidr_block
target_link = hcp_aws_network_peering.example.self_link
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/google/uuid v1.2.0
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/hcl/v2 v2.8.2 // indirect
github.com/hashicorp/hcp-sdk-go v0.7.0
github.com/hashicorp/hcp-sdk-go v0.8.0
github.com/hashicorp/terraform-exec v0.13.3 // indirect
github.com/hashicorp/terraform-plugin-docs v0.4.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.5.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8=
github.com/hashicorp/hcl/v2 v2.8.2 h1:wmFle3D1vu0okesm8BTLVDyJ6/OL9DCLUwn0b2OptiY=
github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
github.com/hashicorp/hcp-sdk-go v0.7.0 h1:OtbcR/rMBlfK5BLowHIPe0HJtb0rEs8FyRAzS+xH9vI=
github.com/hashicorp/hcp-sdk-go v0.7.0/go.mod h1:M+kmFj0s4KWNA5GVOgLhNtCTu3ypTR+QjWYIMgedA5Q=
github.com/hashicorp/hcp-sdk-go v0.8.0 h1:P7mMk2h87BYJ6dk851pD3WvnuXa17hxvutA5slxCWGU=
github.com/hashicorp/hcp-sdk-go v0.8.0/go.mod h1:M+kmFj0s4KWNA5GVOgLhNtCTu3ypTR+QjWYIMgedA5Q=
github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/terraform-exec v0.12.0/go.mod h1:SGhto91bVRlgXQWcJ5znSz+29UZIa8kpBbkGwQ+g9E8=
Expand Down
124 changes: 124 additions & 0 deletions internal/clients/hvn_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,68 @@ package clients

import (
"context"
"fmt"
"log"
"time"

"github.com/hashicorp/hcp-sdk-go/clients/cloud-network/preview/2020-09-07/client/network_service"
networkmodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-network/preview/2020-09-07/models"
sharedmodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-shared/v1/models"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

// CreateHVNRoute creates a new HVN route
func CreateHVNRoute(ctx context.Context, client *Client,
id string,
hvn *sharedmodels.HashicorpCloudLocationLink,
destination string,
target *sharedmodels.HashicorpCloudLocationLink,
location *sharedmodels.HashicorpCloudLocationLocation) (*networkmodels.HashicorpCloudNetwork20200907CreateHVNRouteResponse, error) {

hvnRouteParams := network_service.NewCreateHVNRouteParams()
hvnRouteParams.Context = ctx
hvnRouteParams.HvnLocationOrganizationID = location.OrganizationID
hvnRouteParams.HvnLocationProjectID = location.ProjectID
hvnRouteParams.HvnID = hvn.ID
hvnRouteParams.Body = &networkmodels.HashicorpCloudNetwork20200907CreateHVNRouteRequest{
Destination: destination,
Hvn: hvn,
ID: id,
Target: &networkmodels.HashicorpCloudNetwork20200907HVNRouteTarget{
HvnConnection: target,
},
}
log.Printf("[INFO] Creating HVN route for HVN (%s) with destination CIDR %s", hvn.ID, destination)
hvnRouteResp, err := client.Network.CreateHVNRoute(hvnRouteParams, nil)
if err != nil {
return nil, fmt.Errorf("unable to create HVN route for HVN (%s) with destination CIDR %s: %v", hvn.ID, destination, err)
}

return hvnRouteResp.Payload, nil
}

// GetHVNRoute returns specific HVN route by its ID
func GetHVNRoute(ctx context.Context, client *Client, hvnID, routeID string, loc *sharedmodels.HashicorpCloudLocationLocation) (*networkmodels.HashicorpCloudNetwork20200907HVNRoute, error) {
getHVNRouteParams := network_service.NewGetHVNRouteParams()
getHVNRouteParams.Context = ctx
getHVNRouteParams.HvnID = hvnID
getHVNRouteParams.ID = routeID
getHVNRouteParams.HvnLocationOrganizationID = loc.OrganizationID
getHVNRouteParams.HvnLocationProjectID = loc.ProjectID

getHVNRouteResponse, err := client.Network.GetHVNRoute(getHVNRouteParams, nil)
if err != nil {
return nil, err
}

return getHVNRouteResponse.Payload.Route, nil
}

// ListHVNRoutes lists the routes for an HVN.
func ListHVNRoutes(ctx context.Context, client *Client, hvnID string,
destination string, targetID string, targetType string,
loc *sharedmodels.HashicorpCloudLocationLocation) ([]*networkmodels.HashicorpCloudNetwork20200907HVNRoute, error) {

listHVNRoutesParams := network_service.NewListHVNRoutesParams()
listHVNRoutesParams.Context = ctx
listHVNRoutesParams.HvnID = hvnID
Expand All @@ -28,3 +80,75 @@ func ListHVNRoutes(ctx context.Context, client *Client, hvnID string,

return listHVNRoutesResponse.Payload.Routes, nil
}

// DeleteSnapshotByID deletes an HVN route by its ID
func DeleteHVNRouteByID(ctx context.Context, client *Client, hvnID string,
hvnRouteID string, loc *sharedmodels.HashicorpCloudLocationLocation) (*networkmodels.HashicorpCloudNetwork20200907DeleteHVNRouteResponse, error) {

deleteHVNRouteParams := network_service.NewDeleteHVNRouteParams()

deleteHVNRouteParams.Context = ctx
deleteHVNRouteParams.ID = hvnRouteID
deleteHVNRouteParams.HvnID = hvnID
deleteHVNRouteParams.HvnLocationOrganizationID = loc.OrganizationID
deleteHVNRouteParams.HvnLocationProjectID = loc.ProjectID

deleteHVNRouteResponse, err := client.Network.DeleteHVNRoute(deleteHVNRouteParams, nil)
if err != nil {
return nil, err
}

return deleteHVNRouteResponse.Payload, nil
}

const (
// HvnRouteStateCreating is the CREATING state of an HVN route
HvnRouteStateCreating = string(networkmodels.HashicorpCloudNetwork20200907HVNRouteStateCREATING)

// HvnRouteStateActive is the ACTIVE state of an HVN route
HvnRouteStateActive = string(networkmodels.HashicorpCloudNetwork20200907HVNRouteStateACTIVE)

// HvnRouteStatePending is the PENDING state of an HVN route
HvnRouteStatePending = string(networkmodels.HashicorpCloudNetwork20200907HVNRouteStatePENDING)
)

// hvnRouteRefreshState refreshes the state of the HVN route
func hvnRouteRefreshState(ctx context.Context, client *Client, hvnID, routeID string, loc *sharedmodels.HashicorpCloudLocationLocation) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
route, err := GetHVNRoute(ctx, client, hvnID, routeID, loc)
if err != nil {
return nil, "", err
}

return route, string(route.State), nil
}
}

// WaitForHVNRouteToBeActive will poll the GET HVN route endpoint until
// the state is ACTIVE, ctx is canceled, or an error occurs.
func WaitForHVNRouteToBeActive(ctx context.Context, client *Client,
hvnID string,
routeID string,
loc *sharedmodels.HashicorpCloudLocationLocation,
timeout time.Duration) (*networkmodels.HashicorpCloudNetwork20200907HVNRoute, error) {

stateChangeConf := resource.StateChangeConf{
Pending: []string{
HvnRouteStateCreating,
HvnRouteStatePending,
},
Target: []string{
HvnRouteStateActive,
},
Refresh: hvnRouteRefreshState(ctx, client, hvnID, routeID, loc),
Timeout: timeout,
PollInterval: 5 * time.Second,
}

result, err := stateChangeConf.WaitForStateContext(ctx)
if err != nil {
return nil, fmt.Errorf("error waiting for the HVN route (%s) to become 'ACTIVE': %+v", routeID, err)
}

return result.(*networkmodels.HashicorpCloudNetwork20200907HVNRoute), nil
}
Loading

0 comments on commit 738758b

Please sign in to comment.