Skip to content
This repository has been archived by the owner on Jan 17, 2025. It is now read-only.

Commit

Permalink
Merge branch 'mcr'
Browse files Browse the repository at this point in the history
  • Loading branch information
alkar committed Feb 12, 2020
2 parents 02cb47b + 0d99f0f commit 3cf1704
Show file tree
Hide file tree
Showing 15 changed files with 706 additions and 31 deletions.
12 changes: 12 additions & 0 deletions examples/megaport_mcr_basic/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
data "megaport_location" "foo" {
name_regex = "{{ .location }}"
mcr_available = {{ .mcr_version }}
}

resource "megaport_mcr" "foo" {
mcr_version = {{ .mcr_version }}
name = "terraform_acctest_{{ .uid }}"
location_id = data.megaport_location.foo.id
rate_limit = {{ .rate_limit }}
}

19 changes: 19 additions & 0 deletions examples/megaport_mcr_full/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
data "megaport_location" "foo" {
name_regex = "{{ .location }}"
mcr_available = {{ .mcr_version }}
}

resource "megaport_mcr" "foo" {
mcr_version = {{ .mcr_version }}
name = "terraform_acctest_{{ .uid }}"
location_id = data.megaport_location.foo.id
rate_limit = {{ .rate_limit }}
invoice_reference = "{{ .uid }}"
{{- if .term }}
term = {{ .term }}
{{- end }}
{{- if .asn }}
asn = {{ .asn }}
{{- end }}
}

10 changes: 5 additions & 5 deletions megaport/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (c *Client) GetMegaportPrice(locationId, speed, term uint64, productUid str
return c.getMegaportCharges("megaport", v)
}

