Skip to content

Commit

Permalink
Add custom FQDN support for context profiles
Browse files Browse the repository at this point in the history
To allow addition of custom FQDNs to context profile objects.

Signed-off-by: Kobi Samoray <[email protected]>
  • Loading branch information
ksamoray committed Feb 9, 2023
1 parent e686f0a commit d9bcff2
Show file tree
Hide file tree
Showing 12 changed files with 1,205 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dist/
.idea/
1 change: 1 addition & 0 deletions nsxt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ func Provider() *schema.Provider {
"nsxt_policy_l2_vpn_service": resourceNsxtPolicyL2VpnService(),
"nsxt_policy_ipsec_vpn_local_endpoint": resourceNsxtPolicyIPSecVpnLocalEndpoint(),
"nsxt_policy_ip_discovery_profile": resourceNsxtPolicyIPDiscoveryProfile(),
"nsxt_policy_context_profile_custom_attribute": resourceNsxtPolicyContextProfileCustomAttribute(),
},

ConfigureFunc: providerConfigure,
Expand Down
209 changes: 209 additions & 0 deletions nsxt/resource_nsxt_policy_context_profile_custom_attribute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/* Copyright © 2023 VMware, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/vmware/vsphere-automation-sdk-go/lib/vapi/std/errors"
"github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client"
gm_infra "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra/context_profiles/custom_attributes"
gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model"
infra "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/context_profiles/custom_attributes"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)

var customAttributeKeys = []string{
model.PolicyCustomAttributes_KEY_DOMAIN_NAME,
model.PolicyCustomAttributes_KEY_CUSTOM_URL,
}

func splitCustomAttributeId(id string) (string, string) {
s := strings.Split(id, "~")
return s[0], s[1]
}

func makeCustomAttributeId(key string, attribute string) string {
return fmt.Sprintf("%s~%s", key, attribute)
}

func resourceNsxtPolicyContextProfileCustomAttribute() *schema.Resource {
return &schema.Resource{
Create: resourceNsxtPolicyContextProfileCustomAttributeCreate,
Read: resourceNsxtPolicyContextProfileCustomAttributeRead,
Delete: resourceNsxtPolicyContextProfileCustomAttributeDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Description: "Key for attribute",
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice(customAttributeKeys, false),
},
"attribute": {
Type: schema.TypeString,
Description: "Custom Attribute",
Required: true,
ForceNew: true,
},
},
}
}

func resourceNsxtPolicyContextProfileCustomAttributeExists(id string, connector *client.RestConnector, isGlobalmodel bool) (bool, error) {
var err error
var attrList model.PolicyContextProfileListResult

key, attribute := splitCustomAttributeId(id)
source := model.PolicyCustomAttributes_ATTRIBUTE_SOURCE_CUSTOM
if isGlobalmodel {
var gmAttrList gm_model.PolicyContextProfileListResult
client := gm_infra.NewDefaultClient(connector)
gmAttrList, err = client.List(&key, &source, nil, nil, nil, nil, nil, nil)

al, err1 := convertModelBindingType(gmAttrList, gm_model.PolicyContextProfileListResultBindingType(), model.PolicyContextProfileListResultBindingType())
if err1 != nil {
return false, err1
}

attrList = al.(model.PolicyContextProfileListResult)
} else {
client := infra.NewDefaultClient(connector)
attrList, err = client.List(&key, &source, nil, nil, nil, nil, nil, nil)
if err != nil {
return false, err
}
}

if *attrList.ResultCount == 0 {
return false, nil
}
if isNotFoundError(err) {
return false, nil
}

if err == nil {
for _, c := range attrList.Results {
for _, a := range c.Attributes {
if *a.Key == model.PolicyCustomAttributes_KEY_DOMAIN_NAME {
for _, v := range a.Value {
if v == attribute {
return true, nil
}
}
}
}
}
}

return false, err
}

func resourceNsxtPolicyContextProfileCustomAttributeRead(d *schema.ResourceData, m interface{}) error {
id := d.Id()
key, attribute := splitCustomAttributeId(id)

log.Printf("[INFO] Reading ContextProfileCustomAttribute with ID %s", d.Id())

connector := getPolicyConnector(m)
exists, err := resourceNsxtPolicyContextProfileCustomAttributeExists(id, connector, isPolicyGlobalManager(m))
if err != nil {
return err
}
if !exists {
return errors.NotFound{}
}
d.Set("key", key)
d.Set("attribute", attribute)
return nil
}

func resourceNsxtPolicyContextProfileCustomAttributeCreate(d *schema.ResourceData, m interface{}) error {
var err error
key := d.Get("key").(string)
attribute := d.Get("attribute").(string)
if d.Id() == "" {
d.SetId(makeCustomAttributeId(key, attribute))
}
attributes := []string{attribute}
log.Printf("[INFO] Creating ContextProfileCustomAttribute with ID %s", attribute)

connector := getPolicyConnector(m)

dataTypeString := model.PolicyCustomAttributes_DATATYPE_STRING
obj := model.PolicyCustomAttributes{
Datatype: &dataTypeString,
Key: &key,
Value: attributes,
}

// PATCH the resource
if isPolicyGlobalManager(m) {
gmObj, err1 := convertModelBindingType(obj, model.PolicyCustomAttributesBindingType(), gm_model.PolicyCustomAttributesBindingType())
if err1 != nil {
return err1
}

client := gm_infra.NewDefaultClient(connector)
err = client.Create(gmObj.(gm_model.PolicyCustomAttributes), "add")
} else {
client := infra.NewDefaultClient(connector)
err = client.Create(obj, "add")
}
if err != nil {
return handleCreateError("ContextProfileCustomAttribute", attribute, err)
}

d.Set("key", key)
d.Set("attribute", attribute)

return resourceNsxtPolicyContextProfileCustomAttributeRead(d, m)
}

func resourceNsxtPolicyContextProfileCustomAttributeDelete(d *schema.ResourceData, m interface{}) error {
key, attribute := splitCustomAttributeId(d.Id())
log.Printf("[INFO] Deleting ContextProfileCustomAttribute with ID %s", attribute)
attributes := []string{attribute}
err := resourceNsxtPolicyContextProfileCustomAttributeRead(d, m)

if err != nil {
return err
}

connector := getPolicyConnector(m)

dataTypeString := model.PolicyCustomAttributes_DATATYPE_STRING
obj := model.PolicyCustomAttributes{
Datatype: &dataTypeString,
Key: &key,
Value: attributes,
}

// PATCH the resource
if isPolicyGlobalManager(m) {
gmObj, err1 := convertModelBindingType(obj, model.PolicyCustomAttributesBindingType(), gm_model.PolicyCustomAttributesBindingType())
if err1 != nil {
return err1
}

client := gm_infra.NewDefaultClient(connector)
err = client.Create(gmObj.(gm_model.PolicyCustomAttributes), "remove")
} else {
client := infra.NewDefaultClient(connector)
err = client.Create(obj, "remove")
}

if err != nil {
return handleDeleteError("ContextProfileCustomAttribute", attribute, err)
}
return err
}
119 changes: 119 additions & 0 deletions nsxt/resource_nsxt_policy_context_profile_custom_attribute_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* Copyright © 2023 VMware, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"fmt"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

var accTestPolicyContextProfileCustomAttributeAttributes = map[string]string{
"key": model.PolicyCustomAttributes_KEY_DOMAIN_NAME,
"attribute": "test.fqdn.org",
}

func TestAccResourceNsxtPolicyContextProfileCustomAttribute_basic(t *testing.T) {
testResourceName := "nsxt_policy_context_profile_custom_attribute.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: func(state *terraform.State) error {
return testAccNsxtPolicyContextProfileCustomAttributeCheckDestroy(state, accTestPolicyContextProfileCustomAttributeAttributes["attribute"])
},
Steps: []resource.TestStep{
{
Config: testAccNsxtPolicyContextProfileCustomAttributeTemplate(),
Check: resource.ComposeTestCheckFunc(
testAccNsxtPolicyContextProfileCustomAttributeExists(accTestPolicyContextProfileCustomAttributeAttributes["attribute"], testResourceName),
resource.TestCheckResourceAttr(testResourceName, "key", accTestPolicyContextProfileCustomAttributeAttributes["key"]),
resource.TestCheckResourceAttr(testResourceName, "attribute", accTestPolicyContextProfileCustomAttributeAttributes["attribute"]),
),
},
},
})
}

func TestAccResourceNsxtPolicyContextProfileCustomAttribute_importBasic(t *testing.T) {
name := getAccTestResourceName()
testResourceName := "nsxt_policy_context_profile_custom_attribute.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: func(state *terraform.State) error {
return testAccNsxtPolicyContextProfileCustomAttributeCheckDestroy(state, name)
},
Steps: []resource.TestStep{
{
Config: testAccNsxtPolicyContextProfileCustomAttributeTemplate(),
},
{
ResourceName: testResourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccNsxtPolicyContextProfileCustomAttributeExists(displayName string, resourceName string) resource.TestCheckFunc {
return func(state *terraform.State) error {

connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients))

rs, ok := state.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("Policy ContextProfileCustomAttribute resource %s not found in resources", resourceName)
}

resourceID := rs.Primary.ID
if resourceID == "" {
return fmt.Errorf("Policy ContextProfileCustomAttribute resource ID not set in resources")
}

exists, err := resourceNsxtPolicyContextProfileCustomAttributeExists(resourceID, connector, testAccIsGlobalManager())
if err != nil {
return err
}
if !exists {
return fmt.Errorf("Policy ContextProfileCustomAttribute %s does not exist", resourceID)
}

return nil
}
}

func testAccNsxtPolicyContextProfileCustomAttributeCheckDestroy(state *terraform.State, attribute string) error {
connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients))
for _, rs := range state.RootModule().Resources {

if rs.Type != "nsxt_policy_context_profile_custom_attribute" {
continue
}

resourceID := makeCustomAttributeId(model.PolicyCustomAttributes_KEY_DOMAIN_NAME, rs.Primary.Attributes["attribute"])
exists, err := resourceNsxtPolicyContextProfileCustomAttributeExists(resourceID, connector, testAccIsGlobalManager())
if err == nil {
return err
}

if exists {
return fmt.Errorf("Policy ContextProfileCustomAttribute %s still exists", attribute)
}
}
return nil
}

func testAccNsxtPolicyContextProfileCustomAttributeTemplate() string {
return fmt.Sprintf(`
resource "nsxt_policy_context_profile_custom_attribute" "test" {
key = "%s"
attribute = "%s"
}`, accTestPolicyContextProfileCustomAttributeAttributes["key"], accTestPolicyContextProfileCustomAttributeAttributes["attribute"])
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d9bcff2

Please sign in to comment.