Skip to content

Commit 0d7dc22

Browse files
committed
NSOF-5917 metaport_mapped_elements_attachment: introduce resource
1 parent 35e2c9d commit 0d7dc22

File tree

11 files changed

+319
-0
lines changed

11 files changed

+319
-0
lines changed

docs/resources/metaport.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ description: |-
1010

1111
MetaPort is a lightweight virtual appliance that enables the secure authenticated interface interact between existing servers and the Proofpoint NaaS cloud. Once configured, metaports enable users to access your applications via the Proofpoint cloud.
1212

13+
~> **NOTE:** When using the `mapped_elements` argument of this resource, the resource will take over the management of the MetaPort's mapped elements.
14+
This argument is incompatible with other methods of managing MetaPort's mapped elements, such as `metaport_mapped_elements_attachment`.
15+
Any attempt to manage MetaPort's mapped elements using different methods, will result in resource cycling and/or errors.
16+
1317
## Example Usage
1418

1519
```terraform
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "pfptmeta_metaport_mapped_elements_attachment Resource - terraform-provider-pfptmeta"
4+
subcategory: "Network"
5+
description: |-
6+
Attaches mapped elements to metaport.
7+
---
8+
9+
# pfptmeta_metaport_mapped_elements_attachment (Resource)
10+
11+
Attaches mapped elements to metaport.
12+
13+
~> **NOTE:** Having multiple **metaport_mapped_elements_attachment** resources in conjunction with the same MetaPort and mapped elements will result in erratic behavior!
14+
~> **NOTE:** For any given MetaPort, this resource is incompatible with the `pfptmeta_metaport`
15+
[resource](https://registry.terraform.io/providers/nsofnetworks/pfptmeta/latest/docs/resources/metaport) `mapped_elements` argument.
16+
When using this argument and resource simulteneously, both of them will attempt to manage the MetaPort's mapped elements. As a result, Terraform will display a permanent difference.
17+
18+
## Example Usage
19+
20+
```terraform
21+
resource "pfptmeta_network_element" "mapped-subnet" {
22+
name = "mapped subnet name"
23+
mapped_subnets = ["0.0.0.0/0"]
24+
}
25+
26+
resource "pfptmeta_metaport" "metaport" {
27+
name = "metaport name"
28+
}
29+
30+
resource "pfptmeta_metaport_mapped_elements_attachment" "attachment" {
31+
metaport_id = pfptmeta_metaport.metaport.id
32+
mapped_elements = [pfptmeta_network_element.mapped-subnet.id]
33+
}
34+
```
35+
36+
<!-- schema generated by tfplugindocs -->
37+
## Schema
38+
39+
### Required
40+
41+
- **mapped_elements** (Set of String) Mapped element IDs to be attached to the metaport (Mapped Subnet, Mapped Service or Enterprise DNS)
42+
- **metaport_id** (String)
43+
44+
### Read-Only
45+
46+
- **id** (String) The ID of this resource.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
resource "pfptmeta_network_element" "mapped-subnet" {
2+
name = "mapped subnet name"
3+
mapped_subnets = ["0.0.0.0/0"]
4+
}
5+
6+
resource "pfptmeta_metaport" "metaport" {
7+
name = "metaport name"
8+
}
9+
10+
resource "pfptmeta_metaport_mapped_elements_attachment" "attachment" {
11+
metaport_id = pfptmeta_metaport.metaport.id
12+
mapped_elements = [pfptmeta_network_element.mapped-subnet.id]
13+
}

internal/client/metaport.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,33 @@ func DeleteMetaport(ctx context.Context, c *Client, mID string) (*Metaport, erro
101101
}
102102
return parseMetaport(resp)
103103
}
104+
105+
func AddMappedElementsToMetaport(ctx context.Context, c *Client, mID string, meIDs []string) (*Metaport, error) {
106+
url := fmt.Sprintf("%s/%s/%s/add_mapped_elements", c.BaseURL, metaportEndpoint, mID)
107+
body := make(map[string][]string)
108+
body["mapped_elements"] = meIDs
109+
jsonBody, err := json.Marshal(body)
110+
if err != nil {
111+
return nil, fmt.Errorf("could not convert mapped elements to json: %v", err)
112+
}
113+
resp, err := c.Post(ctx, url, bytes.NewReader(jsonBody))
114+
if err != nil {
115+
return nil, err
116+
}
117+
return parseMetaport(resp)
118+
}
119+
120+
func RemoveMappedElementsFromMetaport(ctx context.Context, c *Client, mID string, meIDs []string) (*Metaport, error) {
121+
url := fmt.Sprintf("%s/%s/%s/remove_mapped_elements", c.BaseURL, metaportEndpoint, mID)
122+
body := make(map[string][]string)
123+
body["mapped_elements"] = meIDs
124+
jsonBody, err := json.Marshal(body)
125+
if err != nil {
126+
return nil, fmt.Errorf("could not convert mapped elements to json: %v", err)
127+
}
128+
resp, err := c.Post(ctx, url, bytes.NewReader(jsonBody))
129+
if err != nil {
130+
return nil, err
131+
}
132+
return parseMetaport(resp)
133+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package acc_tests
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
5+
"regexp"
6+
"testing"
7+
)
8+
9+
const (
10+
metaportAttachmentDependencies = `
11+
resource "pfptmeta_network_element" "mapped-service" {
12+
name = "mapped service"
13+
mapped_service = "mapped.service.com"
14+
}
15+
16+
resource "pfptmeta_network_element" "mapped-service2" {
17+
name = "mapped service"
18+
mapped_service = "mapped.service2.com"
19+
}
20+
21+
resource "pfptmeta_metaport" "metaport" {
22+
name = "metaport name1"
23+
}
24+
`
25+
metaportAttachment1 = `
26+
resource "pfptmeta_metaport_mapped_elements_attachment" "attachment" {
27+
metaport_id = pfptmeta_metaport.metaport.id
28+
mapped_elements = [pfptmeta_network_element.mapped-service.id]
29+
}
30+
`
31+
metaportAttachment2 = `
32+
resource "pfptmeta_metaport_mapped_elements_attachment" "attachment2" {
33+
metaport_id = pfptmeta_metaport.metaport.id
34+
mapped_elements = [pfptmeta_network_element.mapped-service2.id]
35+
}
36+
`
37+
metaportDataSource = `
38+
data "pfptmeta_metaport" "metaport" {
39+
id = pfptmeta_metaport.metaport.id
40+
}
41+
`
42+
)
43+
44+
func TestAccMetaportAttachment(t *testing.T) {
45+
resource.Test(t, resource.TestCase{
46+
PreCheck: func() { testAccPreCheck(t) },
47+
ProviderFactories: providerFactories,
48+
CheckDestroy: validateResourceDestroyed("metaport", "v1/metaports"),
49+
Steps: []resource.TestStep{
50+
{
51+
Config: metaportAttachmentDependencies + metaportAttachment1 + metaportAttachment2,
52+
Check: resource.ComposeTestCheckFunc(
53+
resource.TestMatchResourceAttr(
54+
"pfptmeta_metaport_mapped_elements_attachment.attachment", "metaport_id", regexp.MustCompile("^mp-.+$"),
55+
),
56+
resource.TestCheckResourceAttrPair(
57+
"pfptmeta_network_element.mapped-service", "id",
58+
"pfptmeta_metaport_mapped_elements_attachment.attachment", "mapped_elements.0"),
59+
resource.TestCheckResourceAttrPair(
60+
"pfptmeta_network_element.mapped-service2", "id",
61+
"pfptmeta_metaport_mapped_elements_attachment.attachment2", "mapped_elements.0"),
62+
),
63+
},
64+
{
65+
Config: metaportAttachmentDependencies + metaportAttachment2,
66+
},
67+
{
68+
Config: metaportAttachmentDependencies + metaportAttachment2 + metaportDataSource,
69+
Check: resource.ComposeTestCheckFunc(
70+
resource.TestMatchResourceAttr(
71+
"data.pfptmeta_metaport.metaport", "id", regexp.MustCompile("^mp-.+$"),
72+
),
73+
resource.TestCheckResourceAttrPair(
74+
"pfptmeta_network_element.mapped-service2", "id",
75+
"data.pfptmeta_metaport.metaport", "mapped_elements.0"),
76+
),
77+
},
78+
},
79+
})
80+
}

internal/provider/metaport/resource.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func Resource() *schema.Resource {
3434
Description: mappedElementsDesc,
3535
Type: schema.TypeSet,
3636
Optional: true,
37+
Computed: true,
3738
Elem: &schema.Schema{
3839
Type: schema.TypeString,
3940
ValidateDiagFunc: common.ValidateID(true, "ed", "ne")},
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package metaport_mapped_elements_attachment
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/client"
9+
"net/http"
10+
)
11+
12+
func generateID(mID string, meIDs []string) string {
13+
hash := 0
14+
for _, meID := range meIDs {
15+
hash += schema.HashString(meID)
16+
}
17+
return fmt.Sprintf("%s-%d", mID, hash)
18+
}
19+
20+
func attachmentToResource(d *schema.ResourceData, m *client.Metaport) (diags diag.Diagnostics) {
21+
err := d.Set("metaport_id", m.ID)
22+
if err != nil {
23+
return diag.FromErr(err)
24+
}
25+
mMes := &schema.Set{F: schema.HashString}
26+
for _, i := range m.MappedElements {
27+
mMes.Add(i)
28+
}
29+
schemaMes := d.Get("mapped_elements").(*schema.Set)
30+
schemaMesSet := schema.NewSet(schema.HashString, schemaMes.List())
31+
intersection := mMes.Intersection(schemaMesSet)
32+
mes := client.ResourceTypeSetToStringSlice(intersection)
33+
err = d.Set("mapped_elements", mes)
34+
if err != nil {
35+
return diag.FromErr(err)
36+
}
37+
d.SetId(generateID(m.ID, mes))
38+
return
39+
}
40+
41+
func readResource(ctx context.Context, d *schema.ResourceData, meta interface{}) (diags diag.Diagnostics) {
42+
c := meta.(*client.Client)
43+
44+
mID := d.Get("metaport_id").(string)
45+
rg, err := client.GetMetaport(ctx, c, mID)
46+
if err != nil {
47+
errResponse, ok := err.(*client.ErrorResponse)
48+
if ok && errResponse.Status == http.StatusNotFound {
49+
d.SetId("")
50+
}
51+
return diag.FromErr(err)
52+
}
53+
return attachmentToResource(d, rg)
54+
}
55+
func createResource(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
56+
c := meta.(*client.Client)
57+
58+
mID := d.Get("metaport_id").(string)
59+
mes := client.ResourceTypeSetToStringSlice(d.Get("mapped_elements").(*schema.Set))
60+
m, err := client.AddMappedElementsToMetaport(ctx, c, mID, mes)
61+
if err != nil {
62+
return diag.FromErr(err)
63+
}
64+
return attachmentToResource(d, m)
65+
}
66+
67+
func deleteResource(ctx context.Context, d *schema.ResourceData, meta interface{}) (diags diag.Diagnostics) {
68+
c := meta.(*client.Client)
69+
70+
mID := d.Get("metaport_id").(string)
71+
mes := d.Get("mapped_elements").(*schema.Set)
72+
_, err := client.RemoveMappedElementsFromMetaport(ctx, c, mID, client.ResourceTypeSetToStringSlice(mes))
73+
if err != nil {
74+
d.SetId("")
75+
return diag.FromErr(err)
76+
}
77+
d.SetId("")
78+
return
79+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package metaport_mapped_elements_attachment
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
5+
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/common"
6+
)
7+
8+
func Resource() *schema.Resource {
9+
return &schema.Resource{
10+
Description: "Attaches mapped elements to metaport.",
11+
ReadContext: readResource,
12+
CreateContext: createResource,
13+
DeleteContext: deleteResource,
14+
Schema: map[string]*schema.Schema{
15+
"id": {
16+
Type: schema.TypeString,
17+
Computed: true,
18+
},
19+
"metaport_id": {
20+
Type: schema.TypeString,
21+
Required: true,
22+
ValidateDiagFunc: common.ValidateID(false, "mp"),
23+
ForceNew: true,
24+
},
25+
"mapped_elements": {
26+
Description: "Mapped element IDs to be attached to the metaport (Mapped Subnet, Mapped Service or Enterprise DNS)",
27+
Required: true,
28+
Type: schema.TypeSet,
29+
Elem: &schema.Schema{
30+
Type: schema.TypeString,
31+
ValidateDiagFunc: common.ValidateID(true, "ne", "ed"),
32+
},
33+
MinItems: 1,
34+
ForceNew: true,
35+
},
36+
},
37+
}
38+
}

internal/provider/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/metaport"
2222
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/metaport_cluster"
2323
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/metaport_failover"
24+
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/metaport_mapped_elements_attachment"
2425
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/network_element"
2526
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/network_element_alias"
2627
"github.com/nsofnetworks/terraform-provider-pfptmeta/internal/provider/notification_channel"
@@ -89,6 +90,7 @@ func New(version string) func() *schema.Provider {
8990
"pfptmeta_mapped_domain": mapped_domain.Resource(),
9091
"pfptmeta_mapped_host": mapped_host.Resource(),
9192
"pfptmeta_metaport": metaport.Resource(),
93+
"pfptmeta_metaport_mapped_elements_attachment": metaport_mapped_elements_attachment.Resource(),
9294
"pfptmeta_metaport_cluster": metaport_cluster.Resource(),
9395
"pfptmeta_metaport_failover": metaport_failover.Resource(),
9496
"pfptmeta_enterprise_dns": enterprise_dns.Resource(),

templates/resources/metaport.md.tmpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ description: |-
1010

1111
{{ .Description | trimspace }}
1212

13+
~> **NOTE:** When using the `mapped_elements` argument of this resource, the resource will take over the management of the MetaPort's mapped elements.
14+
This argument is incompatible with other methods of managing MetaPort's mapped elements, such as `metaport_mapped_elements_attachment`.
15+
Any attempt to manage MetaPort's mapped elements using different methods, will result in resource cycling and/or errors.
16+
1317
## Example Usage
1418

1519
{{tffile "examples/resources/pfptmeta_metaport/resource.tf"}}

0 commit comments

Comments
 (0)