Skip to content

Commit

Permalink
Merge pull request #78 from megaport/feat/resourceTags
Browse files Browse the repository at this point in the history
feat: support resource tags for megaport services
  • Loading branch information
MegaportPhilipBrowne authored Oct 16, 2024
2 parents 2ab9458 + 5ce7283 commit 3fcdb48
Show file tree
Hide file tree
Showing 15 changed files with 424 additions and 22 deletions.
36 changes: 29 additions & 7 deletions mcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ type MCRService interface {
DeleteMCR(ctx context.Context, req *DeleteMCRRequest) (*DeleteMCRResponse, error)
// RestoreMCR restores a deleted MCR in the Megaport MCR API.
RestoreMCR(ctx context.Context, mcrId string) (*RestoreMCRResponse, error)
// ListMCRResourceTags returns the resource tags for an MCR in the Megaport MCR API.
ListMCRResourceTags(ctx context.Context, mcrID string) (map[string]string, error)
// UpdateMCRResourceTags updates the resource tags for an MCR in the Megaport MCR API.
UpdateMCRResourceTags(ctx context.Context, mcrID string, tags map[string]string) error

// DEPRECATED - Use ListMCRPrefixFilterLists instead
GetMCRPrefixFilterLists(ctx context.Context, mcrId string) ([]*PrefixFilterList, error)
Expand Down Expand Up @@ -62,6 +66,7 @@ type BuyMCRRequest struct {
MCRAsn int
CostCentre string
PromoCode string
ResourceTags map[string]string `json:"resourceTags,omitempty"`

WaitForProvision bool // Wait until the MCR provisions before returning
WaitForTime time.Duration // How long to wait for the MCR to provision if WaitForProvision is true (default is 5 minutes)
Expand Down Expand Up @@ -202,13 +207,14 @@ func validateBuyMCRRequest(order *BuyMCRRequest) error {

func createMCROrder(req *BuyMCRRequest) []MCROrder {
order := MCROrder{
LocationID: req.LocationID,
Name: req.Name,
Term: req.Term,
Type: "MCR2",
PortSpeed: req.PortSpeed,
PromoCode: req.PromoCode,
Config: MCROrderConfig{},
LocationID: req.LocationID,
Name: req.Name,
Term: req.Term,
Type: "MCR2",
PortSpeed: req.PortSpeed,
PromoCode: req.PromoCode,
ResourceTags: toProductResourceTags(req.ResourceTags),
Config: MCROrderConfig{},
}

if req.CostCentre != "" {
Expand Down Expand Up @@ -482,3 +488,19 @@ func (svc *MCRServiceOp) RestoreMCR(ctx context.Context, mcrId string) (*Restore
IsRestored: true,
}, nil
}

// ListMCRResourceTags returns the resource tags for an MCR in the Megaport MCR API.
func (svc *MCRServiceOp) ListMCRResourceTags(ctx context.Context, mcrID string) (map[string]string, error) {
tags, err := svc.Client.ProductService.ListProductResourceTags(ctx, mcrID)
if err != nil {
return nil, err
}
return fromProductResourceTags(tags), nil
}

// UpdateMCRResourceTags updates the resource tags for an MCR in the Megaport MCR API.
func (svc *MCRServiceOp) UpdateMCRResourceTags(ctx context.Context, mcrID string, tags map[string]string) error {
return svc.Client.ProductService.UpdateProductResourceTags(ctx, mcrID, &UpdateProductResourceTagsRequest{
ResourceTags: toProductResourceTags(tags),
})
}
16 changes: 16 additions & 0 deletions mcr_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ func (suite *MCRIntegrationTestSuite) TestCreatePrefixFilterList() {
PortSpeed: 1000,
MCRAsn: 0,
WaitForProvision: true,
ResourceTags: testResourceTags,
WaitForTime: 5 * time.Minute,
})
if portErr != nil {
Expand Down Expand Up @@ -242,6 +243,21 @@ func (suite *MCRIntegrationTestSuite) TestCreatePrefixFilterList() {
suite.FailNowf("could not create prefix filter list", "could not create prefix filter list %v", prefixErr)
}

tags, err := mcrSvc.ListMCRResourceTags(ctx, mcrId)
if err != nil {
suite.FailNowf("could not list mcr resource tags", "could not list mcr resource tags %v", err)
}
suite.EqualValues(testResourceTags, tags)
err = mcrSvc.UpdateMCRResourceTags(ctx, mcrId, testUpdatedResourceTags)
if err != nil {
suite.FailNowf("could not update mcr resource tags", "could not update mcr resource tags %v", err)
}
tags, err = mcrSvc.ListMCRResourceTags(ctx, mcrId)
if err != nil {
suite.FailNowf("could not list mcr resource tags", "could not list mcr resource tags %v", err)
}
suite.EqualValues(testUpdatedResourceTags, tags)

logger.InfoContext(ctx, "Deleting MCR now.", slog.String("mcr_id", mcrId))
hardDeleteRes, deleteErr := mcrSvc.DeleteMCR(ctx, &DeleteMCRRequest{
MCRID: mcrId,
Expand Down
2 changes: 2 additions & 0 deletions mcr_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type MCROrder struct {
CostCentre string `json:"costCentre"`
PromoCode string `json:"promoCode,omitempty"`
Config MCROrderConfig `json:"config"`

ResourceTags []ResourceTag `json:"resourceTags,omitempty"`
}

// MCROrderConfig represents the configuration for an MCR order.
Expand Down
27 changes: 27 additions & 0 deletions megaport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,33 @@ var runIntegrationTests = flag.Bool("integration", false, "perform integration t
// programLevel is the log level for the test suite
var programLevel = new(slog.LevelVar)

// testResourceTags is a list of resource tags for integration tests
var testResourceTags = map[string]string{
"key1": "value1", "key2": "value2", "key3": "value3",
}

var testProductResourceTags = []ResourceTag{
{Key: "key1", Value: "value1"},
{Key: "key2", Value: "value2"},
{Key: "key3", Value: "value3"},
}

var testUpdatedResourceTags = map[string]string{
"key1updated": "value1updated", "key2updated": "value2updated", "key3updated": "value3updated", "key4updated": "value4updated",
}

var resourceTagJSONBlob = `{
"message": "test-message",
"terms": "test-terms",
"data": {
"resourceTags": [
{"key": "key1", "value": "value1"},
{"key": "key2", "value": "value2"},
{"key": "key3", "value": "value3"}
]
}
}`

// Default Base URL for Integration Tests
const (
MEGAPORTURL = "https://api-staging.megaport.com/"
Expand Down
22 changes: 22 additions & 0 deletions mve.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ type MVEService interface {
ListMVEImages(ctx context.Context) ([]*MVEImage, error)
// ListAvailableMVESizes returns a list of currently available MVE sizes and details for each size. The instance size determines the MVE capabilities, such as how many concurrent connections it can support. The compute sizes are 2/8, 4/16, 8/32, and 12/48, where the first number is the CPU and the second number is the GB of available RAM. Each size has 4 GB of RAM for every vCPU allocated.
ListAvailableMVESizes(ctx context.Context) ([]*MVESize, error)
// ListMVEResourceTags returns a list of resource tags for an MVE in the Megaport MVE API.
ListMVEResourceTags(ctx context.Context, mveID string) (map[string]string, error)
// UpdateMVEResourceTags updates the resource tags for an MVE in the Megaport MVE API.
UpdateMVEResourceTags(ctx context.Context, mveID string, tags map[string]string) error
}

// NewMVEService creates a new instance of the MVE Service.
Expand All @@ -52,6 +56,8 @@ type BuyMVERequest struct {
PromoCode string
CostCentre string

ResourceTags map[string]string `json:"resourceTags,omitempty"`

WaitForProvision bool // Wait until the MVE provisions before returning
WaitForTime time.Duration // How long to wait for the MVE to provision if WaitForProvision is true (default is 5 minutes)
}
Expand Down Expand Up @@ -165,6 +171,7 @@ func createMVEOrder(req *BuyMVERequest) []*MVEOrderConfig {
PromoCode: req.PromoCode,
CostCentre: req.CostCentre,
VendorConfig: req.VendorConfig,
ResourceTags: toProductResourceTags(req.ResourceTags),
ProductType: strings.ToUpper(PRODUCT_MVE),
Config: MVEConfig{
DiversityZone: req.DiversityZone,
Expand Down Expand Up @@ -329,3 +336,18 @@ func validateBuyMVERequest(req *BuyMVERequest) error {
}
return nil
}

func (svc *MVEServiceOp) ListMVEResourceTags(ctx context.Context, mveID string) (map[string]string, error) {
tags, err := svc.Client.ProductService.ListProductResourceTags(ctx, mveID)
if err != nil {
return nil, err
}
return fromProductResourceTags(tags), nil
}

// UpdateMVEResourceTags updates the resource tags for an MVE in the Megaport MVE API.
func (svc *MVEServiceOp) UpdateMVEResourceTags(ctx context.Context, mveID string, tags map[string]string) error {
return svc.Client.ProductService.UpdateProductResourceTags(ctx, mveID, &UpdateProductResourceTagsRequest{
ResourceTags: toProductResourceTags(tags),
})
}
24 changes: 23 additions & 1 deletion mve_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func (suite *MVEIntegrationTestSuite) TestArubaMVE() {
WaitForProvision: true,
WaitForTime: 5 * time.Minute,
DiversityZone: "red",
ResourceTags: testResourceTags,
})
if err != nil {
suite.FailNowf("error buying mve", "error buying mve %v", err)
Expand All @@ -86,6 +87,27 @@ func (suite *MVEIntegrationTestSuite) TestArubaMVE() {

logger.DebugContext(ctx, "MVE Purchased", slog.String("mve_id", mveUid))

tags, err := mveSvc.ListMVEResourceTags(ctx, mveUid)
if err != nil {
suite.FailNowf("could not list mve resource tags", "could not list mve resource tags %v", err)
}
suite.EqualValues(testResourceTags, tags)

err = mveSvc.UpdateMVEResourceTags(ctx, mveUid, testUpdatedResourceTags)
if err != nil {
suite.FailNowf("could not update mve resource tags", "could not update mve resource tags %v", err)
}
tags, err = mveSvc.ListMVEResourceTags(ctx, mveUid)
if err != nil {
suite.FailNowf("could not list mve resource tags", "could not list mve resource tags %v", err)
}
suite.EqualValues(testUpdatedResourceTags, tags)
mveDetails, err := mveSvc.GetMVE(ctx, mveUid)
if err != nil {
suite.FailNowf("could not get mve", "could not get mve %v", err)
}
suite.Equal(mveDetails.ResourceTags, testResourceTags)

logger.InfoContext(ctx, "Deleting MVE now", slog.String("mve_id", mveUid))

deleteRes, err := mveSvc.DeleteMVE(ctx, &DeleteMVERequest{
Expand All @@ -96,7 +118,7 @@ func (suite *MVEIntegrationTestSuite) TestArubaMVE() {
}
suite.True(deleteRes.IsDeleted)

mveDetails, err := mveSvc.GetMVE(ctx, mveUid)
mveDetails, err = mveSvc.GetMVE(ctx, mveUid)
if err != nil {
suite.FailNowf("could not get mve", "could not get mve %v", err)
}
Expand Down
4 changes: 4 additions & 0 deletions mve_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type MVEOrderConfig struct {
NetworkInterfaces []MVENetworkInterface `json:"vnics"`
VendorConfig VendorConfig `json:"vendorConfig"`
Config MVEConfig `json:"config"`

ResourceTags []ResourceTag `json:"resourceTags,omitempty"`
}

// Nested configuration Fields for the MVE Order
Expand Down Expand Up @@ -202,6 +204,8 @@ type MVE struct {
DiversityZone string `json:"diversityZone"`
NetworkInterfaces []*MVENetworkInterface `json:"vnics"`
LocationDetails *ProductLocationDetails `json:"locationDetail"`

ResourceTags []map[string]string `json:"resourceTags,omitempty"`
}

// MVEResources represents the resources associated with an MVE.
Expand Down
23 changes: 23 additions & 0 deletions port.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ type PortService interface {
UnlockPort(ctx context.Context, portId string) (*UnlockPortResponse, error)
// CheckPortVLANAvailability checks if a VLAN is available on a port in the Megaport Products API.
CheckPortVLANAvailability(ctx context.Context, portId string, vlan int) (bool, error)
// ListPortResourceTags lists the resource tags for a port in the Megaport Port API.
ListPortResourceTags(ctx context.Context, portID string) (map[string]string, error)
// UpdatePortResourceTags updates the resource tags for a port in the Megaport Port API.
UpdatePortResourceTags(ctx context.Context, portID string, tags map[string]string) error
}

// NewPortService creates a new instance of the Port Service.
Expand Down Expand Up @@ -60,6 +64,8 @@ type BuyPortRequest struct {
CostCentre string `json:"costCentre"`
PromoCode string `json:"promoCode"`

ResourceTags map[string]string `json:"resourceTags"`

WaitForProvision bool // Wait until the VXC provisions before returning
WaitForTime time.Duration // How long to wait for the VXC to provision if WaitForProvision is true (default is 5 minutes)
}
Expand Down Expand Up @@ -220,6 +226,7 @@ func createPortOrder(req *BuyPortRequest) []PortOrder {
MarketplaceVisibility: req.MarketPlaceVisibility,
CostCentre: req.CostCentre,
PromoCode: req.PromoCode,
ResourceTags: toProductResourceTags(req.ResourceTags),
}}
}

Expand Down Expand Up @@ -486,3 +493,19 @@ func (svc *PortServiceOp) CheckPortVLANAvailability(ctx context.Context, portId
}
return false, nil
}

// ListPortResourceTags lists the resource tags for a port in the Megaport Port API.
func (svc *PortServiceOp) ListPortResourceTags(ctx context.Context, portID string) (map[string]string, error) {
tags, err := svc.Client.ProductService.ListProductResourceTags(ctx, portID)
if err != nil {
return nil, err
}
return fromProductResourceTags(tags), nil
}

func (svc *PortServiceOp) UpdatePortResourceTags(ctx context.Context, portID string, tags map[string]string) error {
productTags := toProductResourceTags(tags)
return svc.Client.ProductService.UpdateProductResourceTags(ctx, portID, &UpdateProductResourceTagsRequest{
ResourceTags: productTags,
})
}
15 changes: 15 additions & 0 deletions port_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ func (suite *PortIntegrationTestSuite) TestSinglePort() {
for _, p := range portsListPostCreate {
if p.UID == portID {
foundNewPort = true
tags, err := suite.client.PortService.ListPortResourceTags(ctx, p.UID)
if err != nil {
suite.FailNowf("could not list port resource tags", "could not list port resource tags %v", err)
}
suite.EqualValues(testResourceTags, tags)
err = suite.client.PortService.UpdatePortResourceTags(ctx, p.UID, testUpdatedResourceTags)
if err != nil {
suite.FailNowf("could not update port resource tags", "could not update port resource tags %v", err)
}
tags, err = suite.client.PortService.ListPortResourceTags(ctx, p.UID)
if err != nil {
suite.FailNowf("could not list port resource tags", "could not list port resource tags %v", err)
}
suite.EqualValues(testUpdatedResourceTags, tags)
}
}

Expand Down Expand Up @@ -172,6 +186,7 @@ func (suite *PortIntegrationTestSuite) testCreatePort(c *Client, ctx context.Con
DiversityZone: "red",
WaitForProvision: true,
WaitForTime: 5 * time.Minute,
ResourceTags: testResourceTags,
})

if err != nil {
Expand Down
1 change: 1 addition & 0 deletions port_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type PortOrder struct {
MarketplaceVisibility bool `json:"marketplaceVisibility"`
Config PortOrderConfig `json:"config"`
PromoCode string `json:"promoCode,omitempty"`
ResourceTags []ResourceTag `json:"resourceTags,omitempty"`
}

type PortOrderConfig struct {
Expand Down
Loading

0 comments on commit 3fcdb48

Please sign in to comment.