From b019b60cbafa72d76176095691b26db939994dba Mon Sep 17 00:00:00 2001 From: Enhao Cui Date: Wed, 6 Apr 2022 15:29:28 -0700 Subject: [PATCH] Add External IDs Support for Group --- nsxt/resource_nsxt_policy_group.go | 78 +++++++++++++++++++++++ website/docs/r/policy_group.html.markdown | 14 ++++ 2 files changed, 92 insertions(+) diff --git a/nsxt/resource_nsxt_policy_group.go b/nsxt/resource_nsxt_policy_group.go index c69c1fcca..4d154358e 100644 --- a/nsxt/resource_nsxt_policy_group.go +++ b/nsxt/resource_nsxt_policy_group.go @@ -44,6 +44,13 @@ var conjunctionOperatorValues = []string{ model.ConjunctionOperator_CONJUNCTION_OPERATOR_AND, } +var externalMemberTypeValues = []string{ + model.ExternalIDExpression_MEMBER_TYPE_VIRTUALMACHINE, + model.ExternalIDExpression_MEMBER_TYPE_VIRTUALNETWORKINTERFACE, + model.ExternalIDExpression_MEMBER_TYPE_CLOUDNATIVESERVICEINSTANCE, + model.ExternalIDExpression_MEMBER_TYPE_PHYSICALSERVER, +} + func resourceNsxtPolicyGroup() *schema.Resource { return &schema.Resource{ Create: resourceNsxtPolicyGroupCreate, @@ -117,6 +124,27 @@ func getMACAddressExpressionSchema() *schema.Resource { } } +func getExternalIDExpressionSchema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "external_ids": { + Type: schema.TypeSet, + Required: true, + Description: "List of external ids", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "member_type": { + Type: schema.TypeString, + Required: true, + Description: "External ID member type", + ValidateFunc: validation.StringInSlice(externalMemberTypeValues, false), + }, + }, + } +} + func getPathExpressionSchema() *schema.Resource { return &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -226,6 +254,12 @@ func getCriteriaSetSchema() *schema.Resource { Optional: true, MaxItems: 1, }, + "external_id_expression": { + Type: schema.TypeList, + Description: "External ID expression specifying additional members in the Group", + Elem: getExternalIDExpressionSchema(), + Optional: true, + }, }, } } @@ -423,6 +457,29 @@ func buildGroupMacAddressData(ipaddr interface{}) (*data.StructValue, error) { return dataValue.(*data.StructValue), nil } +func buildGroupExternalIDExpressionData(externalId interface{}) (*data.StructValue, error) { + idMap := externalId.(map[string]interface{}) + memberType := idMap["member_type"] + var extIds []string + + for _, extId := range idMap["external_ids"].(*schema.Set).List() { + extIds = append(extIds, extId) + } + extIdStruct := model.ExternalIDExpression{ + MemberType: memberType, + ExternalIds: extIds, + ResourceType: model.ExternalIDExpression__TYPE_IDENTIFIER, + } + + converter := bindings.NewTypeConverter() + converter.SetMode(bindings.REST) + dataValue, errors := converter.ConvertToVapi(extIdStruct, model.ExternalIDExpressionBindingType()) + if errors != nil { + return nil, errors[0] + } + return dataValue.(*data.StructValue), nil +} + func buildGroupMemberPathData(paths interface{}) (*data.StructValue, error) { pathMap := paths.(map[string]interface{}) var pathList []string @@ -496,6 +553,12 @@ func buildGroupExpressionDataFromType(expressionType string, datum interface{}) return nil, err } return data, nil + } else if expressionType == "external_id_expression" { + data, err := buildGroupExternalIDExpressionData(datum) + if err != nil { + return nil, err + } + return data, nil } return nil, fmt.Errorf("Unknown expression type: %v", expressionType) } @@ -643,6 +706,21 @@ func fromGroupExpressionData(expressions []*data.StructValue) ([]map[string]inte addrList = append(addrList, addrMap) macMap["macaddress_expression"] = addrList parsedCriteria = append(parsedCriteria, macMap) + } else if expStruct.ResourceType == model.ExternalIDExpression__TYPE_IDENTIFIER { + log.Printf("[DEBUG] Parsing external id expression") + extIdData, errors := converter.ConvertToGolang(expression, model.ExternalIDExpressionBindingType()) + if len(errors) > 0 { + return nil, nil, errors[0] + } + extIdStruct := extIdData.(model.ExternalIDExpression) + var idList []map[string]interface{} + var extIdMap = make(map[string]interface{}) + extIdMap["member_type"] = extIdStruct.MemberType + extIdMap["external_ids"] = extIdStruct.ExternalIds + var idMap = make(map[string]interface{}) + idList = append(idList, extIdMap) + idMap["external_id_expression"] = idList + parsedCriteria = append(parsedCriteria, idMap) } else if expStruct.ResourceType == model.Condition__TYPE_IDENTIFIER { log.Printf("[DEBUG] Parsing condition") condMap, err := groupConditionDataToMap(expression) diff --git a/website/docs/r/policy_group.html.markdown b/website/docs/r/policy_group.html.markdown index be5b98326..2832e802d 100644 --- a/website/docs/r/policy_group.html.markdown +++ b/website/docs/r/policy_group.html.markdown @@ -53,6 +53,17 @@ resource "nsxt_policy_group" "group1" { } } + conjunction { + operator = "OR" + } + + criteria { + external_id_expression { + member_type = "VirtualMachine" + external_ids = ["520ba7b0-d9f8-87b1-6f44-15bbeb7935c7", "52748a9e-d61d-e29b-d54b-07f169ff0ee8-4000"] + } + } + extended_criteria { identity_group { distinguished_name = "cn=u1,ou=users,dc=example,dc=local" @@ -158,6 +169,9 @@ The following arguments are supported: * `mac_addresses` - (Required) List of MAC addresses. * `path_expression` - (Optional) An expression block to specify direct group members by policy path. * `member_paths` - (Required) List of policy paths for direct members for this Group (such as Segments, Segment ports, Groups etc). + * `external_id_expression` - (Optional) An expression block to specify external IDs for the specified member type for this Group. + * `member_type` - (Required) External ID member type. Must be one of: `VirtualMachine`, `VirtualNetworkInterface`, `CloudNativeServiceInstance`, or `PhysicalServer`. + * `external_ids ` - (Required) List of external IDs for the specified member type. * `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`. * `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. * `member_type` (Required) Specifies the type of resource to query. Must be one of: `IPSet`, `LogicalPort`, `LogicalSwitch`, `Segment`, `SegmentPort` or `VirtualMachine`.