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

     1  /*
     2   * Copyright 2022 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  
    11  	"github.com/vmware/go-vcloud-director/v2/types/v56"
    12  )
    13  
    14  // EdgeBgpNeighbor represents NSX-T Edge Gateway BGP Neighbor
    15  type EdgeBgpNeighbor struct {
    16  	EdgeBgpNeighbor *types.EdgeBgpNeighbor
    17  	client          *Client
    18  	// edgeGatewayId is stored for usage in EdgeBgpNeighbor receiver functions
    19  	edgeGatewayId string
    20  }
    21  
    22  // CreateBgpNeighbor creates BGP Neighbor with the given configuration
    23  func (egw *NsxtEdgeGateway) CreateBgpNeighbor(bgpNeighborConfig *types.EdgeBgpNeighbor) (*EdgeBgpNeighbor, error) {
    24  	client := egw.client
    25  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpNeighbor
    26  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	// Insert Edge Gateway ID into endpoint path
    32  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	returnObject := &EdgeBgpNeighbor{
    38  		client:          egw.client,
    39  		edgeGatewayId:   egw.EdgeGateway.ID,
    40  		EdgeBgpNeighbor: &types.EdgeBgpNeighbor{},
    41  	}
    42  
    43  	task, err := client.OpenApiPostItemAsync(apiVersion, urlRef, nil, bgpNeighborConfig)
    44  	if err != nil {
    45  		return nil, fmt.Errorf("error creating NSX-T Edge Gateway BGP Neighbor: %s", err)
    46  	}
    47  
    48  	err = task.WaitTaskCompletion()
    49  	if err != nil {
    50  		return nil, fmt.Errorf("error creating NSX-T Edge Gateway BGP Neighbor: %s", err)
    51  	}
    52  
    53  	// API has problems therefore explicit manual handling is required to lookup newly created object
    54  	// VCD 10.2 -> no ID for newly created object is returned at all
    55  	// VCD 10.3 -> `Details` field in task contains ID of newly created object
    56  	// To cover all cases this code will at first look for ID in `Details` field and fall back to
    57  	// lookup by name if `Details` field is empty.
    58  	//
    59  	// The drawback of this is that it is possible to create duplicate records with the same name on VCDs that don't
    60  	// return IDs, but there is no better way for VCD versions that don't return API code
    61  
    62  	bgpNeighborId := task.Task.Details
    63  	if bgpNeighborId != "" {
    64  		getUrlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID), bgpNeighborId)
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  		err = client.OpenApiGetItem(apiVersion, getUrlRef, nil, returnObject.EdgeBgpNeighbor, nil)
    69  		if err != nil {
    70  			return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway BGP Neighbor after creation: %s", err)
    71  		}
    72  	} else {
    73  		// ID after object creation was not returned therefore retrieving the entity by Name to lookup ID
    74  		// This has a risk of duplicate items, but is the only way to find the object when ID is not returned
    75  		bgpNeighbor, err := egw.GetBgpNeighborByIp(bgpNeighborConfig.NeighborAddress)
    76  		if err != nil {
    77  			return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway BGP Neighbor after creation: %s", err)
    78  		}
    79  		returnObject = bgpNeighbor
    80  	}
    81  
    82  	return returnObject, nil
    83  }
    84  
    85  // GetAllBgpNeighbors retrieves all BGP Neighbors with an optional filter
    86  func (egw *NsxtEdgeGateway) GetAllBgpNeighbors(queryParameters url.Values) ([]*EdgeBgpNeighbor, error) {
    87  	queryParams := copyOrNewUrlValues(queryParameters)
    88  
    89  	client := egw.client
    90  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpNeighbor
    91  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	// Insert Edge Gateway ID into endpoint path
    97  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID))
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	typeResponses := []*types.EdgeBgpNeighbor{{}}
   103  	err = client.OpenApiGetAllItems(apiVersion, urlRef, queryParams, &typeResponses, nil)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	wrappedResponses := make([]*EdgeBgpNeighbor, len(typeResponses))
   109  	for sliceIndex := range typeResponses {
   110  		wrappedResponses[sliceIndex] = &EdgeBgpNeighbor{
   111  			EdgeBgpNeighbor: typeResponses[sliceIndex],
   112  			client:          client,
   113  			edgeGatewayId:   egw.EdgeGateway.ID,
   114  		}
   115  	}
   116  
   117  	return wrappedResponses, nil
   118  }
   119  
   120  // GetBgpNeighborByIp retrieves BGP Neighbor by Neighbor IP address
   121  // It is meant to retrieve exactly one entry:
   122  // * Will fail if more than one entry with the same Neighbor IP found (should not happen as uniqueness is
   123  // enforced by API)
   124  // * Will return an error containing `ErrorEntityNotFound` if no entries are found
   125  //
   126  // Note. API does not support filtering by 'neighborIpAddress' field therefore filtering is performed on client
   127  // side
   128  func (egw *NsxtEdgeGateway) GetBgpNeighborByIp(neighborIpAddress string) (*EdgeBgpNeighbor, error) {
   129  	if neighborIpAddress == "" {
   130  		return nil, fmt.Errorf("neighborIpAddress cannot be empty")
   131  	}
   132  
   133  	allBgpNeighbors, err := egw.GetAllBgpNeighbors(nil)
   134  	if err != nil {
   135  		return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway BGP Neighbor: %s", err)
   136  	}
   137  
   138  	var filteredBgpNeighbors []*EdgeBgpNeighbor
   139  	for _, bgpNeighbor := range allBgpNeighbors {
   140  		if bgpNeighbor.EdgeBgpNeighbor.NeighborAddress == neighborIpAddress {
   141  			filteredBgpNeighbors = append(filteredBgpNeighbors, bgpNeighbor)
   142  		}
   143  	}
   144  
   145  	if len(filteredBgpNeighbors) > 1 {
   146  		return nil, fmt.Errorf("more than one NSX-T Edge Gateway BGP Neighbor found with IP Address '%s'", neighborIpAddress)
   147  	}
   148  
   149  	if len(filteredBgpNeighbors) == 0 {
   150  		return nil, fmt.Errorf("%s: no NSX-T Edge Gateway BGP Neighbor found with IP Address '%s'", ErrorEntityNotFound, neighborIpAddress)
   151  	}
   152  
   153  	return filteredBgpNeighbors[0], nil
   154  }
   155  
   156  // GetBgpNeighborById retrieves BGP Neighbor By ID
   157  func (egw *NsxtEdgeGateway) GetBgpNeighborById(id string) (*EdgeBgpNeighbor, error) {
   158  	if id == "" {
   159  		return nil, fmt.Errorf("id is required")
   160  	}
   161  
   162  	client := egw.client
   163  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpNeighbor
   164  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
   165  	if err != nil {
   166  		return nil, err
   167  	}
   168  
   169  	// Insert Edge Gateway ID into endpoint path
   170  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, egw.EdgeGateway.ID), id)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  
   175  	returnObject := &EdgeBgpNeighbor{
   176  		client:          egw.client,
   177  		edgeGatewayId:   egw.EdgeGateway.ID,
   178  		EdgeBgpNeighbor: &types.EdgeBgpNeighbor{},
   179  	}
   180  
   181  	err = client.OpenApiGetItem(apiVersion, urlRef, nil, returnObject.EdgeBgpNeighbor, nil)
   182  	if err != nil {
   183  		return nil, fmt.Errorf("error retrieving NSX-T Edge Gateway BGP Neighbor: %s", err)
   184  	}
   185  
   186  	return returnObject, nil
   187  }
   188  
   189  // Update updates existing BGP Neighbor with new configuration and returns it
   190  func (bgpNeighbor *EdgeBgpNeighbor) Update(bgpNeighborConfig *types.EdgeBgpNeighbor) (*EdgeBgpNeighbor, error) {
   191  	client := bgpNeighbor.client
   192  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpNeighbor
   193  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
   194  	if err != nil {
   195  		return nil, err
   196  	}
   197  
   198  	// Insert Edge Gateway ID into endpoint path
   199  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, bgpNeighbor.edgeGatewayId), bgpNeighborConfig.ID)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	returnObject := &EdgeBgpNeighbor{
   205  		client:          bgpNeighbor.client,
   206  		edgeGatewayId:   bgpNeighbor.edgeGatewayId,
   207  		EdgeBgpNeighbor: &types.EdgeBgpNeighbor{},
   208  	}
   209  
   210  	err = client.OpenApiPutItem(apiVersion, urlRef, nil, bgpNeighborConfig, returnObject.EdgeBgpNeighbor, nil)
   211  	if err != nil {
   212  		return nil, fmt.Errorf("error setting NSX-T Edge Gateway BGP Neighbor: %s", err)
   213  	}
   214  
   215  	return returnObject, nil
   216  }
   217  
   218  // Delete deletes existing BGP Neighbor
   219  func (bgpNeighbor *EdgeBgpNeighbor) Delete() error {
   220  	client := bgpNeighbor.client
   221  	endpoint := types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointEdgeBgpNeighbor
   222  	apiVersion, err := client.getOpenApiHighestElevatedVersion(endpoint)
   223  	if err != nil {
   224  		return err
   225  	}
   226  
   227  	// Insert Edge Gateway ID into endpoint path
   228  	urlRef, err := client.OpenApiBuildEndpoint(fmt.Sprintf(endpoint, bgpNeighbor.edgeGatewayId), bgpNeighbor.EdgeBgpNeighbor.ID)
   229  	if err != nil {
   230  		return err
   231  	}
   232  
   233  	err = client.OpenApiDeleteItem(apiVersion, urlRef, nil, nil)
   234  	if err != nil {
   235  		return fmt.Errorf("error deleting NSX-T Edge Gateway BGP Neighbor: %s", err)
   236  	}
   237  
   238  	return nil
   239  }