From 382784607229bc959e70f4c68ed30710511c667e Mon Sep 17 00:00:00 2001 From: Dimitrios Karagiannis Date: Wed, 16 Oct 2019 08:45:47 +0100 Subject: [PATCH] Refactor VxcService Most of the different products on Megaport are VXCs. Their lifecycle is controlled through the same endpoints on the Megaport API and the process is more or less uniform, apart from the different payloads for each type of VXC as presented on the web ui (eg.: private, partner, cloud). Therefore, we can reuse the underlying CRUD methods in the package and export methods specific to each type of VXC. Signed-off-by: Dimitrios Karagiannis --- megaport/api/vxc.go | 173 ++++++++++++---------- megaport/resource_megaport_private_vxc.go | 10 +- 2 files changed, 100 insertions(+), 83 deletions(-) diff --git a/megaport/api/vxc.go b/megaport/api/vxc.go index b43fb11..554a8c3 100644 --- a/megaport/api/vxc.go +++ b/megaport/api/vxc.go @@ -16,81 +16,11 @@ func NewVxcService(c *Client) *VxcService { return &VxcService{c} } -type VxcCreateInput struct { - InvoiceReference string - Name string - ProductUidA string - ProductUidB string - RateLimit uint64 - VlanA uint64 - VlanB uint64 -} - -func (v *VxcCreateInput) toPayload() ([]byte, error) { - payload := []*vxcCreatePayload{{ - ProductUid: v.ProductUidA, - AssociatedVxcs: []vxcCreatePayloadAssociatedVxc{{ - ProductName: v.Name, - RateLimit: v.RateLimit, - CostCentre: v.InvoiceReference, - AEnd: &vxcCreatePayloadAssociatedVxcEnd{Vlan: v.VlanA}, - BEnd: &vxcCreatePayloadAssociatedVxcEnd{ProductUid: v.ProductUidB, Vlan: v.VlanB}, - }}, - }} - return json.Marshal(payload) -} - -type VxcCreateOutput struct { - ProductUid string -} - -type vxcCreatePayload struct { - ProductUid string `json:"productUid"` - AssociatedVxcs []vxcCreatePayloadAssociatedVxc `json:"associatedVxcs"` -} - -type vxcCreatePayloadAssociatedVxc struct { - ProductName string `json:"productName"` - RateLimit uint64 `json:"rateLimit"` - CostCentre string `json:"costCentre"` - AEnd *vxcCreatePayloadAssociatedVxcEnd `json:"aEnd"` - BEnd *vxcCreatePayloadAssociatedVxcEnd `json:"bEnd"` -} - -type vxcCreatePayloadAssociatedVxcEnd struct { - ProductUid string `json:"productUid,omitempty"` - Vlan uint64 `json:"vlan"` +type networkDesignInput interface { + toPayload() ([]byte, error) } -type VxcUpdateInput struct { - InvoiceReference string - Name string - ProductUid string - RateLimit uint64 - VlanA uint64 - VlanB uint64 -} - -func (v *VxcUpdateInput) toPayload() ([]byte, error) { - payload := &vxcUpdatePayload{ - AEndVlan: v.VlanA, - BEndVlan: v.VlanB, - CostCentre: v.InvoiceReference, - Name: v.Name, - RateLimit: v.RateLimit, - } - return json.Marshal(payload) -} - -type vxcUpdatePayload struct { - AEndVlan uint64 `json:"aEndVlan"` - BEndVlan uint64 `json:"bEndVlan,omitempty"` - CostCentre string `json:"costCentre"` - Name string `json:"name"` - RateLimit uint64 `json:"rateLimit"` -} - -func (p *VxcService) Create(v *VxcCreateInput) (*VxcCreateOutput, error) { +func (p *VxcService) create(v networkDesignInput) (*string, error) { payload, err := v.toPayload() if err != nil { return nil, err @@ -112,10 +42,11 @@ func (p *VxcService) Create(v *VxcCreateInput) (*VxcCreateOutput, error) { if err := p.c.do(req, &d); err != nil { return nil, err } - return &VxcCreateOutput{ProductUid: d[0]["vxcJTechnicalServiceUid"].(string)}, nil + uid := d[0]["vxcJTechnicalServiceUid"].(string) + return &uid, nil } -func (p *VxcService) Get(uid string) (*ProductAssociatedVxc, error) { +func (p *VxcService) get(uid string) (*ProductAssociatedVxc, error) { // TODO: change name req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/product/%s", p.c.BaseURL, uid), nil) if err != nil { return nil, err @@ -127,13 +58,13 @@ func (p *VxcService) Get(uid string) (*ProductAssociatedVxc, error) { return data, nil } -func (p *VxcService) Update(v *VxcUpdateInput) error { +func (p *VxcService) update(uid string, v networkDesignInput) error { payload, err := v.toPayload() if err != nil { return err } b := bytes.NewReader(payload) - req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%s/v2/product/vxc/%s", p.c.BaseURL, v.ProductUid), b) + req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%s/v2/product/vxc/%s", p.c.BaseURL, uid), b) if err != nil { return err } @@ -143,7 +74,7 @@ func (p *VxcService) Update(v *VxcUpdateInput) error { return nil } -func (p *VxcService) Delete(uid string) error { +func (p *VxcService) delete(uid string) error { req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/v2/product/%s/action/CANCEL_NOW", p.c.BaseURL, uid), nil) if err != nil { return err @@ -153,3 +84,89 @@ func (p *VxcService) Delete(uid string) error { } return nil } + +type vxcCreatePayload struct { + ProductUid string `json:"productUid"` + AssociatedVxcs []*vxcCreatePayloadAssociatedVxc `json:"associatedVxcs"` +} + +type vxcCreatePayloadAssociatedVxc struct { + ProductName string `json:"productName"` + RateLimit uint64 `json:"rateLimit"` + CostCentre string `json:"costCentre"` + AEnd *vxcCreatePayloadAssociatedVxcEnd `json:"aEnd"` + BEnd *vxcCreatePayloadAssociatedVxcEnd `json:"bEnd"` +} + +type vxcCreatePayloadAssociatedVxcEnd struct { + ProductUid string `json:"productUid,omitempty"` // XXX extra + Vlan uint64 `json:"vlan"` +} + +type PrivateVxcCreateInput struct { + InvoiceReference string + Name string + ProductUidA string + ProductUidB string + RateLimit uint64 + VlanA uint64 + VlanB uint64 +} + +func (v *PrivateVxcCreateInput) toPayload() ([]byte, error) { + payload := []*vxcCreatePayload{{ + ProductUid: v.ProductUidA, + AssociatedVxcs: []*vxcCreatePayloadAssociatedVxc{{ + ProductName: v.Name, + RateLimit: v.RateLimit, + CostCentre: v.InvoiceReference, + AEnd: &vxcCreatePayloadAssociatedVxcEnd{Vlan: v.VlanA}, + BEnd: &vxcCreatePayloadAssociatedVxcEnd{ProductUid: v.ProductUidB, Vlan: v.VlanB}, + }}, + }} + return json.Marshal(payload) +} + +type PrivateVxcUpdateInput struct { + InvoiceReference string + Name string + ProductUid string + RateLimit uint64 + VlanA uint64 + VlanB uint64 +} + +func (v *PrivateVxcUpdateInput) toPayload() ([]byte, error) { + payload := &vxcUpdatePayload{ + AEndVlan: v.VlanA, + BEndVlan: v.VlanB, + CostCentre: v.InvoiceReference, + Name: v.Name, + RateLimit: v.RateLimit, + } + return json.Marshal(payload) +} + +type vxcUpdatePayload struct { + AEndVlan uint64 `json:"aEndVlan"` + BEndVlan uint64 `json:"bEndVlan,omitempty"` + CostCentre string `json:"costCentre"` + Name string `json:"name"` + RateLimit uint64 `json:"rateLimit"` +} + +func (p *VxcService) CreatePrivateVxc(v *PrivateVxcCreateInput) (*string, error) { + return p.create(v) +} + +func (p *VxcService) GetPrivateVxc(uid string) (*ProductAssociatedVxc, error) { + return p.get(uid) +} + +func (p *VxcService) UpdatePrivateVxc(v *PrivateVxcUpdateInput) error { + return p.update(v.ProductUid, v) +} + +func (p *VxcService) DeletePrivateVxc(uid string) error { + return p.delete(uid) +} diff --git a/megaport/resource_megaport_private_vxc.go b/megaport/resource_megaport_private_vxc.go index 0cac2d2..987c4f9 100644 --- a/megaport/resource_megaport_private_vxc.go +++ b/megaport/resource_megaport_private_vxc.go @@ -49,7 +49,7 @@ func resourceMegaportPrivateVxc() *schema.Resource { func resourceMegaportPrivateVxcRead(d *schema.ResourceData, m interface{}) error { cfg := m.(*Config) - p, err := cfg.Client.Vxc.Get(d.Id()) + p, err := cfg.Client.Vxc.GetPrivateVxc(d.Id()) if err != nil { log.Printf("resourceMegaportPrivateVxcRead: %v", err) d.SetId("") @@ -71,7 +71,7 @@ func resourceMegaportPrivateVxcCreate(d *schema.ResourceData, m interface{}) err cfg := m.(*Config) a := d.Get("a_end").([]interface{})[0].(map[string]interface{}) b := d.Get("b_end").([]interface{})[0].(map[string]interface{}) - o, err := cfg.Client.Vxc.Create(&api.VxcCreateInput{ + uid, err := cfg.Client.Vxc.CreatePrivateVxc(&api.PrivateVxcCreateInput{ ProductUidA: a["product_uid"].(string), ProductUidB: b["product_uid"].(string), Name: d.Get("name").(string), @@ -83,7 +83,7 @@ func resourceMegaportPrivateVxcCreate(d *schema.ResourceData, m interface{}) err if err != nil { return err } - d.SetId(o.ProductUid) + d.SetId(*uid) return resourceMegaportPrivateVxcRead(d, m) } @@ -98,7 +98,7 @@ func resourceMegaportPrivateVxcUpdate(d *schema.ResourceData, m interface{}) err //if log.Printf(">>1 %#v", a) log.Printf(">>2 %#v", a["vlan"]) - if err := cfg.Client.Vxc.Update(&api.VxcUpdateInput{ + if err := cfg.Client.Vxc.UpdatePrivateVxc(&api.PrivateVxcUpdateInput{ InvoiceReference: d.Get("invoice_reference").(string), Name: d.Get("name").(string), ProductUid: d.Id(), @@ -113,7 +113,7 @@ func resourceMegaportPrivateVxcUpdate(d *schema.ResourceData, m interface{}) err func resourceMegaportPrivateVxcDelete(d *schema.ResourceData, m interface{}) error { cfg := m.(*Config) - err := cfg.Client.Vxc.Delete(d.Id()) + err := cfg.Client.Vxc.DeletePrivateVxc(d.Id()) if err != nil && err != api.ErrNotFound { return err }