github.com/vmware/go-vcloud-director/v2@v2.24.0/govcd/vdc_group.go (about)

     1  /*
     2   * Copyright 2021 VMware, Inc.  All rights reserved.  Licensed under the Apache v2 License.
     3   */
     4  
     5  package govcd
     6  
     7  import (
     8  	"fmt"
     9  	"net/url"
    10  	"strings"
    11  
    12  	"github.com/vmware/go-vcloud-director/v2/types/v56"
    13  )
    14  
    15  // VdcGroup is a structure defining a VdcGroup in Organization
    16  type VdcGroup struct {
    17  	VdcGroup *types.VdcGroup
    18  	Href     string
    19  	client   *Client
    20  	parent   organization
    21  }
    22  
    23  // CreateNsxtVdcGroup create NSX-T VDC group with provided VDC IDs.
    24  // More generic creation method available also - CreateVdcGroup
    25  func (adminOrg *AdminOrg) CreateNsxtVdcGroup(name, description, startingVdcId string, participatingVdcIds []string) (*VdcGroup, error) {
    26  	participatingVdcs, err := composeParticipatingOrgVdcs(adminOrg, startingVdcId, participatingVdcIds)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	vdcGroupConfig := &types.VdcGroup{}
    32  	vdcGroupConfig.OrgId = adminOrg.orgId()
    33  	vdcGroupConfig.Name = name
    34  	vdcGroupConfig.Description = description
    35  	vdcGroupConfig.ParticipatingOrgVdcs = participatingVdcs
    36  	vdcGroupConfig.LocalEgress = false
    37  	vdcGroupConfig.UniversalNetworkingEnabled = false
    38  	vdcGroupConfig.NetworkProviderType = "NSX_T"
    39  	vdcGroupConfig.Type = "LOCAL"
    40  	vdcGroupConfig.ParticipatingOrgVdcs = participatingVdcs
    41  	return adminOrg.CreateVdcGroup(vdcGroupConfig)
    42  }
    43  
    44  // composeParticipatingOrgVdcs converts fetched candidate VDCs to []types.ParticipatingOrgVdcs
    45  // returns error also in case participatingVdcId not found as candidate VDC.
    46  func composeParticipatingOrgVdcs(adminOrg *AdminOrg, startingVdcId string, participatingVdcIds []string) ([]types.ParticipatingOrgVdcs, error) {
    47  	candidateVdcs, err := adminOrg.GetAllNsxtVdcGroupCandidates(startingVdcId, nil)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	participatingVdcs := []types.ParticipatingOrgVdcs{}
    52  	var foundParticipatingVdcsIds []string
    53  	for _, candidateVdc := range candidateVdcs {
    54  		if contains(candidateVdc.Id, participatingVdcIds) {
    55  			participatingVdcs = append(participatingVdcs, types.ParticipatingOrgVdcs{
    56  				OrgRef:  candidateVdc.OrgRef,
    57  				SiteRef: candidateVdc.SiteRef,
    58  				VdcRef: types.OpenApiReference{
    59  					ID: candidateVdc.Id,
    60  				},
    61  				FaultDomainTag:       candidateVdc.FaultDomainTag,
    62  				NetworkProviderScope: candidateVdc.NetworkProviderScope,
    63  			})
    64  			foundParticipatingVdcsIds = append(foundParticipatingVdcsIds, candidateVdc.Id)
    65  		}
    66  	}
    67  
    68  	if len(participatingVdcs) != len(participatingVdcIds) {
    69  		var notFoundVdcs []string
    70  		for _, participatingVdcId := range participatingVdcIds {
    71  			if !contains(participatingVdcId, foundParticipatingVdcsIds) {
    72  				notFoundVdcs = append(notFoundVdcs, participatingVdcId)
    73  			}
    74  		}
    75  		return nil, fmt.Errorf("VDC IDs are not found as Candidate VDCs: %s", notFoundVdcs)
    76  	}
    77  
    78  	return participatingVdcs, nil
    79  }
    80  
    81  // contains tells whether slice of string contains item.
    82  func contains(item string, slice []string) bool {
    83  	for _, n := range slice {
    84  		if item == n {
    85  			return true
    86  		}
    87  	}
    88  	return false
    89  }
    90  
    91  // CreateVdcGroup create VDC group with provided VDC ref.
    92  // Only supports NSX-T VDCs.
    93  func (adminOrg *AdminOrg) CreateVdcGroup(vdcGroup *types.VdcGroup) (*VdcGroup, error) {
    94  	tenantContext, err := adminOrg.getTenantContext()
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	return createVdcGroup(adminOrg, vdcGroup, getTenantContextHeader(tenantContext))
    99  }
   100  
   101  // createVdcGroup create VDC group with provided VDC ref.
   102  // Only supports NSX-T VDCs.
   103  func createVdcGroup(adminOrg *AdminOrg, vdcGroup *types.VdcGroup,
   104  	additionalHeader map[string]string) (*VdcGroup, error) {
   105  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroups
   106  	apiVersion, err := adminOrg.client.checkOpenApiEndpointCompatibility(endpoint)
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  
   111  	urlRef, err := adminOrg.client.OpenApiBuildEndpoint(endpoint)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	typeResponse := &VdcGroup{
   117  		VdcGroup: &types.VdcGroup{},
   118  		client:   adminOrg.client,
   119  		Href:     urlRef.String(),
   120  		parent:   adminOrg,
   121  	}
   122  
   123  	err = adminOrg.client.OpenApiPostItem(apiVersion, urlRef, nil,
   124  		vdcGroup, typeResponse.VdcGroup, additionalHeader)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	return typeResponse, nil
   130  }
   131  
   132  // GetAllNsxtVdcGroupCandidates returns NSXT candidate VDCs for VDC group
   133  func (adminOrg *AdminOrg) GetAllNsxtVdcGroupCandidates(startingVdcId string, queryParameters url.Values) ([]*types.CandidateVdc, error) {
   134  	queryParams := copyOrNewUrlValues(queryParameters)
   135  	queryParams = queryParameterFilterAnd("_context==LOCAL", queryParams)
   136  	queryParams = queryParameterFilterAnd(fmt.Sprintf("_context==%s", startingVdcId), queryParams)
   137  	queryParams.Add("filterEncoded", "true")
   138  	queryParams.Add("links", "true")
   139  	return adminOrg.GetAllVdcGroupCandidates(queryParams)
   140  }
   141  
   142  // GetAllVdcGroupCandidates returns candidate VDCs for VDC group
   143  func (adminOrg *AdminOrg) GetAllVdcGroupCandidates(queryParameters url.Values) ([]*types.CandidateVdc, error) {
   144  	tenantContext, err := adminOrg.getTenantContext()
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsCandidateVdcs
   150  	minimumApiVersion, err := adminOrg.client.checkOpenApiEndpointCompatibility(endpoint)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  
   155  	urlRef, err := adminOrg.client.OpenApiBuildEndpoint(endpoint)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	responses := []*types.CandidateVdc{}
   161  	err = adminOrg.client.OpenApiGetAllItems(minimumApiVersion, urlRef, queryParameters, &responses, getTenantContextHeader(tenantContext))
   162  	if err != nil {
   163  		return nil, err
   164  	}
   165  
   166  	return responses, nil
   167  }
   168  
   169  // Delete deletes VDC group
   170  func (vdcGroup *VdcGroup) Delete() error {
   171  	return vdcGroup.ForceDelete(false)
   172  }
   173  
   174  // ForceDelete deletes VDC group with force parameter if enabled
   175  func (vdcGroup *VdcGroup) ForceDelete(force bool) error {
   176  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroups
   177  	minimumApiVersion, err := vdcGroup.client.checkOpenApiEndpointCompatibility(endpoint)
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	if vdcGroup.VdcGroup.Id == "" {
   183  		return fmt.Errorf("cannot delete VDC group without id")
   184  	}
   185  
   186  	urlRef, err := vdcGroup.client.OpenApiBuildEndpoint(endpoint, vdcGroup.VdcGroup.Id)
   187  	if err != nil {
   188  		return err
   189  	}
   190  
   191  	params := copyOrNewUrlValues(nil)
   192  	if force {
   193  		params.Add("force", "true")
   194  	}
   195  
   196  	err = vdcGroup.client.OpenApiDeleteItem(minimumApiVersion, urlRef, params, nil)
   197  	if err != nil {
   198  		return fmt.Errorf("error deleting VDC group (force %t): %s", force, err)
   199  	}
   200  
   201  	return nil
   202  }
   203  
   204  // GetAllVdcGroups retrieves all VDC groups. Query parameters can be supplied to perform additional filtering
   205  func (adminOrg *AdminOrg) GetAllVdcGroups(queryParameters url.Values) ([]*VdcGroup, error) {
   206  	tenantContext, err := adminOrg.getTenantContext()
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  
   211  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroups
   212  	minimumApiVersion, err := adminOrg.client.checkOpenApiEndpointCompatibility(endpoint)
   213  	if err != nil {
   214  		return nil, err
   215  	}
   216  
   217  	urlRef, err := adminOrg.client.OpenApiBuildEndpoint(endpoint)
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  
   222  	responses := []*types.VdcGroup{}
   223  	err = adminOrg.client.OpenApiGetAllItems(minimumApiVersion, urlRef, queryParameters, &responses, getTenantContextHeader(tenantContext))
   224  	if err != nil {
   225  		return nil, err
   226  	}
   227  
   228  	var wrappedVdcGroups []*VdcGroup
   229  	for _, response := range responses {
   230  		urlRef, err := adminOrg.client.OpenApiBuildEndpoint(endpoint, response.Id)
   231  		if err != nil {
   232  			return nil, err
   233  		}
   234  		wrappedVdcGroup := &VdcGroup{
   235  			VdcGroup: response,
   236  			client:   adminOrg.client,
   237  			Href:     urlRef.String(),
   238  			parent:   adminOrg,
   239  		}
   240  		wrappedVdcGroups = append(wrappedVdcGroups, wrappedVdcGroup)
   241  	}
   242  
   243  	return wrappedVdcGroups, nil
   244  }
   245  
   246  // GetVdcGroupByName retrieves VDC group by given name
   247  // When the name contains commas, semicolons or asterisks, the encoding is rejected by the API in VCD.
   248  // For this reason, when one or more commas, semicolons or asterisks are present we run the search brute force,
   249  // by fetching all VDC groups and comparing the names.
   250  // Also, url.QueryEscape as well as url.Values.Encode() both encode the space as a + character. So we use
   251  // search brute force too. Reference to issue:
   252  // https://github.com/golang/go/issues/4013
   253  // https://github.com/czos/goamz/pull/11/files
   254  func (adminOrg *AdminOrg) GetVdcGroupByName(name string) (*VdcGroup, error) {
   255  	slowSearch, params := shouldDoSlowSearch("name", name)
   256  
   257  	var foundVdcGroups []*VdcGroup
   258  	vdcGroups, err := adminOrg.GetAllVdcGroups(params)
   259  	if err != nil {
   260  		return nil, err
   261  	}
   262  	if len(vdcGroups) == 0 {
   263  		return nil, ErrorEntityNotFound
   264  	}
   265  	foundVdcGroups = append(foundVdcGroups, vdcGroups[0])
   266  
   267  	if slowSearch {
   268  		foundVdcGroups = nil
   269  		for _, vdcGroup := range vdcGroups {
   270  			if vdcGroup.VdcGroup.Name == name {
   271  				foundVdcGroups = append(foundVdcGroups, vdcGroup)
   272  			}
   273  		}
   274  		if len(foundVdcGroups) == 0 {
   275  			return nil, ErrorEntityNotFound
   276  		}
   277  		if len(foundVdcGroups) > 1 {
   278  			return nil, fmt.Errorf("more than one VDC group found with name '%s'", name)
   279  		}
   280  	}
   281  
   282  	if len(vdcGroups) > 1 && !slowSearch {
   283  		return nil, fmt.Errorf("more than one VDC group found with name '%s'", name)
   284  	}
   285  
   286  	return foundVdcGroups[0], nil
   287  }
   288  
   289  // GetVdcGroupById Returns VDC group using provided ID
   290  func (adminOrg *AdminOrg) GetVdcGroupById(id string) (*VdcGroup, error) {
   291  	tenantContext, err := adminOrg.getTenantContext()
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  
   296  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroups
   297  	minimumApiVersion, err := adminOrg.client.checkOpenApiEndpointCompatibility(endpoint)
   298  	if err != nil {
   299  		return nil, err
   300  	}
   301  
   302  	if id == "" {
   303  		return nil, fmt.Errorf("empty VDC group ID")
   304  	}
   305  
   306  	urlRef, err := adminOrg.client.OpenApiBuildEndpoint(endpoint, id)
   307  	if err != nil {
   308  		return nil, err
   309  	}
   310  
   311  	vdcGroup := &VdcGroup{
   312  		VdcGroup: &types.VdcGroup{},
   313  		client:   adminOrg.client,
   314  		Href:     urlRef.String(),
   315  		parent:   adminOrg,
   316  	}
   317  
   318  	err = adminOrg.client.OpenApiGetItem(minimumApiVersion, urlRef, nil, vdcGroup.VdcGroup, getTenantContextHeader(tenantContext))
   319  	if err != nil {
   320  		return nil, err
   321  	}
   322  
   323  	return vdcGroup, nil
   324  }
   325  
   326  // GetVdcGroupById Returns VDC group using provided ID
   327  func (org *Org) GetVdcGroupById(id string) (*VdcGroup, error) {
   328  	if id == "" {
   329  		return nil, fmt.Errorf("empty VDC group ID")
   330  	}
   331  
   332  	tenantContext, err := org.getTenantContext()
   333  	if err != nil {
   334  		return nil, err
   335  	}
   336  
   337  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroups
   338  	minimumApiVersion, err := org.client.checkOpenApiEndpointCompatibility(endpoint)
   339  	if err != nil {
   340  		return nil, err
   341  	}
   342  
   343  	urlRef, err := org.client.OpenApiBuildEndpoint(endpoint, id)
   344  	if err != nil {
   345  		return nil, err
   346  	}
   347  
   348  	vdcGroup := &VdcGroup{
   349  		VdcGroup: &types.VdcGroup{},
   350  		client:   org.client,
   351  		Href:     urlRef.String(),
   352  		parent:   org,
   353  	}
   354  
   355  	err = org.client.OpenApiGetItem(minimumApiVersion, urlRef, nil, vdcGroup.VdcGroup, getTenantContextHeader(tenantContext))
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  
   360  	return vdcGroup, nil
   361  }
   362  
   363  // Update updates existing Vdc group. Allows changing only name and description and participating VCDs
   364  // Not restrictive update method also available - GenericUpdate
   365  func (vdcGroup *VdcGroup) Update(name, description string, participatingOrgVddIs []string) (*VdcGroup, error) {
   366  
   367  	vdcGroup.VdcGroup.Name = name
   368  	vdcGroup.VdcGroup.Description = description
   369  
   370  	participatingOrgVdcs, err := composeParticipatingOrgVdcs(vdcGroup.parent.fullObject().(*AdminOrg), vdcGroup.VdcGroup.Id, participatingOrgVddIs)
   371  	if err != nil {
   372  		return nil, err
   373  	}
   374  	vdcGroup.VdcGroup.ParticipatingOrgVdcs = participatingOrgVdcs
   375  
   376  	return vdcGroup.GenericUpdate()
   377  }
   378  
   379  // GenericUpdate updates existing Vdc group. API allows changing only name and description and participating VCDs
   380  func (vdcGroup *VdcGroup) GenericUpdate() (*VdcGroup, error) {
   381  	tenantContext, err := vdcGroup.getTenantContext()
   382  	if err != nil {
   383  		return nil, err
   384  	}
   385  
   386  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroups
   387  	minimumApiVersion, err := vdcGroup.client.checkOpenApiEndpointCompatibility(endpoint)
   388  	if err != nil {
   389  		return nil, err
   390  	}
   391  
   392  	if vdcGroup.VdcGroup.Id == "" {
   393  		return nil, fmt.Errorf("cannot update VDC group without id")
   394  	}
   395  
   396  	urlRef, err := vdcGroup.client.OpenApiBuildEndpoint(endpoint, vdcGroup.VdcGroup.Id)
   397  	if err != nil {
   398  		return nil, err
   399  	}
   400  
   401  	returnVdcGroup := &VdcGroup{
   402  		VdcGroup: &types.VdcGroup{},
   403  		client:   vdcGroup.client,
   404  		Href:     vdcGroup.Href,
   405  		parent:   vdcGroup.parent,
   406  	}
   407  
   408  	err = vdcGroup.client.OpenApiPutItem(minimumApiVersion, urlRef, nil, vdcGroup.VdcGroup,
   409  		returnVdcGroup.VdcGroup, getTenantContextHeader(tenantContext))
   410  	if err != nil {
   411  		return nil, fmt.Errorf("error updating VDC group: %s", err)
   412  	}
   413  
   414  	return returnVdcGroup, nil
   415  }
   416  
   417  // UpdateDfwPolicies updates distributed firewall policies
   418  func (vdcGroup *VdcGroup) UpdateDfwPolicies(dfwPolicies types.DfwPolicies) (*VdcGroup, error) {
   419  	tenantContext, err := vdcGroup.getTenantContext()
   420  	if err != nil {
   421  		return nil, err
   422  	}
   423  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsDfwPolicies
   424  	minimumApiVersion, err := vdcGroup.client.checkOpenApiEndpointCompatibility(endpoint)
   425  	if err != nil {
   426  		return nil, err
   427  	}
   428  
   429  	if vdcGroup.VdcGroup.Id == "" {
   430  		return nil, fmt.Errorf("cannot update VDC group Dfw policies without id")
   431  	}
   432  
   433  	urlRef, err := vdcGroup.client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, vdcGroup.VdcGroup.Id))
   434  	if err != nil {
   435  		return nil, err
   436  	}
   437  
   438  	err = vdcGroup.client.OpenApiPutItem(minimumApiVersion, urlRef, nil, dfwPolicies,
   439  		nil, getTenantContextHeader(tenantContext))
   440  	if err != nil {
   441  		return nil, fmt.Errorf("error updating VDC group Dfw policies: %s", err)
   442  	}
   443  
   444  	adminOrg := vdcGroup.parent.fullObject().(*AdminOrg)
   445  	return adminOrg.GetVdcGroupById(vdcGroup.VdcGroup.Id)
   446  }
   447  
   448  // UpdateDefaultDfwPolicies updates distributed firewall default policies
   449  func (vdcGroup *VdcGroup) UpdateDefaultDfwPolicies(defaultDfwPolicies types.DefaultPolicy) (*VdcGroup, error) {
   450  	tenantContext, err := vdcGroup.getTenantContext()
   451  	if err != nil {
   452  		return nil, err
   453  	}
   454  
   455  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsDfwDefaultPolicies
   456  	minimumApiVersion, err := vdcGroup.client.checkOpenApiEndpointCompatibility(endpoint)
   457  	if err != nil {
   458  		return nil, err
   459  	}
   460  
   461  	if vdcGroup.VdcGroup.Id == "" {
   462  		return nil, fmt.Errorf("cannot update VDC group default DFW policies without id")
   463  	}
   464  
   465  	urlRef, err := vdcGroup.client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, vdcGroup.VdcGroup.Id))
   466  	if err != nil {
   467  		return nil, err
   468  	}
   469  
   470  	err = vdcGroup.client.OpenApiPutItem(minimumApiVersion, urlRef, nil, defaultDfwPolicies,
   471  		nil, getTenantContextHeader(tenantContext))
   472  	if err != nil {
   473  		return nil, fmt.Errorf("error updating VDC group default DFW policies: %s", err)
   474  	}
   475  
   476  	adminOrg := vdcGroup.parent.fullObject().(*AdminOrg)
   477  	return adminOrg.GetVdcGroupById(vdcGroup.VdcGroup.Id)
   478  }
   479  
   480  // ActivateDfw activates distributed firewall
   481  func (vdcGroup *VdcGroup) ActivateDfw() (*VdcGroup, error) {
   482  	return vdcGroup.UpdateDfwPolicies(types.DfwPolicies{
   483  		Enabled: true,
   484  	})
   485  }
   486  
   487  // DeactivateDfw deactivates distributed firewall
   488  func (vdcGroup *VdcGroup) DeactivateDfw() (*VdcGroup, error) {
   489  	return vdcGroup.UpdateDfwPolicies(types.DfwPolicies{
   490  		Enabled: false,
   491  	})
   492  }
   493  
   494  // GetDfwPolicies retrieves all distributed firewall policies
   495  func (vdcGroup *VdcGroup) GetDfwPolicies() (*types.DfwPolicies, error) {
   496  	tenantContext, err := vdcGroup.getTenantContext()
   497  	if err != nil {
   498  		return nil, err
   499  	}
   500  
   501  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcGroupsDfwPolicies
   502  	minimumApiVersion, err := vdcGroup.client.checkOpenApiEndpointCompatibility(endpoint)
   503  	if err != nil {
   504  		return nil, err
   505  	}
   506  
   507  	urlRef, err := vdcGroup.client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, vdcGroup.VdcGroup.Id))
   508  	if err != nil {
   509  		return nil, err
   510  	}
   511  
   512  	response := types.DfwPolicies{}
   513  	err = vdcGroup.client.OpenApiGetItem(minimumApiVersion, urlRef, nil, &response, getTenantContextHeader(tenantContext))
   514  	if err != nil {
   515  		return nil, err
   516  	}
   517  
   518  	return &response, nil
   519  }
   520  
   521  // EnableDefaultPolicy activates default dfw policy
   522  func (vdcGroup *VdcGroup) EnableDefaultPolicy() (*VdcGroup, error) {
   523  	dfwPolicies, err := vdcGroup.GetDfwPolicies()
   524  	if err != nil {
   525  		return nil, err
   526  	}
   527  
   528  	if dfwPolicies.DefaultPolicy == nil {
   529  		return nil, fmt.Errorf("DFW has to be enabled before changing  Default policy")
   530  	}
   531  	dfwPolicies.DefaultPolicy.Enabled = addrOf(true)
   532  	return vdcGroup.UpdateDefaultDfwPolicies(*dfwPolicies.DefaultPolicy)
   533  }
   534  
   535  // DisableDefaultPolicy deactivates default dfw policy
   536  func (vdcGroup *VdcGroup) DisableDefaultPolicy() (*VdcGroup, error) {
   537  	dfwPolicies, err := vdcGroup.GetDfwPolicies()
   538  	if err != nil {
   539  		return nil, err
   540  	}
   541  
   542  	if dfwPolicies.DefaultPolicy == nil {
   543  		return nil, fmt.Errorf("DFW has to be enabled before changing Default policy")
   544  	}
   545  	dfwPolicies.DefaultPolicy.Enabled = addrOf(false)
   546  	return vdcGroup.UpdateDefaultDfwPolicies(*dfwPolicies.DefaultPolicy)
   547  }
   548  
   549  func getOwnerTypeFromUrn(urn string) (string, error) {
   550  	if !isUrn(urn) {
   551  		return "", fmt.Errorf("supplied ID is not URN: %s", urn)
   552  	}
   553  
   554  	ss := strings.Split(urn, ":")
   555  	return ss[2], nil
   556  }
   557  
   558  // OwnerIsVdcGroup evaluates given URN and returns true if it is a VDC Group
   559  func OwnerIsVdcGroup(urn string) bool {
   560  	ownerType, err := getOwnerTypeFromUrn(urn)
   561  	if err != nil {
   562  		return false
   563  	}
   564  
   565  	if strings.EqualFold(ownerType, types.UrnTypeVdcGroup) {
   566  		return true
   567  	}
   568  
   569  	return false
   570  }
   571  
   572  // OwnerIsVdc evaluates a given URN and returns true if it is a VDC
   573  func OwnerIsVdc(urn string) bool {
   574  	ownerType, err := getOwnerTypeFromUrn(urn)
   575  	if err != nil {
   576  		return false
   577  	}
   578  
   579  	if strings.EqualFold(ownerType, types.UrnTypeVdc) {
   580  		return true
   581  	}
   582  
   583  	return false
   584  }
   585  
   586  // GetCapabilities allows to retrieve a list of VDC capabilities. It has a list of values. Some particularly useful are:
   587  // * networkProvider - overlay stack responsible for providing network functionality. (NSX_V or NSX_T)
   588  // * crossVdc - supports cross vDC network creation
   589  func (vdcGroup *VdcGroup) GetCapabilities() ([]types.VdcCapability, error) {
   590  	if vdcGroup.VdcGroup.Id == "" {
   591  		return nil, fmt.Errorf("VDC ID must be set to get capabilities")
   592  	}
   593  
   594  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcCapabilities
   595  	minimumApiVersion, err := vdcGroup.client.checkOpenApiEndpointCompatibility(endpoint)
   596  	if err != nil {
   597  		return nil, err
   598  	}
   599  
   600  	urlRef, err := vdcGroup.client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, url.QueryEscape(vdcGroup.VdcGroup.Id)))
   601  	if err != nil {
   602  		return nil, err
   603  	}
   604  
   605  	capabilities := make([]types.VdcCapability, 0)
   606  	err = vdcGroup.client.OpenApiGetAllItems(minimumApiVersion, urlRef, nil, &capabilities, nil)
   607  	if err != nil {
   608  		return nil, err
   609  	}
   610  	return capabilities, nil
   611  }
   612  
   613  // IsNsxt is a convenience function to check if VDC is backed by NSX-T pVdc
   614  // If error occurs - it returns false
   615  func (vdcGroup *VdcGroup) IsNsxt() bool {
   616  	vdcCapabilities, err := vdcGroup.GetCapabilities()
   617  	if err != nil {
   618  		return false
   619  	}
   620  
   621  	networkProviderCapability := getCapabilityValue(vdcCapabilities, "networkProvider")
   622  	return networkProviderCapability == types.VdcCapabilityNetworkProviderNsxt
   623  }