Skip to content

Commit f9c3a64

Browse files
authored
Merge pull request #733 from vmware/group_ext_id
Add External IDs Support for Group
2 parents c3169fb + c99582d commit f9c3a64

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

nsxt/resource_nsxt_policy_group.go

+79
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ var conjunctionOperatorValues = []string{
4444
model.ConjunctionOperator_CONJUNCTION_OPERATOR_AND,
4545
}
4646

47+
var externalMemberTypeValues = []string{
48+
model.ExternalIDExpression_MEMBER_TYPE_VIRTUALMACHINE,
49+
model.ExternalIDExpression_MEMBER_TYPE_VIRTUALNETWORKINTERFACE,
50+
model.ExternalIDExpression_MEMBER_TYPE_CLOUDNATIVESERVICEINSTANCE,
51+
model.ExternalIDExpression_MEMBER_TYPE_PHYSICALSERVER,
52+
}
53+
4754
func resourceNsxtPolicyGroup() *schema.Resource {
4855
return &schema.Resource{
4956
Create: resourceNsxtPolicyGroupCreate,
@@ -117,6 +124,28 @@ func getMACAddressExpressionSchema() *schema.Resource {
117124
}
118125
}
119126

127+
func getExternalIDExpressionSchema() *schema.Resource {
128+
return &schema.Resource{
129+
Schema: map[string]*schema.Schema{
130+
"external_ids": {
131+
Type: schema.TypeSet,
132+
Required: true,
133+
Description: "List of external IDs",
134+
Elem: &schema.Schema{
135+
Type: schema.TypeString,
136+
},
137+
},
138+
"member_type": {
139+
Type: schema.TypeString,
140+
Optional: true,
141+
Description: "External ID member type, default to virtual machine if not specified",
142+
ValidateFunc: validation.StringInSlice(externalMemberTypeValues, false),
143+
Default: model.ExternalIDExpression_MEMBER_TYPE_VIRTUALMACHINE,
144+
},
145+
},
146+
}
147+
}
148+
120149
func getPathExpressionSchema() *schema.Resource {
121150
return &schema.Resource{
122151
Schema: map[string]*schema.Schema{
@@ -226,6 +255,12 @@ func getCriteriaSetSchema() *schema.Resource {
226255
Optional: true,
227256
MaxItems: 1,
228257
},
258+
"external_id_expression": {
259+
Type: schema.TypeList,
260+
Description: "External ID expression specifying additional members in the Group",
261+
Elem: getExternalIDExpressionSchema(),
262+
Optional: true,
263+
},
229264
},
230265
}
231266
}
@@ -423,6 +458,29 @@ func buildGroupMacAddressData(ipaddr interface{}) (*data.StructValue, error) {
423458
return dataValue.(*data.StructValue), nil
424459
}
425460

461+
func buildGroupExternalIDExpressionData(externalID interface{}) (*data.StructValue, error) {
462+
idMap := externalID.(map[string]interface{})
463+
memberType := idMap["member_type"].(string)
464+
var extIDs []string
465+
466+
for _, extID := range idMap["external_ids"].(*schema.Set).List() {
467+
extIDs = append(extIDs, extID.(string))
468+
}
469+
extIDStruct := model.ExternalIDExpression{
470+
MemberType: &memberType,
471+
ExternalIds: extIDs,
472+
ResourceType: model.ExternalIDExpression__TYPE_IDENTIFIER,
473+
}
474+
475+
converter := bindings.NewTypeConverter()
476+
converter.SetMode(bindings.REST)
477+
dataValue, errors := converter.ConvertToVapi(extIDStruct, model.ExternalIDExpressionBindingType())
478+
if errors != nil {
479+
return nil, errors[0]
480+
}
481+
return dataValue.(*data.StructValue), nil
482+
}
483+
426484
func buildGroupMemberPathData(paths interface{}) (*data.StructValue, error) {
427485
pathMap := paths.(map[string]interface{})
428486
var pathList []string
@@ -496,6 +554,12 @@ func buildGroupExpressionDataFromType(expressionType string, datum interface{})
496554
return nil, err
497555
}
498556
return data, nil
557+
} else if expressionType == "external_id_expression" {
558+
data, err := buildGroupExternalIDExpressionData(datum)
559+
if err != nil {
560+
return nil, err
561+
}
562+
return data, nil
499563
}
500564
return nil, fmt.Errorf("Unknown expression type: %v", expressionType)
501565
}
@@ -643,6 +707,21 @@ func fromGroupExpressionData(expressions []*data.StructValue) ([]map[string]inte
643707
addrList = append(addrList, addrMap)
644708
macMap["macaddress_expression"] = addrList
645709
parsedCriteria = append(parsedCriteria, macMap)
710+
} else if expStruct.ResourceType == model.ExternalIDExpression__TYPE_IDENTIFIER {
711+
log.Printf("[DEBUG] Parsing external id expression")
712+
extIDData, errors := converter.ConvertToGolang(expression, model.ExternalIDExpressionBindingType())
713+
if len(errors) > 0 {
714+
return nil, nil, errors[0]
715+
}
716+
extIDStruct := extIDData.(model.ExternalIDExpression)
717+
var idList []map[string]interface{}
718+
var extIDMap = make(map[string]interface{})
719+
extIDMap["member_type"] = extIDStruct.MemberType
720+
extIDMap["external_ids"] = extIDStruct.ExternalIds
721+
var idMap = make(map[string]interface{})
722+
idList = append(idList, extIDMap)
723+
idMap["external_id_expression"] = idList
724+
parsedCriteria = append(parsedCriteria, idMap)
646725
} else if expStruct.ResourceType == model.Condition__TYPE_IDENTIFIER {
647726
log.Printf("[DEBUG] Parsing condition")
648727
condMap, err := groupConditionDataToMap(expression)

nsxt/resource_nsxt_policy_group_test.go

+99
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,52 @@ func TestAccResourceNsxtGlobalPolicyGroup_singleIPAddressCriteria(t *testing.T)
131131
})
132132
}
133133

