Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: push connection speed validation down to the API #610

Merged
merged 5 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/data-sources/equinix_metal_connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ In addition to all arguments above, the following attributes are exported:
* `redundancy` - Connection redundancy, reduntant or primary.
* `type` - Connection type, dedicated or shared.
* `project_id` - ID of project to which the connection belongs.
* `speed` - Connection speed, one of 50Mbps, 200Mbps, 500Mbps, 1Gbps, 2Gbps, 5Gbps, 10Gbps.
* `speed` - Connection speed - Values will be in the format '<number>Mbps' or '<number>Gpbs', for example '100Mbps`, '50Gbps', etc.
* `description` - Description of the connection resource.
* `mode` - Mode for connections in IBX facilities with the dedicated type - standard or tunnel.
* `tags` - String list of tags.
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/equinix_metal_connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ The following arguments are supported:
* `type` - (Required) Connection type - dedicated or shared.
* `contact_email` - (Optional) The preferred email used for communication and notifications about the Equinix Fabric interconnection. Required when using a Project API key. Optional and defaults to the primary user email address when using a User API key.
* `project_id` - (Optional) ID of the project where the connection is scoped to, must be set for.
* `speed` - (Required) Connection speed - one of 50Mbps, 200Mbps, 500Mbps, 1Gbps, 2Gbps, 5Gbps, 10Gbps.
* `speed` - (Required) Connection speed - Values must be in the format '<number>Mbps' or '<number>Gpbs', for example '100Mbps' or '50Gbps'. Actual supported values will depend on the connection type and whether the connection uses VLANs or VRF.
* `description` - (Optional) Description for the connection resource.
* `mode` - (Optional) Mode for connections in IBX facilities with the dedicated type - standard or tunnel. Default is standard.
* `tags` - (Optional) String list of tags.
Expand Down
2 changes: 1 addition & 1 deletion internal/resources/metal/connection/datasource_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func dataSourceSchema(ctx context.Context) schema.Schema {
Computed: true,
},
"speed": schema.StringAttribute{
Description: fmt.Sprintf("Port speed. Possible values are %s", allowedSpeedsString()),
Description: "Connection speed - Values will be in the format '<number>Mbps' or '<number>Gpbs', for example '100Mbps`, '50Gbps', etc.",
Computed: true,
},
"description": schema.StringAttribute{
Expand Down
8 changes: 7 additions & 1 deletion internal/resources/metal/connection/datasource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,13 @@ func TestAccDataSourceMetalConnection_withVlans_upgradeFromVersion(t *testing.T)
"equinix_metal_connection.test", "vlans.#",
"data.equinix_metal_connection.test", "vlans.#"),
resource.TestCheckResourceAttr(
"data.equinix_metal_connection.test", "vlans.#", "0"),
"data.equinix_metal_connection.test", "vlans.#", "2"),
resource.TestCheckResourceAttrPair(
"equinix_metal_vlan.test1", "vxlan",
"data.equinix_metal_connection.test", "vlans.0"),
resource.TestCheckResourceAttrPair(
"equinix_metal_vlan.test2", "vxlan",
"data.equinix_metal_connection.test", "vlans.1"),
),
},
{
Expand Down
3 changes: 1 addition & 2 deletions internal/resources/metal/connection/resource_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package connection

import (
"context"
"fmt"

"github.com/equinix/terraform-provider-equinix/internal/framework"
fwtypes "github.com/equinix/terraform-provider-equinix/internal/framework/types"
Expand Down Expand Up @@ -95,7 +94,7 @@ func resourceSchema(ctx context.Context) schema.Schema {
},
},
"speed": schema.StringAttribute{
Description: fmt.Sprintf("Port speed. Required for a_side connections. Allowed values are %s", allowedSpeedsString()),
Description: "Connection speed - Values must be in the format '<number>Mbps' or '<number>Gpbs', for example '100Mbps' or '50Gbps'. Actual supported values will depend on the connection type and whether the connection uses VLANs or VRF.",
Optional: true,
Computed: true,
},
Expand Down
63 changes: 26 additions & 37 deletions internal/resources/metal/connection/speed.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,42 @@ package connection

import (
"fmt"
"strings"
"regexp"
"strconv"
)

var (
mega uint64 = 1000 * 1000
giga uint64 = 1000 * mega
allowedSpeeds = []struct {
Int uint64
Str string
}{
{50 * mega, "50Mbps"},
{200 * mega, "200Mbps"},
{500 * mega, "500Mbps"},
{1 * giga, "1Gbps"},
{2 * giga, "2Gbps"},
{5 * giga, "5Gbps"},
{10 * giga, "10Gbps"},
{100 * giga, "100Gbps"},
}
mega uint64 = 1000 * 1000
giga uint64 = 1000 * mega
SpeedFormat = regexp.MustCompile(`^(\d+)((M|G)bps)$`)
)

func allowedSpeedsString() string {
allowedStrings := []string{}
for _, allowedSpeed := range allowedSpeeds {
allowedStrings = append(allowedStrings, allowedSpeed.Str)
}
return strings.Join(allowedStrings, ", ")
}

func speedStrToUint(speed string) (uint64, error) {
allowedStrings := []string{}
for _, allowedSpeed := range allowedSpeeds {
if allowedSpeed.Str == speed {
return allowedSpeed.Int, nil
parts := SpeedFormat.FindStringSubmatch(speed)
if parts != nil {
base, err := strconv.Atoi(parts[1])
if parts[2] == "Mbps" {
return uint64(base) * mega, nil
} else if parts[2] == "Gbps" {
return uint64(base) * giga, nil
}
allowedStrings = append(allowedStrings, allowedSpeed.Str)
return 0, err
}
return 0, fmt.Errorf("invalid speed string: %s. Allowed strings: %s", speed, strings.Join(allowedStrings, ", "))
return 0, fmt.Errorf("invalid speed string %v, must match %v", speed, SpeedFormat.String())
}

func speedUintToStr(speed uint64) (string, error) {
allowedUints := []uint64{}
for _, allowedSpeed := range allowedSpeeds {
if speed == allowedSpeed.Int {
return allowedSpeed.Str, nil
}
allowedUints = append(allowedUints, allowedSpeed.Int)
var base uint64
var unit string

if (speed % giga) == 0 {
unit = "Gbps"
base = speed / giga
} else if (speed % mega) == 0 {
unit = "Mbps"
base = speed / mega
} else {
return "", fmt.Errorf("unsupported speed value %v", speed)
}
return "", fmt.Errorf("%d is not allowed speed value. Allowed values: %v", speed, allowedUints)
return strconv.Itoa(int(base)) + unit, nil
}
20 changes: 18 additions & 2 deletions internal/resources/metal/connection/speed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,28 @@ func TestSpeedConversion(t *testing.T) {
}

speedUint, err = speedStrToUint("100Gbps")
if err == nil {
t.Errorf("Expected error converting invalid speed string to uint, got: %d", speedUint)
if err != nil {
t.Errorf("Error converting speed string to uint64: %s", err)
}
if speedUint != 100*giga {
t.Errorf("Speed string conversion failed. Expected: %d, got: %d", 100*giga, speedUint)
}

speedStr, err = speedUintToStr(100 * giga)
if err != nil {
t.Errorf("Error converting speed uint to string: %s", err)
}
if speedStr != "100Gbps" {
t.Errorf("Speed uint conversion failed. Expected: %s, got: %s", "100Gbps", speedStr)
}

speedStr, err = speedUintToStr(100*giga + 2)
if err == nil {
t.Errorf("Expected error converting invalid speed uint to string, got: %s", speedStr)
}

speedUint, err = speedStrToUint("100kWh")
if err == nil {
t.Errorf("Expected error converting invalid speed string to uint, got: %d", speedUint)
}
}
Loading