Skip to content

Commit

Permalink
Merge pull request #835 from ksamoray/context_profile_custom_fqdns
Browse files Browse the repository at this point in the history
 Add FQDN or URL Custom support for context profile
  • Loading branch information
ksamoray authored Feb 23, 2023
2 parents 26c5a3e + 9a96959 commit 6eba95d
Show file tree
Hide file tree
Showing 12 changed files with 1,203 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
207 changes: 207 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,207 @@
/* Copyright © 2023 VMware, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"fmt"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"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 == key {
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)
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)
d.SetId(makeCustomAttributeID(key, 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"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)

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 6eba95d

Please sign in to comment.