Skip to content

Commit 999e57b

Browse files
authored
Adds funcs to return strings w/ prefixes and suffixes (#158)
* Adds funcs to return strings w/ prefixes and suffixes Previously, the only string function returned a typical mlab hostname. This commit adds additional string functions to return various combinations of the hostname with or without prefixes and suffixes. Additionally, this commit modifies the v2 regexp to capture and return an prefix. Previously the prefix match was a non-capturing group. * Renames Prefix to Service + PR feedback changes * Fixes String functions + adds more unit tests I realized that some of the String* functions would return bad hostnames in the event that certain fields were not present in the input hostname. This commit should fix that. Also, this commit adds unit tests for the new String* functions to be sure they are doing what we expect. * Simplifies the String function, reusing existing functionality
1 parent 3c1e2c3 commit 999e57b

File tree

2 files changed

+186
-54
lines changed

2 files changed

+186
-54
lines changed

host/host.go

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
// Name represents an M-Lab hostname and all of its constituent parts.
1313
type Name struct {
14+
Service string
1415
Machine string
1516
Site string
1617
Project string
@@ -25,7 +26,7 @@ func Parse(name string) (Name, error) {
2526
var parts Name
2627

2728
reV1 := regexp.MustCompile(`(?:[a-z-.]+)?(mlab[1-4]d?)[-.]([a-z]{3}[0-9tc]{2})\.(measurement-lab.org)$`)
28-
reV2 := regexp.MustCompile(`(?:[a-z-.]+)?(mlab[1-4]d?)-([a-z]{3}[0-9tc]{2})\.(.*?)\.(measurement-lab.org)-?([a-z0-9]{4})?$`)
29+
reV2 := regexp.MustCompile(`([a-z0-9]+)?-?(mlab[1-4]d?)-([a-z]{3}[0-9tc]{2})\.(.*?)\.(measurement-lab.org)(-[a-z0-9]{4})?$`)
2930

3031
// Example hostnames with field counts when split by '.':
3132
// v1
@@ -34,34 +35,36 @@ func Parse(name string) (Name, error) {
3435
// ndt.iupui.mlab1.lga01.measurement-lab.org - 6
3536
// v2
3637
// mlab1-lga01.mlab-oti.measurement-lab.org - 4
37-
// mlab1-lga01.mlab-oti.measurement-lab.org-d9h6 - 4 (A MIG instance with a random suffix)
38+
// mlab1-lga01.mlab-oti.measurement-lab.org-d9h6 - 4 (A MIG instance with a random suffix)
39+
// ndt-mlab1-lga01.mlab-oti.measurement-lab.org-d9h6 - 4 (A MIG instance with a service and random suffix)
3840
// ndt-iupui-mlab1-lga01.mlab-oti.measurement-lab.org - 4
3941
// ndt-mlab1-lga01.mlab-oti.measurement-lab.org - 4
4042

4143
fields := strings.Split(name, ".")
4244
if len(fields) < 3 || len(fields) > 6 {
43-
return parts, fmt.Errorf("Invalid hostname: %s", name)
45+
return parts, fmt.Errorf("invalid hostname: %s", name)
4446
}
4547

4648
// v2 names always have four fields. And the first field will always
4749
// be longer than a machine name e.g. "mlab1".
4850
if len(fields) == 4 && len(fields[0]) > 6 {
4951
mV2 := reV2.FindAllStringSubmatch(name, -1)
50-
if len(mV2) != 1 || len(mV2[0]) != 6 {
51-
return parts, fmt.Errorf("Invalid v2 hostname: %s", name)
52+
if len(mV2) != 1 || len(mV2[0]) != 7 {
53+
return parts, fmt.Errorf("invalid v2 hostname: %s", name)
5254
}
5355
parts = Name{
54-
Machine: mV2[0][1],
55-
Site: mV2[0][2],
56-
Project: mV2[0][3],
57-
Domain: mV2[0][4],
58-
Suffix: mV2[0][5],
56+
Service: mV2[0][1],
57+
Machine: mV2[0][2],
58+
Site: mV2[0][3],
59+
Project: mV2[0][4],
60+
Domain: mV2[0][5],
61+
Suffix: mV2[0][6],
5962
Version: "v2",
6063
}
6164
} else {
6265
mV1 := reV1.FindAllStringSubmatch(name, -1)
6366
if len(mV1) != 1 || len(mV1[0]) != 4 {
64-
return parts, fmt.Errorf("Invalid v1 hostname: %s", name)
67+
return parts, fmt.Errorf("invalid v1 hostname: %s", name)
6568
}
6669
parts = Name{
6770
Machine: mV1[0][1],
@@ -75,6 +78,8 @@ func Parse(name string) (Name, error) {
7578
return parts, nil
7679
}
7780

81+
// Returns a typical M-Lab machine hostname
82+
// Example: mlab2-abc01.mlab-sandbox.measurement-lab.org
7883
func (n Name) String() string {
7984
switch n.Version {
8085
case "v2":
@@ -83,3 +88,25 @@ func (n Name) String() string {
8388
return fmt.Sprintf("%s.%s.%s", n.Machine, n.Site, n.Domain)
8489
}
8590
}
91+
92+
// Returns an M-lab hostname with any service name preserved
93+
// Example: ndt-mlab1-abc01.mlab-sandbox.measurement-lab.org
94+
func (n Name) StringWithService() string {
95+
if n.Service != "" {
96+
return fmt.Sprintf("%s-%s-%s.%s.%s", n.Service, n.Machine, n.Site, n.Project, n.Domain)
97+
} else {
98+
return n.String()
99+
}
100+
}
101+
102+
// Returns an M-lab hostname with any suffix preserved
103+
// Example: mlab1-abc01.mlab-sandbox.measurement-lab.org-gz77
104+
func (n Name) StringWithSuffix() string {
105+
return fmt.Sprintf("%s-%s.%s.%s%s", n.Machine, n.Site, n.Project, n.Domain, n.Suffix)
106+
}
107+
108+
// Returns an M-lab hostname with any service and suffix preserved
109+
// Example: ndt-mlab1-abc01.mlab-sandbox.measurement-lab.org-gz77
110+
func (n Name) StringAll() string {
111+
return n.StringWithService() + n.Suffix
112+
}

host/host_test.go

Lines changed: 148 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -27,100 +27,91 @@ func TestName(t *testing.T) {
2727
},
2828
{
2929
name: "valid-v2",
30-
hostname: "mlab1-lol01.mlab-oti.measurement-lab.org",
30+
hostname: "mlab1-lol01.mlab-sandbox.measurement-lab.org",
3131
want: Name{
3232
Machine: "mlab1",
3333
Site: "lol01",
34-
Project: "mlab-oti",
34+
Project: "mlab-sandbox",
3535
Domain: "measurement-lab.org",
3636
Version: "v2",
3737
},
3838
},
3939
{
4040
name: "valid-v2-with-suffix",
41-
hostname: "mlab1-lol01.mlab-oti.measurement-lab.org-a9b8",
41+
hostname: "mlab1-lol01.mlab-sandbox.measurement-lab.org-a9b8",
4242
want: Name{
4343
Machine: "mlab1",
4444
Site: "lol01",
45-
Project: "mlab-oti",
45+
Project: "mlab-sandbox",
4646
Domain: "measurement-lab.org",
47-
Suffix: "a9b8",
47+
Suffix: "-a9b8",
4848
Version: "v2",
4949
},
5050
},
5151
{
52-
name: "valid-v1-bmc",
53-
hostname: "mlab1d.lol01.measurement-lab.org",
54-
want: Name{
55-
Machine: "mlab1d",
56-
Site: "lol01",
57-
Domain: "measurement-lab.org",
58-
Version: "v1",
59-
},
60-
},
61-
{
62-
name: "valid-v2-bmc",
63-
hostname: "mlab1d-lol01.mlab-oti.measurement-lab.org",
52+
name: "valid-v2-with-service",
53+
hostname: "ndt-mlab1-lol01.mlab-sandbox.measurement-lab.org",
6454
want: Name{
65-
Machine: "mlab1d",
55+
Service: "ndt",
56+
Machine: "mlab1",
6657
Site: "lol01",
67-
Project: "mlab-oti",
58+
Project: "mlab-sandbox",
6859
Domain: "measurement-lab.org",
6960
Version: "v2",
7061
},
7162
},
7263
{
73-
name: "valid-v1-with-ndt-flat",
74-
hostname: "ndt-iupui-mlab1-lol01.measurement-lab.org",
64+
name: "valid-v2-with-service-and-suffix",
65+
hostname: "ndt-mlab1-lol01.mlab-sandbox.measurement-lab.org-a9b8",
7566
want: Name{
67+
Service: "ndt",
7668
Machine: "mlab1",
7769
Site: "lol01",
70+
Project: "mlab-sandbox",
7871
Domain: "measurement-lab.org",
79-
Version: "v1",
72+
Suffix: "-a9b8",
73+
Version: "v2",
8074
},
8175
},
8276
{
83-
name: "valid-v1-with-ndt-regular",
84-
hostname: "ndt.iupui.mlab1.lol01.measurement-lab.org",
77+
name: "valid-v1-bmc",
78+
hostname: "mlab1d.lol01.measurement-lab.org",
8579
want: Name{
86-
Machine: "mlab1",
80+
Machine: "mlab1d",
8781
Site: "lol01",
8882
Domain: "measurement-lab.org",
8983
Version: "v1",
9084
},
9185
},
9286
{
93-
name: "valid-v2-with-ndt",
94-
hostname: "ndt-iupui-mlab1-lol01.mlab-oti.measurement-lab.org",
87+
name: "valid-v2-bmc",
88+
hostname: "mlab1d-lol01.mlab-sandbox.measurement-lab.org",
9589
want: Name{
96-
Machine: "mlab1",
90+
Machine: "mlab1d",
9791
Site: "lol01",
98-
Project: "mlab-oti",
92+
Project: "mlab-sandbox",
9993
Domain: "measurement-lab.org",
10094
Version: "v2",
10195
},
10296
},
10397
{
104-
name: "valid-v2-with-ndt-short",
105-
hostname: "ndt-mlab1-lol01.mlab-oti.measurement-lab.org",
98+
name: "valid-v1-with-ndt-flat",
99+
hostname: "ndt-iupui-mlab1-lol01.measurement-lab.org",
106100
want: Name{
107101
Machine: "mlab1",
108102
Site: "lol01",
109-
Project: "mlab-oti",
110103
Domain: "measurement-lab.org",
111-
Version: "v2",
104+
Version: "v1",
112105
},
113106
},
114107
{
115-
name: "valid-v2-with-ndt-short-with-suffix",
116-
hostname: "ndt-mlab1-lol01.mlab-oti.measurement-lab.org-q44c",
108+
name: "valid-v1-with-ndt-regular",
109+
hostname: "ndt.iupui.mlab1.lol01.measurement-lab.org",
117110
want: Name{
118111
Machine: "mlab1",
119112
Site: "lol01",
120-
Project: "mlab-oti",
121113
Domain: "measurement-lab.org",
122-
Suffix: "q44c",
123-
Version: "v2",
114+
Version: "v1",
124115
},
125116
},
126117
{
@@ -172,7 +163,7 @@ func TestName(t *testing.T) {
172163
return
173164
}
174165
if !reflect.DeepEqual(result, test.want) {
175-
t.Errorf("\nUnexpected result. Got:\n%+v\nExpected:\n%+v", result, test.want)
166+
t.Errorf("\nUnexpected result. Got:\n%#v\nExpected:\n%#v", result, test.want)
176167
}
177168
})
178169
}
@@ -181,16 +172,130 @@ func TestName(t *testing.T) {
181172
func TestName_String(t *testing.T) {
182173
tests := []struct {
183174
name string
175+
want string
184176
}{
185-
{name: "mlab1.foo01.measurement-lab.org"},
186-
{name: "mlab1-foo01.mlab-sandbox.measurement-lab.org"},
177+
{
178+
name: "mlab1.foo01.measurement-lab.org",
179+
want: "mlab1.foo01.measurement-lab.org",
180+
},
181+
{
182+
name: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
183+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
184+
},
185+
{
186+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
187+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
188+
},
189+
{
190+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
191+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
192+
},
193+
}
194+
for _, tt := range tests {
195+
t.Run(tt.name, func(t *testing.T) {
196+
n, err := Parse(tt.name)
197+
rtx.Must(err, "Failed to parse: %s", tt.name)
198+
if got := n.String(); got != tt.want {
199+
t.Errorf("Name.String() = %v, want %v", got, tt.want)
200+
}
201+
})
202+
}
203+
}
204+
205+
func TestName_StringWithService(t *testing.T) {
206+
tests := []struct {
207+
name string
208+
want string
209+
}{
210+
{
211+
name: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
212+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
213+
},
214+
{
215+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
216+
want: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
217+
},
218+
{
219+
name: "mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
220+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
221+
},
222+
{
223+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
224+
want: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
225+
},
226+
}
227+
for _, tt := range tests {
228+
t.Run(tt.name, func(t *testing.T) {
229+
n, err := Parse(tt.name)
230+
rtx.Must(err, "Failed to parse: %s", tt.name)
231+
if got := n.StringWithService(); got != tt.want {
232+
t.Errorf("Name.StringWithService() = %v, want %v", got, tt.want)
233+
}
234+
})
235+
}
236+
}
237+
238+
func TestName_StringWithSuffix(t *testing.T) {
239+
tests := []struct {
240+
name string
241+
want string
242+
}{
243+
{
244+
name: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
245+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
246+
},
247+
{
248+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
249+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
250+
},
251+
{
252+
name: "mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
253+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
254+
},
255+
{
256+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
257+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
258+
},
259+
}
260+
for _, tt := range tests {
261+
t.Run(tt.name, func(t *testing.T) {
262+
n, err := Parse(tt.name)
263+
rtx.Must(err, "Failed to parse: %s", tt.name)
264+
if got := n.StringWithSuffix(); got != tt.want {
265+
t.Errorf("Name.StringWithSuffix() = %v, want %v", got, tt.want)
266+
}
267+
})
268+
}
269+
}
270+
271+
func TestName_StringAll(t *testing.T) {
272+
tests := []struct {
273+
name string
274+
want string
275+
}{
276+
{
277+
name: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
278+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org",
279+
},
280+
{
281+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
282+
want: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org",
283+
},
284+
{
285+
name: "mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
286+
want: "mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
287+
},
288+
{
289+
name: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
290+
want: "ndt-mlab1-foo01.mlab-sandbox.measurement-lab.org-qf8y",
291+
},
187292
}
188293
for _, tt := range tests {
189294
t.Run(tt.name, func(t *testing.T) {
190295
n, err := Parse(tt.name)
191296
rtx.Must(err, "Failed to parse: %s", tt.name)
192-
if got := n.String(); got != tt.name {
193-
t.Errorf("Name.String() = %v, want %v", got, tt.name)
297+
if got := n.StringAll(); got != tt.want {
298+
t.Errorf("Name.StringAll() = %v, want %v", got, tt.want)
194299
}
195300
})
196301
}

0 commit comments

Comments
 (0)