Skip to content

Commit d601eba

Browse files
committed
Implement nxst_policy_edge_high_availability_profile resource
Signed-off-by: Kobi Samoray <kobi.samoray@broadcom.com>
1 parent c097b61 commit d601eba

File tree

4 files changed

+599
-13
lines changed

4 files changed

+599
-13
lines changed

nsxt/provider.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -527,19 +527,20 @@ func Provider() *schema.Provider {
527527
"nsxt_policy_shared_resource": resourceNsxtPolicySharedResource(),
528528
"nsxt_policy_gateway_connection": resourceNsxtPolicyGatewayConnection(),
529529
"nsxt_policy_distributed_vlan_connection": resourceNsxtPolicyDistributedVlanConnection(),
530-
"nsxt_vpc": resourceNsxtVpc(),
531-
"nsxt_vpc_attachment": resourceNsxtVpcAttachment(),
532-
"nsxt_vpc_nat_rule": resourceNsxtPolicyVpcNatRule(),
533-
"nsxt_policy_transit_gateway_attachment": resourceNsxtPolicyTransitGatewayAttachment(),
534-
"nsxt_vpc_external_address": resourceNsxtVpcExternalAddress(),
535-
"nsxt_vpc_ip_address_allocation": resourceNsxtVpcIpAddressAllocation(),
536-
"nsxt_vpc_subnet": resourceNsxtVpcSubnet(),
537-
"nsxt_policy_transit_gateway_nat_rule": resourceNsxtPolicyTransitGatewayNatRule(),
538-
"nsxt_vpc_static_route": resourceNsxtVpcStaticRoutes(),
539-
"nsxt_policy_project_ip_address_allocation": resourceNsxtPolicyProjectIpAddressAllocation(),
540-
"nsxt_vpc_dhcp_v4_static_binding": resourceNsxtVpcSubnetDhcpV4StaticBindingConfig(),
541-
"nsxt_policy_l7_access_profile": resourceNsxtPolicyL7AccessProfile(),
542-
"nsxt_policy_edge_transport_node": resourceNsxtPolicyEdgeTransportNode(),
530+
"nsxt_vpc": resourceNsxtVpc(),
531+
"nsxt_vpc_attachment": resourceNsxtVpcAttachment(),
532+
"nsxt_vpc_nat_rule": resourceNsxtPolicyVpcNatRule(),
533+
"nsxt_policy_transit_gateway_attachment": resourceNsxtPolicyTransitGatewayAttachment(),
534+
"nsxt_vpc_external_address": resourceNsxtVpcExternalAddress(),
535+
"nsxt_vpc_ip_address_allocation": resourceNsxtVpcIpAddressAllocation(),
536+
"nsxt_vpc_subnet": resourceNsxtVpcSubnet(),
537+
"nsxt_policy_transit_gateway_nat_rule": resourceNsxtPolicyTransitGatewayNatRule(),
538+
"nsxt_vpc_static_route": resourceNsxtVpcStaticRoutes(),
539+
"nsxt_policy_project_ip_address_allocation": resourceNsxtPolicyProjectIpAddressAllocation(),
540+
"nsxt_vpc_dhcp_v4_static_binding": resourceNsxtVpcSubnetDhcpV4StaticBindingConfig(),
541+
"nsxt_policy_l7_access_profile": resourceNsxtPolicyL7AccessProfile(),
542+
"nsxt_policy_edge_transport_node": resourceNsxtPolicyEdgeTransportNode(),
543+
"nsxt_policy_edge_high_availability_profile": resourceNsxtPolicyEdgeHighAvailabilityProfile(),
543544
},
544545

