Skip to content

Commit

Permalink
feat(host): add v3 format for dynamic dns names (#178)
Browse files Browse the repository at this point in the history
* feat(host): add v3 format for dynamic dns names
  • Loading branch information
stephen-soltesz authored Jan 22, 2024
1 parent 088ae14 commit dd8dc69
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 6 deletions.
45 changes: 39 additions & 6 deletions host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Name struct {
Machine string
Site string
Project string
Org string
Domain string
Suffix string
Version string
Expand All @@ -27,6 +28,15 @@ func Parse(name string) (Name, error) {

reV1 := regexp.MustCompile(`(?:[a-z-.]+)?(mlab[1-4]d?)[-.]([a-z]{3}[0-9tc]{2})\.(measurement-lab.org)$`)
reV2 := regexp.MustCompile(`([a-z0-9]+)?-?(mlab[1-4]d?)-([a-z]{3}[0-9tc]{2})\.(.*?)\.(measurement-lab.org)(-[a-z0-9]{4})?$`)
// The v3 naming convention is defined in:
// * https://docs.google.com/document/d/1XHgpX7Tbjy_c71TKsFUxb1_ax2624PB4SE9R15OoD_o/edit?#heading=h.s5vpfclyu15x
// The structure follows the pattern:
// * <service>-<IATA><ASN>-<machine>.<organization>.<project>.measurement-lab.org
// * the same rules apply for service, iata, and project names as earlier versions.
// * most ASNs are 16bit numbers, but since 2007 they can be 32bit numbers, allowing up to 10 decimal digits.
// * machine names are 6 byte base64 encoded IPv4 addresses.
// * site name precedes machine name for readability.
reV3 := regexp.MustCompile(`^(?:([a-z0-9]+)-)?([a-z]{3}[0-9]{1,10})-([a-zA-Z0-9]{6})\.(.*?)\.(.*?)\.(measurement-lab.org)$`)

// Example hostnames with field counts when split by '.':
// v1
Expand All @@ -39,6 +49,10 @@ func Parse(name string) (Name, error) {
// ndt-mlab1-lga01.mlab-oti.measurement-lab.org-d9h6 - 4 (A MIG instance with a service and random suffix)
// ndt-iupui-mlab1-lga01.mlab-oti.measurement-lab.org - 4
// ndt-mlab1-lga01.mlab-oti.measurement-lab.org - 4
// v3
// lga3356-BA6fSw.rnp.autojoin.measurement-lab.org - 5
// ndt-lga3356-BA6fSw.rnp.autojoin.measurement-lab.org - 5
// ndt-lga3356-BA6fSw.mlab.sandbox.measurement-lab.org - 5

if name == "third-party" {
// Unconditionally return a Name for third-party origins.
Expand All @@ -54,9 +68,26 @@ func Parse(name string) (Name, error) {
return parts, fmt.Errorf("invalid hostname: %s", name)
}

// v2 names always have four fields. And the first field will always
// be longer than a machine name e.g. "mlab1".
if len(fields) == 4 && len(fields[0]) > 6 {
// v3 names always have 5 fields.
// v2 names always have 4 fields. And, the first field will always
// be longer than a machine name e.g. "mlab1", which distinguishes
// it from v1 name with four fields.
switch {
case len(fields) == 5:
mV3 := reV3.FindAllStringSubmatch(name, -1)
if len(mV3) != 1 || len(mV3[0]) != 7 {
return parts, fmt.Errorf("invalid v3 hostname: %s", name)
}
parts = Name{
Service: mV3[0][1],
Site: mV3[0][2],
Machine: mV3[0][3],
Org: mV3[0][4],
Project: mV3[0][5],
Domain: mV3[0][6],
Version: "v3",
}
case len(fields) == 4 && len(fields[0]) > 6:
mV2 := reV2.FindAllStringSubmatch(name, -1)
if len(mV2) != 1 || len(mV2[0]) != 7 {
return parts, fmt.Errorf("invalid v2 hostname: %s", name)
Expand All @@ -70,7 +101,7 @@ func Parse(name string) (Name, error) {
Suffix: mV2[0][6],
Version: "v2",
}
} else {
default:
mV1 := reV1.FindAllStringSubmatch(name, -1)
if len(mV1) != 1 || len(mV1[0]) != 4 {
return parts, fmt.Errorf("invalid v1 hostname: %s", name)
Expand All @@ -91,6 +122,8 @@ func Parse(name string) (Name, error) {
// Example: mlab2-abc01.mlab-sandbox.measurement-lab.org
func (n Name) String() string {
switch n.Version {
case "v3":
return fmt.Sprintf("%s-%s.%s.%s.%s", n.Site, n.Machine, n.Org, n.Project, n.Domain)
case "v2":
return fmt.Sprintf("%s-%s.%s.%s", n.Machine, n.Site, n.Project, n.Domain)
default:
Expand All @@ -102,7 +135,7 @@ func (n Name) String() string {
// Example: ndt-mlab1-abc01.mlab-sandbox.measurement-lab.org
func (n Name) StringWithService() string {
if n.Service != "" {
return fmt.Sprintf("%s-%s-%s.%s.%s", n.Service, n.Machine, n.Site, n.Project, n.Domain)
return fmt.Sprintf("%s-%s", n.Service, n.String())
} else {
return n.String()
}
Expand All @@ -111,7 +144,7 @@ func (n Name) StringWithService() string {
// Returns an M-lab hostname with any suffix preserved
// Example: mlab1-abc01.mlab-sandbox.measurement-lab.org-gz77
func (n Name) StringWithSuffix() string {
return fmt.Sprintf("%s-%s.%s.%s%s", n.Machine, n.Site, n.Project, n.Domain, n.Suffix)
return fmt.Sprintf("%s%s", n.String(), n.Suffix)
}

// Returns an M-lab hostname with any service and suffix preserved
Expand Down
71 changes: 71 additions & 0 deletions host/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,61 @@ func TestName(t *testing.T) {
want: Name{},
wantErr: true,
},
{
name: "valid-v3-machine",
hostname: "lol12345-abcdef.mlab.sandbox.measurement-lab.org",
want: Name{
Machine: "abcdef",
Site: "lol12345",
Org: "mlab",
Project: "sandbox",
Domain: "measurement-lab.org",
Version: "v3",
},
},
{
name: "valid-v3-service",
hostname: "ndt-lol12345-abcdef.mlab.sandbox.measurement-lab.org",
want: Name{
Service: "ndt",
Machine: "abcdef",
Site: "lol12345",
Org: "mlab",
Project: "sandbox",
Domain: "measurement-lab.org",
Version: "v3",
},
},
{
name: "invalid-v3-too-long-asn-machine",
hostname: "lol12345678901-abcdef.mlab.sandbox.measurement-lab.org",
want: Name{},
wantErr: true,
},
{
name: "invalid-v3-too-long-asn-service",
hostname: "ndt-lol12345678901-abcdef.mlab.sandbox.measurement-lab.org",
want: Name{},
wantErr: true,
},
{
name: "invalid-v3-site-too-long",
hostname: "abcd12345-abcdef.mlab.sandbox.measurement-lab.org",
want: Name{},
wantErr: true,
},
{
name: "invalid-v3-missing-service",
hostname: "-abc12345-abcdef.mlab.sandbox.measurement-lab.org",
want: Name{},
wantErr: true,
},
{
name: "invalid-v3-machine-too-long",
hostname: "abc12345-abcdef8.mlab.sandbox.measurement-lab.org",
want: Name{},
wantErr: true,
},
}

for _, test := range tests {
Expand Down Expand Up @@ -205,6 +260,10 @@ func TestName_String(t *testing.T) {
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
},
{
name: "ndt-lol12345-abcdef.mlab.sandbox.measurement-lab.org",
want: "lol12345-abcdef.mlab.sandbox.measurement-lab.org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -238,6 +297,10 @@ func TestName_StringWithService(t *testing.T) {
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
want: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
},
{
name: "ndt-lol12345-abcdef.mlab.sandbox.measurement-lab.org",
want: "ndt-lol12345-abcdef.mlab.sandbox.measurement-lab.org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -271,6 +334,10 @@ func TestName_StringWithSuffix(t *testing.T) {
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
},
{
name: "ndt-lol12345-abcdef.mlab.sandbox.measurement-lab.org",
want: "lol12345-abcdef.mlab.sandbox.measurement-lab.org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -304,6 +371,10 @@ func TestName_StringAll(t *testing.T) {
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
want: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
},
{
name: "ndt-lol12345-abcdef.mlab.sandbox.measurement-lab.org",
want: "ndt-lol12345-abcdef.mlab.sandbox.measurement-lab.org",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit dd8dc69

Please sign in to comment.