func (c *Client) GetMCR1Price(locationId, speed uint64, productUid string) (*MegaportCharges, error) {
func (c *Client) GetMcr1Price(locationId, speed uint64, productUid string) (*MegaportCharges, error) {
v := url.Values{}
v.Set("locationId", strconv.FormatUint(locationId, 10))
v.Set("speed", strconv.FormatUint(speed, 10))
Expand All @@ -151,7 +151,7 @@ func (c *Client) GetMCR1Price(locationId, speed uint64, productUid string) (*Meg
return c.getMegaportCharges("mcr", v)
}

func (c *Client) GetMCR2Price(locationId, speed uint64, productUid string) (*MegaportCharges, error) {
func (c *Client) GetMcr2Price(locationId, speed uint64, productUid string) (*MegaportCharges, error) {
v := url.Values{}
v.Set("locationId", strconv.FormatUint(locationId, 10))
v.Set("speed", strconv.FormatUint(speed, 10))
Expand Down Expand Up @@ -203,16 +203,16 @@ func (c *Client) do(req *http.Request, data interface{}) error {
if resp.StatusCode == http.StatusNotFound {
return ErrNotFound
}
if resp.StatusCode != http.StatusOK {
if resp.StatusCode < 200 || resp.StatusCode > 299 {
r := megaportResponse{}
if err := parseResponseBody(resp, &r); err != nil {
return err
}
err := responseDataToError(r.Data)
if err != nil {
return fmt.Errorf("megaport-api: %s: %w", r.Message, err)
return fmt.Errorf("megaport-api (%d): %s: %w", resp.StatusCode, r.Message, err)
} else {
return fmt.Errorf("megaport-api: %s", r.Message)
return fmt.Errorf("megaport-api (%d): %s", resp.StatusCode, r.Message)
}
}
return parseResponseBody(resp, &megaportResponse{Data: data})
Expand Down
12 changes: 6 additions & 6 deletions megaport/api/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,27 +90,27 @@ func TestClient_responseDataToError(t *testing.T) {
}{
{
p: `{"message":"foo"}`,
e: `megaport-api: foo`,
e: `megaport-api (500): foo`,
},
{
p: `{"message":"foo","data":"bar"}`,
e: `megaport-api: foo: bar`,
e: `megaport-api (500): foo: bar`,
},
{
p: `{"message":"foo","data":["bar","baz"]}`,
e: `megaport-api: foo: 2 errors: ['bar', 'baz']`,
e: `megaport-api (500): foo: 2 errors: ['bar', 'baz']`,
},
{
p: `{"message":"foo","data":{"a":"b"}}`,
e: `megaport-api: foo: a="b"`,
e: `megaport-api (500): foo: a="b"`,
},
{
p: `{"message":"foo","data":{"c":5}}`,
e: `megaport-api: foo: c=5`,
e: `megaport-api (500): foo: c=5`,
},
{
p: `{"message":"foo","data":true}`,
e: `megaport-api: foo: cannot process error data of type bool: true`,
e: `megaport-api (500): foo: cannot process error data of type bool: true`,
},
}
c, s := testClientServer(func(w http.ResponseWriter, r *http.Request) {
Expand Down
163 changes: 163 additions & 0 deletions megaport/api/mcr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package api

import (
"encoding/json"
"fmt"
"net/http"
)

type McrCreateInput interface {
networkDesignInput
mcrVersion() uint64
}

type Mcr1CreateInput struct {
Asn *uint64
InvoiceReference *string
LocationId *uint64
Name *string
RateLimit *uint64
Term *uint64
}

func (v *Mcr1CreateInput) mcrVersion() uint64 {
return 1
}

func (v *Mcr1CreateInput) productType() string {
return ProductTypeMcr1
}

func (v *Mcr1CreateInput) toPayload() ([]byte, error) {
payload := []*portCreatePayload{{
LocationId: v.LocationId,
Config: &portCreatePayloadPortConfig{},
CostCentre: v.InvoiceReference,
PortSpeed: v.RateLimit,
ProductName: v.Name,
ProductType: String(ProductTypeMcr1),
Term: v.Term,
Virtual: Bool(true),
}}
if v.Asn != nil && *v.Asn > 0 {
payload[0].Config.McrAsn = v.Asn
}
return json.Marshal(payload)
}

type Mcr2CreateInput struct {
Asn *uint64
InvoiceReference *string
LocationId *uint64
Name *string
RateLimit *uint64
}

func (v *Mcr2CreateInput) mcrVersion() uint64 {
return 2
}

func (v *Mcr2CreateInput) productType() string {
return ProductTypeMcr2
}

func (v *Mcr2CreateInput) toPayload() ([]byte, error) {
payload := []*portCreatePayload{{
LocationId: v.LocationId,
Config: &portCreatePayloadPortConfig{},
CostCentre: v.InvoiceReference,
PortSpeed: v.RateLimit,
ProductName: v.Name,
ProductType: String(ProductTypeMcr2),
}}
if v.Asn != nil && *v.Asn > 0 {
payload[0].Config.McrAsn = v.Asn
}
return json.Marshal(payload)
}

type McrUpdateInput interface {
networkDesignInput
productUid() string
}

type Mcr1UpdateInput struct {
InvoiceReference *string
Name *string
ProductUid *string
}

func (v *Mcr1UpdateInput) productUid() string {
return *v.ProductUid
}

func (v *Mcr1UpdateInput) productType() string {
return ProductTypeMcr1
}

func (v *Mcr1UpdateInput) toPayload() ([]byte, error) {
payload := &portUpdatePayload{
Name: v.Name,
CostCentre: v.InvoiceReference,
}
return json.Marshal(payload)
}

type Mcr2UpdateInput struct {
InvoiceReference *string
Name *string
ProductUid *string
}

func (v *Mcr2UpdateInput) productUid() string {
return *v.ProductUid
}

func (v *Mcr2UpdateInput) productType() string {
return ProductTypeMcr2
}

func (v *Mcr2UpdateInput) toPayload() ([]byte, error) {
payload := &portUpdatePayload{
Name: v.Name,
CostCentre: v.InvoiceReference,
}
return json.Marshal(payload)
}

func (c *Client) CreateMcr(v McrCreateInput) (*string, error) {
d, err := c.create(v)
if err != nil {
return nil, err
}
uid := d[0]["technicalServiceUid"].(string)
return &uid, nil
}

func (c *Client) GetMcr(uid string) (*Product, error) {
d := &Product{}
if err := c.get(uid, d); err != nil {
return nil, err
}
return d, nil
}

func (c *Client) UpdateMcr(v McrUpdateInput) error {
return c.update(v.productUid(), v)
}

func (c *Client) DeleteMcr(uid string) error {
return c.delete(uid)
}

func (c *Client) ListMcrs() ([]*Product, error) {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v2/products", c.BaseURL), nil)
if err != nil {
return nil, err
}
data := []*Product{}
if err := c.do(req, &data); err != nil {
return nil, err
}
return data, nil
}
35 changes: 20 additions & 15 deletions megaport/api/port.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
)

const (
ProductTypePort = "MEGAPORT"
ProductTypeMCR1 = "MEGAPORT"
ProductTypeMCR2 = "MCR2"
ProductTypePort = "MEGAPORT" // Virtual = false, ProductType = MEGAPORT
ProductTypeMcr1 = "MEGAPORT" // Virtual = true, ProductType = MEGAPORT
ProductTypeMcr2 = "MCR2" // Virtual = false, ProductType = MCR2
ProductTypeVxc = "VXC"
)

Expand All @@ -20,18 +20,23 @@ const (
// mcr2: virtual = false, type = MCR2

type portCreatePayload struct {
CreateDate *uint64 `json:"createDate,omitempty"` // TODO: need to fill in? :o
CostCentre *string `json:"costCentre"`
LagPortCount *uint64 `json:"lagPortCount,omitempty"` // TODO: Required: the number of ports in this LAG order (https://dev.megaport.com/#standard-api-orders-validate-lag-order)
LocationId *uint64 `json:"locationId"`
LocationUid *string `json:"locationUid,omitempty"` // TODO: null in example, is it a string? https://dev.megaport.com/#standard-api-orders-validate-port-order
Market *string `json:"market,omitempty"` // TODO: what is this ???
PortSpeed *uint64 `json:"portSpeed"` // TODO: validate 1000, 10000, 100000
ProductName *string `json:"productName"`
ProductType *string `json:"productType"` // TODO: "MEGAPORT"?
Term *uint64 `json:"term"`
Virtual *bool `json:"virtual"` // TODO: False for port, true for MCR1.0 (https://dev.megaport.com/#standard-api-orders-validate-port-order)
MarketplaceVisibility *bool `json:"marketplaceVisibility,omitempty"`
CreateDate *uint64 `json:"createDate,omitempty"` // TODO: need to fill in? :o
Config *portCreatePayloadPortConfig `json:"config,omitempty"`
CostCentre *string `json:"costCentre"`
LagPortCount *uint64 `json:"lagPortCount,omitempty"` // TODO: Required: the number of ports in this LAG order (https://dev.megaport.com/#standard-api-orders-validate-lag-order)
LocationId *uint64 `json:"locationId"`
LocationUid *string `json:"locationUid,omitempty"` // TODO: null in example, is it a string? https://dev.megaport.com/#standard-api-orders-validate-port-order
Market *string `json:"market,omitempty"` // TODO: what is this ???
PortSpeed *uint64 `json:"portSpeed"` // TODO: validate 1000, 10000, 100000
ProductName *string `json:"productName"`
ProductType *string `json:"productType"` // TODO: "MEGAPORT"?
Term *uint64 `json:"term"`
Virtual *bool `json:"virtual"` // TODO: False for port, true for MCR1.0 (https://dev.megaport.com/#standard-api-orders-validate-port-order)
MarketplaceVisibility *bool `json:"marketplaceVisibility,omitempty"`
}

type portCreatePayloadPortConfig struct {
McrAsn *uint64 `json:"mcrAsn,omitempty"`
}

type portUpdatePayload struct {
Expand Down
20 changes: 16 additions & 4 deletions megaport/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ type LocationAddress struct {
}

type LocationProducts struct {
MCR bool
MCRVersion uint64
MCR1 []uint64
MCR2 []uint64
Mcr bool
McrVersion uint64
Mcr1 []uint64
Mcr2 []uint64
Megaport []uint64
}

Expand Down Expand Up @@ -152,6 +152,18 @@ type Product struct {
VxcAutoApproval bool
}

func (p *Product) McrVersion() int {
switch p.ProductType {
case "MCR2":
return 2
case "MEGAPORT":
if p.Virtual {
return 1
}
}
return -1
}

type ProductResources struct { // TODO: verify these are the only valid fields
// CrossConnect ProductResourcesCrossConnect `json:"cross_connect"` // TODO: only referenced in https://dev.megaport.com/#general-get-product-list
Interface ProductResourcesInterface
Expand Down
8 changes: 8 additions & 0 deletions megaport/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ func testAccCheckResourceDestroy(s *terraform.State) error {
if v != nil && !isResourceDeleted(v.ProvisioningStatus) {
return fmt.Errorf("testAccCheckResourceDestroy: %q (%s) has not been destroyed", n, rs.Primary.ID)
}
case "megaport_mcr":
v, err := cfg.Client.GetMcr(rs.Primary.ID)
if err != nil {
return err
}
if v != nil && !isResourceDeleted(v.ProvisioningStatus) {
return fmt.Errorf("testAccCheckResourceDestroy: %q (%s) has not been destroyed", n, rs.Primary.ID)
}
case "megaport_aws_vxc":
fallthrough
case "megaport_gcp_vxc":
Expand Down
6 changes: 5 additions & 1 deletion megaport/data_source_megaport_partner_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@ func dataSourceMegaportPartnerPortRead(d *schema.ResourceData, m interface{}) er
if err != nil {
return err
}
if err := d.Set("bandwidths", bandwidths); err != nil { // apparently it's fine to use []uint64 here
bw := make([]int, len(bandwidths))
for i, v := range bandwidths {
bw[i] = int(v)
}
if err := d.Set("bandwidths", bw); err != nil {
return err
}
d.SetId(p.ProductUid)
Expand Down
1 change: 1 addition & 0 deletions megaport/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func Provider() terraform.ResourceProvider {

ResourcesMap: map[string]*schema.Resource{
"megaport_port": resourceMegaportPort(),
"megaport_mcr": resourceMegaportMcr(),
"megaport_aws_vxc": resourceMegaportAwsVxc(),
"megaport_gcp_vxc": resourceMegaportGcpVxc(),
"megaport_private_vxc": resourceMegaportPrivateVxc(),
Expand Down
Loading

0 comments on commit 3cf1704

Please sign in to comment.