545546
ConfigureFunc: providerConfigure,
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
/* Copyright © 2024 Broadcom, Inc. All Rights Reserved.
2+
SPDX-License-Identifier: MPL-2.0 */
3+
4+
package nsxt
5+
6+
import (
7+
"fmt"
8+
"log"
9+
"reflect"
10+
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
13+
"github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client"
14+
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra"
15+
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/sites/enforcement_points"
16+
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
17+
18+
"github.com/vmware/terraform-provider-nsxt/nsxt/metadata"
19+
)
20+
21+
var policyEdgeHighAvailabilityProfileSchema = map[string]*metadata.ExtendedSchema{
22+
"nsx_id": metadata.GetExtendedSchema(getNsxIDSchema()),
23+
"path": metadata.GetExtendedSchema(getPathSchema()),
24+
"display_name": metadata.GetExtendedSchema(getDisplayNameSchema()),
25+
"description": metadata.GetExtendedSchema(getDescriptionSchema()),
26+
"revision": metadata.GetExtendedSchema(getRevisionSchema()),
27+
"tag": metadata.GetExtendedSchema(getTagsSchema()),
28+
"site_path": {
29+
Schema: schema.Schema{
30+
Type: schema.TypeString,
31+
Description: "Path to the site this Host Transport Node belongs to",
32+
Optional: true,
33+
ForceNew: true,
34+
Default: defaultInfraSitePath,
35+
ValidateFunc: validatePolicyPath(),
36+
},
37+
Metadata: metadata.Metadata{
38+
SchemaType: "string",
39+
Skip: true,
40+
},
41+
},
42+
"enforcement_point": {
43+
Schema: schema.Schema{
44+
Type: schema.TypeString,
45+
Description: "ID of the enforcement point this Host Transport Node belongs to",
46+
Optional: true,
47+
ForceNew: true,
48+
Default: "default",
49+
},
50+
Metadata: metadata.Metadata{
51+
SchemaType: "string",
52+
Skip: true,
53+
},
54+
},
55+
"bfd_probe_interval": {
56+
Schema: schema.Schema{
57+
Type: schema.TypeInt,
58+
Optional: true,
59+
Default: 500,
60+
ValidateFunc: validation.IntBetween(50, 60000),
61+
},
62+
Metadata: metadata.Metadata{
63+
SchemaType: "int",
64+
SdkFieldName: "BfdProbeInterval",
65+
},
66+
},
67+
"bfd_allowed_hops": {
68+
Schema: schema.Schema{
69+
Type: schema.TypeInt,
70+
Optional: true,
71+
Default: 255,
72+
ValidateFunc: validation.IntBetween(1, 255),
73+
},
74+
Metadata: metadata.Metadata{
75+
SchemaType: "int",
76+
SdkFieldName: "BfdAllowedHops",
77+
},
78+
},
79+
"bfd_declare_dead_multiple": {
80+
Schema: schema.Schema{
81+
Type: schema.TypeInt,
82+
Optional: true,
83+
Default: 3,
84+
ValidateFunc: validation.IntBetween(2, 16),
85+
},
86+
Metadata: metadata.Metadata{
87+
SchemaType: "int",
88+
SdkFieldName: "BfdDeclareDeadMultiple",
89+
},
90+
},
91+
"standby_relocation_config": {
92+
Schema: schema.Schema{
93+
Type: schema.TypeList,
94+
MaxItems: 1,
95+
Elem: &metadata.ExtendedResource{
96+
Schema: map[string]*metadata.ExtendedSchema{
97+
"standby_relocation_threshold": {
98+
Schema: schema.Schema{
99+
Type: schema.TypeInt,
100+
Optional: true,
101+
Computed: true,
102+
},
103+
Metadata: metadata.Metadata{
104+
SchemaType: "int",
105+
SdkFieldName: "StandbyRelocationThreshold",
106+
},
107+
},
108+
},
109+
},
110+
Optional: true,
111+
Computed: true,
112+
},
113+
Metadata: metadata.Metadata{
114+
SchemaType: "struct",
115+
SdkFieldName: "StandbyRelocationConfig",
116+
ReflectType: reflect.TypeOf(model.StandbyRelocationConfig{}),
117+
},
118+
},
119+
}
120+
121+
func resourceNsxtPolicyEdgeHighAvailabilityProfile() *schema.Resource {
122+
return &schema.Resource{
123+
Create: resourceNsxtPolicyEdgeHighAvailabilityProfileCreate,
124+
Read: resourceNsxtPolicyEdgeHighAvailabilityProfileRead,
125+
Update: resourceNsxtPolicyEdgeHighAvailabilityProfileUpdate,
126+
Delete: resourceNsxtPolicyEdgeHighAvailabilityProfileDelete,
127+
Importer: &schema.ResourceImporter{
128+
State: resourceNsxtPolicyEdgeHighAvailabilityProfileImporter,
129+
},
130+
Schema: metadata.GetSchemaFromExtendedSchema(policyEdgeHighAvailabilityProfileSchema),
131+
}
132+
}
133+
134+
func resourceNsxtPolicyEdgeHighAvailabilityProfileExists(siteID, epID, id string, connector client.Connector) (bool, error) {
135+
// Check site existence first
136+
siteClient := infra.NewSitesClient(connector)
137+
_, err := siteClient.Get(siteID)
138+
if err != nil {
139+
msg := fmt.Sprintf("failed to read site %s", siteID)
140+
return false, logAPIError(msg, err)
141+
}
142+
143+
client := enforcement_points.NewEdgeClusterHighAvailabilityProfilesClient(connector)
144+
_, err = client.Get(siteID, epID, id)
145+
if err == nil {
146+
return true, nil
147+
}
148+
149+
if isNotFoundError(err) {
150+
return false, nil
151+
}
152+
153+
return false, logAPIError("Error retrieving resource", err)
154+
}
155+
156+
func resourceNsxtPolicyEdgeHighAvailabilityProfileCreate(d *schema.ResourceData, m interface{}) error {
157+
id := d.Get("nsx_id").(string)
158+
if id == "" {
159+
id = newUUID()
160+
}
161+
sitePath := d.Get("site_path").(string)
162+
siteID := getResourceIDFromResourcePath(sitePath, "sites")
163+
if siteID == "" {
164+
return fmt.Errorf("error obtaining Site ID from site path %s", sitePath)
165+
}
166+
epID := d.Get("enforcement_point").(string)
167+
if epID == "" {
168+
epID = getPolicyEnforcementPoint(m)
169+
}
170+
171+
connector := getPolicyConnector(m)
172+
exists, err := resourceNsxtPolicyEdgeHighAvailabilityProfileExists(siteID, epID, id, connector)
173+
if err != nil {
174+
return err
175+
}
176+
if exists {
177+
return fmt.Errorf("resource with ID %s already exists", id)
178+
}
179+
180+
displayName := d.Get("display_name").(string)
181+
description := d.Get("description").(string)
182+
tags := getPolicyTagsFromSchema(d)
183+
184+
obj := model.PolicyEdgeHighAvailabilityProfile{
185+
DisplayName: &displayName,
186+
Description: &description,
187+
Tags: tags,
188+
}
189+
190+
elem := reflect.ValueOf(&obj).Elem()
191+
if err := metadata.SchemaToStruct(elem, d, policyEdgeHighAvailabilityProfileSchema, "", nil); err != nil {
192+
return err
193+
}
194+
195+
log.Printf("[INFO] Creating PolicyEdgeHighAvailabilityProfile with ID %s", id)
196+
197+
client := enforcement_points.NewEdgeClusterHighAvailabilityProfilesClient(connector)
198+
err = client.Patch(siteID, epID, id, obj)
199+
if err != nil {
200+
return handleCreateError("PolicyEdgeHighAvailabilityProfile", id, err)
201+
}
202+
d.SetId(id)
203+
d.Set("nsx_id", id)
204+
205+
return resourceNsxtPolicyEdgeHighAvailabilityProfileRead(d, m)
206+
}
207+
208+
func resourceNsxtPolicyEdgeHighAvailabilityProfileRead(d *schema.ResourceData, m interface{}) error {
209+
id, siteID, epID, err := policyIDSiteEPTuple(d, m)
210+
if err != nil {
211+
return err
212+
}
213+
214+
connector := getPolicyConnector(m)
215+
client := enforcement_points.NewEdgeClusterHighAvailabilityProfilesClient(connector)
216+
obj, err := client.Get(siteID, epID, id)
217+
if err != nil {
218+
return handleReadError(d, "PolicyEdgeHighAvailabilityProfile", id, err)
219+
}
220+
221+
setPolicyTagsInSchema(d, obj.Tags)
222+
d.Set("nsx_id", id)
223+
d.Set("display_name", obj.DisplayName)
224+
d.Set("description", obj.Description)
225+
d.Set("revision", obj.Revision)
226+
d.Set("path", obj.Path)
227+
228+
elem := reflect.ValueOf(&obj).Elem()
229+
return metadata.StructToSchema(elem, d, policyEdgeHighAvailabilityProfileSchema, "", nil)
230+
}
231+
232+
func resourceNsxtPolicyEdgeHighAvailabilityProfileUpdate(d *schema.ResourceData, m interface{}) error {
233+
id, siteID, epID, err := policyIDSiteEPTuple(d, m)
234+
if err != nil {
235+
return err
236+
}
237+
238+
description := d.Get("description").(string)
239+
displayName := d.Get("display_name").(string)
240+
tags := getPolicyTagsFromSchema(d)
241+
242+
revision := int64(d.Get("revision").(int))
243+
244+
obj := model.PolicyEdgeHighAvailabilityProfile{
245+
DisplayName: &displayName,
246+
Description: &description,
247+
Tags: tags,
248+
Revision: &revision,
249+
}
250+
251+
elem := reflect.ValueOf(&obj).Elem()
252+
if err := metadata.SchemaToStruct(elem, d, policyEdgeHighAvailabilityProfileSchema, "", nil); err != nil {
253+
return err
254+
}
255+
256+
connector := getPolicyConnector(m)
257+
client := enforcement_points.NewEdgeClusterHighAvailabilityProfilesClient(connector)
258+
_, err = client.Update(siteID, epID, id, obj)
259+
if err != nil {
260+
return handleUpdateError("PolicyEdgeHighAvailabilityProfile", id, err)
261+
}
262+
263+
return resourceNsxtPolicyEdgeHighAvailabilityProfileRead(d, m)
264+
}
265+
266+
func resourceNsxtPolicyEdgeHighAvailabilityProfileDelete(d *schema.ResourceData, m interface{}) error {
267+
id, siteID, epID, err := policyIDSiteEPTuple(d, m)
268+
if err != nil {
269+
return err
270+
}
271+
272+
connector := getPolicyConnector(m)
273+
client := enforcement_points.NewEdgeClusterHighAvailabilityProfilesClient(connector)
274+
err = client.Delete(siteID, epID, id)
275+
276+
if err != nil {
277+
return handleDeleteError("PolicyEdgeHighAvailabilityProfile", id, err)
278+
}
279+
280+
return nil
281+
}
282+
283+
func resourceNsxtPolicyEdgeHighAvailabilityProfileImporter(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
284+
importID := d.Id()
285+
rd, err := nsxtPolicyPathResourceImporterHelper(d, m)
286+
if err != nil {
287+
return rd, err
288+
}
289+
290+
epID, err := getParameterFromPolicyPath("/enforcement-points/", "/edge-cluster-high-availability-profiles/", importID)
291+
if err != nil {
292+
return nil, err
293+
}
294+
d.Set("enforcement_point", epID)
295+
sitePath, err := getSitePathFromChildResourcePath(importID)
296+
if err != nil {
297+
return rd, err
298+
}
299+
d.Set("site_path", sitePath)
300+
301+
return rd, nil
302+
}

0 commit comments

Comments
 (0)