134+
func TestAccResourceNsxtGlobalPolicyGroup_externalIDCriteria(t *testing.T) {
135+
name := getAccTestResourceName()
136+
updatedName := getAccTestResourceName()
137+
testResourceName := "nsxt_policy_group.test"
138+
139+
resource.ParallelTest(t, resource.TestCase{
140+
PreCheck: func() {
141+
testAccPreCheck(t)
142+
},
143+
Providers: testAccProviders,
144+
CheckDestroy: func(state *terraform.State) error {
145+
return testAccNsxtPolicyGroupCheckDestroy(state, updatedName, defaultDomain)
146+
},
147+
Steps: []resource.TestStep{
148+
{
149+
Config: testAccNsxtPolicyGroupExternalIDCreateTemplate(name, defaultDomain),
150+
Check: resource.ComposeTestCheckFunc(
151+
testAccNsxtPolicyGroupExists(testResourceName, defaultDomain),
152+
resource.TestCheckResourceAttr(testResourceName, "display_name", name),
153+
resource.TestCheckResourceAttr(testResourceName, "description", "Acceptance Test"),
154+
resource.TestCheckResourceAttr(testResourceName, "domain", defaultDomain),
155+
resource.TestCheckResourceAttrSet(testResourceName, "path"),
156+
resource.TestCheckResourceAttrSet(testResourceName, "revision"),
157+
resource.TestCheckResourceAttr(testResourceName, "conjunction.#", "0"),
158+
resource.TestCheckResourceAttr(testResourceName, "tag.#", "2"),
159+
resource.TestCheckResourceAttr(testResourceName, "criteria.#", "1"),
160+
),
161+
},
162+
{
163+
Config: testAccNsxtPolicyGroupExternalIDUpdateTemplate(updatedName, defaultDomain),
164+
Check: resource.ComposeTestCheckFunc(
165+
testAccNsxtPolicyGroupExists(testResourceName, defaultDomain),
166+
resource.TestCheckResourceAttr(testResourceName, "display_name", updatedName),
167+
resource.TestCheckResourceAttr(testResourceName, "description", "Acceptance Test"),
168+
resource.TestCheckResourceAttr(testResourceName, "domain", defaultDomain),
169+
resource.TestCheckResourceAttrSet(testResourceName, "path"),
170+
resource.TestCheckResourceAttrSet(testResourceName, "revision"),
171+
resource.TestCheckResourceAttr(testResourceName, "conjunction.#", "1"),
172+
resource.TestCheckResourceAttr(testResourceName, "tag.#", "0"),
173+
resource.TestCheckResourceAttr(testResourceName, "criteria.#", "2"),
174+
),
175+
},
176+
},
177+
})
178+
}
179+
134180
func TestAccResourceNsxtGlobalPolicyGroup_withDomain(t *testing.T) {
135181
name := "test-nsx-global-policy-group-domain"
136182
testResourceName := "nsxt_policy_group.test"
@@ -778,6 +824,59 @@ resource "nsxt_policy_group" "test" {
778824
`, name)
779825
}
780826

827+
func testAccNsxtPolicyGroupExternalIDCreateTemplate(name string, siteName string) string {
828+
return fmt.Sprintf(`
829+
resource "nsxt_policy_group" "test" {
830+
display_name = "%s"
831+
description = "Acceptance Test"
832+
833+
criteria {
834+
external_id_expression {
835+
member_type = "VirtualMachine"
836+
external_ids = ["520ba7b0-d9f8-87b1-6f44-15bbeb7935c7", "52748a9e-d61d-e29b-d54b-07f169ff0ee8-4000"]
837+
}
838+
}
839+
840+
tag {
841+
scope = "scope1"
842+
tag = "tag1"
843+
}
844+
845+
tag {
846+
scope = "scope2"
847+
tag = "tag2"
848+
}
849+
}
850+
`, name)
851+
}
852+
853+
func testAccNsxtPolicyGroupExternalIDUpdateTemplate(name string, siteName string) string {
854+
return fmt.Sprintf(`
855+
resource "nsxt_policy_group" "test" {
856+
display_name = "%s"
857+
description = "Acceptance Test"
858+
859+
criteria {
860+
external_id_expression {
861+
member_type = "VirtualMachine"
862+
external_ids = ["520ba7b0-d9f8-87b1-6f44-15bbeb7935c7", "52748a9e-d61d-e29b-d54b-07f169ff0ee8-4000"]
863+
}
864+
}
865+
866+
conjunction {
867+
operator = "OR"
868+
}
869+
870+
criteria {
871+
external_id_expression {
872+
member_type = "VirtualNetworkInterface"
873+
external_ids = ["520ba7b0-d9f8-87b1-6f44-15bbeb7935c7", "52748a9e-d61d-e29b-d54b-07f169ff0ee8-4000"]
874+
}
875+
}
876+
}
877+
`, name)
878+
}
879+
781880
func testAccNsxtPolicyGroupPathsPrerequisites() string {
782881
var preRequisites string
783882
if testAccIsGlobalManager() {

website/docs/r/policy_group.html.markdown

+14
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ resource "nsxt_policy_group" "group1" {
5353
}
5454
}
5555
56+
conjunction {
57+
operator = "OR"
58+
}
59+
60+
criteria {
61+
external_id_expression {
62+
member_type = "VirtualMachine"
63+
external_ids = ["520ba7b0-d9f8-87b1-6f44-15bbeb7935c7", "52748a9e-d61d-e29b-d54b-07f169ff0ee8-4000"]
64+
}
65+
}
66+
5667
extended_criteria {
5768
identity_group {
5869
distinguished_name = "cn=u1,ou=users,dc=example,dc=local"
@@ -158,6 +169,9 @@ The following arguments are supported:
158169
* `mac_addresses` - (Required) List of MAC addresses.
159170
* `path_expression` - (Optional) An expression block to specify direct group members by policy path.
160171
* `member_paths` - (Required) List of policy paths for direct members for this Group (such as Segments, Segment ports, Groups etc).
172+
* `external_id_expression` - (Optional) An expression block to specify external IDs for the specified member type for this Group.
173+
* `member_type` - (Optional) External ID member type. Must be one of: `VirtualMachine`, `VirtualNetworkInterface`, `CloudNativeServiceInstance`, or `PhysicalServer`. Defaults to `VirtualMachine`.
174+
* `external_ids` - (Required) List of external IDs for the specified member type.
161175
* `condition` (Optional) A repeatable condition block to select this Group's members. When multiple `condition` blocks are used in a single `criteria` they form a nested expression that's implicitly ANDed together and each nested condition must used the same `member_type`.
162176
* `key` (Required) Specifies the attribute to query. Must be one of: `Tag`, `ComputerName`, `OSName` or `Name`. For a `member_type` other than `VirtualMachine`, only the `Tag` key is supported.
163177
* `member_type` (Required) Specifies the type of resource to query. Must be one of: `IPSet`, `LogicalPort`, `LogicalSwitch`, `Segment`, `SegmentPort` or `VirtualMachine`.

0 commit comments

Comments
 (0)