Skip to content

Commit 2d017cc

Browse files
Add Location metadata to results (#18)
* Add Location type to v2.Targets
1 parent fc420b5 commit 2d017cc

File tree

6 files changed

+80
-75
lines changed

6 files changed

+80
-75
lines changed

api/v2/api.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ type NextRequest struct {
7777
URL string `json:"url"`
7878
}
7979

80+
// Location contains metadata about the geographic location of a target machine.
81+
type Location struct {
82+
City string `json:"city"`
83+
Country string `json:"country"`
84+
}
85+
8086
// Target contains information needed to run a measurement to a measurement
8187
// service on a single M-Lab machine. Measurement services may support multiple
8288
// resources. A Target contains at least one measurement service resource in
@@ -85,6 +91,9 @@ type Target struct {
8591
// Machine is the FQDN of the machine hosting the measurement service.
8692
Machine string `json:"machine"`
8793

94+
// Location contains metadata about the geographic location of the target machine.
95+
Location *Location `json:"location,omitempty"`
96+
8897
// URLs contains measurement service resource names and the complete URL for
8998
// running a measurement.
9099
//

handler/handler.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type Client struct {
3535
// Locator defines how the TranslatedQuery handler requests machines nearest to
3636
// the client.
3737
type Locator interface {
38-
Nearest(ctx context.Context, service, lat, lon string) ([]string, error)
38+
Nearest(ctx context.Context, service, lat, lon string) ([]v2.Target, error)
3939
}
4040

4141
// NewClient creates a new client.
@@ -76,17 +76,16 @@ func (c *Client) TranslatedQuery(rw http.ResponseWriter, req *http.Request) {
7676

7777
// Make proxy request using AppEngine provided lat,lon.
7878
lat, lon := splitLatLon(req.Header.Get("X-AppEngine-CityLatLong"))
79-
machines, err := c.Nearest(req.Context(), service, lat, lon)
79+
targets, err := c.Nearest(req.Context(), service, lat, lon)
8080
if err != nil {
8181
result.Error = v2.NewError("nearest", "Failed to lookup nearest machines", http.StatusInternalServerError)
8282
writeResult(rw, result.Error.Status, &result)
8383
return
8484
}
8585

86-
// Construct result targets with empty URLs.
87-
targets := []v2.Target{}
88-
for i := range machines {
89-
targets = append(targets, v2.Target{Machine: machines[i], URLs: map[string]string{}})
86+
// Update targets with empty URLs.
87+
for i := range targets {
88+
targets[i].URLs = map[string]string{}
9089
}
9190

9291
// Populate each set of URLs using the ports configuration.

handler/handler_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ func (s *fakeSigner) Sign(cl jwt.Claims) (string, error) {
3333
}
3434

3535
type fakeLocator struct {
36-
err error
37-
machines []string
36+
err error
37+
targets []v2.Target
3838
}
3939

40-
func (l *fakeLocator) Nearest(ctx context.Context, service, lat, lon string) ([]string, error) {
40+
func (l *fakeLocator) Nearest(ctx context.Context, service, lat, lon string) ([]v2.Target, error) {
4141
if l.err != nil {
4242
return nil, l.err
4343
}
44-
return l.machines, nil
44+
return l.targets, nil
4545
}
4646

4747
func TestClient_TranslatedQuery(t *testing.T) {
@@ -73,7 +73,7 @@ func TestClient_TranslatedQuery(t *testing.T) {
7373
path: "ndt/ndt5",
7474
signer: &fakeSigner{},
7575
locator: &fakeLocator{
76-
machines: []string{"mlab1-lga0t.measurement-lab.org"},
76+
targets: []v2.Target{{Machine: "mlab1-lga0t.measurement-lab.org"}},
7777
},
7878
latlon: "40.3,-70.4",
7979
wantKey: "ws://:3001/ndt_protocol",
@@ -116,9 +116,9 @@ func TestClient_TranslatedQuery(t *testing.T) {
116116
t.Errorf("TranslatedQuery() wrong status; got %d, want %d", result.Error.Status, tt.wantStatus)
117117
}
118118
// pretty.Print(result)
119-
if len(tt.locator.machines) != len(result.Results) {
119+
if len(tt.locator.targets) != len(result.Results) {
120120
t.Errorf("TranslateQuery() wrong result count; got %d, want %d",
121-
len(result.Results), len(tt.locator.machines))
121+
len(result.Results), len(tt.locator.targets))
122122
}
123123
if len(result.Results[0].URLs) != len(static.Configs[tt.path]) {
124124
t.Errorf("TranslateQuery() result wrong URL count; got %d, want %d",

handler/monitoring_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func TestClient_Monitoring(t *testing.T) {
3838
},
3939
signer: &fakeSigner{},
4040
locator: &fakeLocator{
41-
machines: []string{"mlab1-lga0t.measurement-lab.org"},
41+
targets: []v2.Target{{Machine: "mlab1-lga0t.measurement-lab.org"}},
4242
},
4343
path: "ndt/ndt5",
4444
wantKey: "wss://:3010/ndt_protocol",

proxy/proxy.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"github.com/m-lab/go/host"
1515
"github.com/m-lab/go/rtx"
16+
v2 "github.com/m-lab/locate/api/v2"
1617
"github.com/m-lab/locate/static"
1718
)
1819

@@ -25,7 +26,9 @@ var (
2526
type geoOptions []target
2627

2728
type target struct {
28-
FQDN string `json:"fqdn"`
29+
FQDN string `json:"fqdn"`
30+
City string `json:"city"`
31+
Country string `json:"country"`
2932
}
3033

3134
// LegacyLocator manages requests to the legacy mlab-ns service.
@@ -50,7 +53,7 @@ var ErrNoContent = errors.New("no content from server")
5053

5154
// Nearest discovers the nearest machines for the target service, using a
5255
// proxied request to the LegacyServer such as mlab-ns.
53-
func (ll *LegacyLocator) Nearest(ctx context.Context, service, lat, lon string) ([]string, error) {
56+
func (ll *LegacyLocator) Nearest(ctx context.Context, service, lat, lon string) ([]v2.Target, error) {
5457
path, ok := static.LegacyServices[service]
5558
if !ok {
5659
return nil, fmt.Errorf("Unsupported service: %q", service)
@@ -100,21 +103,22 @@ func UnmarshalResponse(req *http.Request, result interface{}) (*http.Response, e
100103

101104
// collect reads all FQDN results from the given options and guarantees to
102105
// return v2 formatted hostnames.
103-
func (ll *LegacyLocator) collect(opts *geoOptions) []string {
104-
targets := []string{}
106+
func (ll *LegacyLocator) collect(opts *geoOptions) []v2.Target {
107+
targets := []v2.Target{}
105108
for _, opt := range *opts {
106109
name, err := host.Parse(opt.FQDN)
107110
if err != nil {
108111
continue
109112
}
110-
// TODO: after the v2 migration, eliminate v1 logic.
111-
if name.Version == "v1" {
112-
// Convert name to v2.
113-
name.Project = ll.project
114-
name.Version = "v2"
113+
target := v2.Target{
114+
Machine: name.String(),
115+
Location: &v2.Location{
116+
City: opt.City,
117+
Country: opt.Country,
118+
},
115119
}
116120
// Convert the service name into a canonical machine name.
117-
targets = append(targets, name.String())
121+
targets = append(targets, target)
118122
}
119123
return targets
120124
}

proxy/proxy_test.go

Lines changed: 44 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,22 @@ import (
66
"net/http"
77
"net/http/httptest"
88
"net/url"
9-
"reflect"
109
"testing"
1110

11+
"github.com/go-test/deep"
1212
"github.com/m-lab/go/rtx"
13+
v2 "github.com/m-lab/locate/api/v2"
1314
"github.com/m-lab/locate/static"
1415
)
1516

16-
var legacyNames = `[
17-
{
18-
"ip": [
19-
"128.177.119.203",
20-
"2001:438:fffd:2b::203"
21-
],
22-
"country": "US",
23-
"city": "New York_NY",
24-
"fqdn": "ndt-iupui-mlab1-lga06.measurement-lab.org",
25-
"site": "lga06"
26-
},
27-
{
28-
"ip": [
29-
"4.35.94.37",
30-
"2001:1900:2100:14::37"
31-
],
32-
"country": "US",
33-
"city": "New York_NY",
34-
"fqdn": "ndt-iupui-mlab3-lga05.measurement-lab.org",
35-
"site": "lga05"
36-
}
37-
]`
38-
3917
var projectNames = `[
4018
{
4119
"ip": [
4220
"128.177.119.203",
4321
"2001:438:fffd:2b::203"
4422
],
4523
"country": "US",
46-
"city": "New York_NY",
24+
"city": "New York",
4725
"fqdn": "ndt-mlab1-lga06.mlab-staging.measurement-lab.org",
4826
"site": "lga06"
4927
},
@@ -53,7 +31,7 @@ var projectNames = `[
5331
"2001:1900:2100:14::37"
5432
],
5533
"country": "US",
56-
"city": "New York_NY",
34+
"city": "New York",
5735
"fqdn": "ndt-mlab3-lga05.mlab-staging.measurement-lab.org",
5836
"site": "lga05"
5937
}
@@ -66,8 +44,8 @@ var shortNames = `[
6644
"2001:5a0:4300::152"
6745
],
6846
"country": "US",
69-
"city": "New York_NY",
70-
"fqdn": "ndt-mlab2-lga03.measurement-lab.org",
47+
"city": "New York",
48+
"fqdn": "ndt-mlab2-lga03.mlab-sandbox.measurement-lab.org",
7149
"site": "lga03"
7250
},
7351
{
@@ -76,8 +54,8 @@ var shortNames = `[
7654
"2001:550:1d00:100::165"
7755
],
7856
"country": "US",
79-
"city": "New York_NY",
80-
"fqdn": "ndt-mlab3-lga08.measurement-lab.org",
57+
"city": "New York",
58+
"fqdn": "ndt-mlab3-lga08.mlab-sandbox.measurement-lab.org",
8159
"site": "lga08"
8260
}
8361
]`
@@ -89,7 +67,7 @@ var badNames = `[
8967
"2001:5a0:4300::152"
9068
],
9169
"country": "US",
92-
"city": "New York_NY",
70+
"city": "New York",
9371
"fqdn": "invalid-hostname.measurementlab.net",
9472
"site": "lga03"
9573
},
@@ -99,7 +77,7 @@ var badNames = `[
9977
"2001:550:1d00:100::165"
10078
],
10179
"country": "US",
102-
"city": "New York_NY",
80+
"city": "New York",
10381
"fqdn": "invalid-hostname-2.measurementlab.net",
10482
"site": "lga08"
10583
}
@@ -132,29 +110,31 @@ func TestNearest(t *testing.T) {
132110
breakReader bool
133111
badScheme string
134112
badURL string
135-
want []string
113+
want []v2.Target
136114
wantErr bool
137115
}{
138-
{
139-
name: "success-legacy-names",
140-
service: "ndt/ndt5",
141-
lat: "40.3",
142-
lon: "-70.1",
143-
content: legacyNames,
144-
status: http.StatusOK,
145-
want: []string{
146-
"mlab1-lga06.mlab-testing.measurement-lab.org", "mlab3-lga05.mlab-testing.measurement-lab.org",
147-
},
148-
},
149116
{
150117
name: "success-project-names",
151118
service: "ndt/ndt5",
152119
lat: "40.3",
153120
lon: "-70.1",
154121
content: projectNames,
155122
status: http.StatusOK,
156-
want: []string{
157-
"mlab1-lga06.mlab-staging.measurement-lab.org", "mlab3-lga05.mlab-staging.measurement-lab.org",
123+
want: []v2.Target{
124+
{
125+
Machine: "mlab1-lga06.mlab-staging.measurement-lab.org",
126+
Location: &v2.Location{
127+
City: "New York",
128+
Country: "US",
129+
},
130+
},
131+
{
132+
Machine: "mlab3-lga05.mlab-staging.measurement-lab.org",
133+
Location: &v2.Location{
134+
City: "New York",
135+
Country: "US",
136+
},
137+
},
158138
},
159139
},
160140
{
@@ -164,8 +144,21 @@ func TestNearest(t *testing.T) {
164144
lon: "-70.1",
165145
content: shortNames,
166146
status: http.StatusOK,
167-
want: []string{
168-
"mlab2-lga03.mlab-testing.measurement-lab.org", "mlab3-lga08.mlab-testing.measurement-lab.org",
147+
want: []v2.Target{
148+
{
149+
Machine: "mlab2-lga03.mlab-sandbox.measurement-lab.org",
150+
Location: &v2.Location{
151+
City: "New York",
152+
Country: "US",
153+
},
154+
},
155+
{
156+
Machine: "mlab3-lga08.mlab-sandbox.measurement-lab.org",
157+
Location: &v2.Location{
158+
City: "New York",
159+
Country: "US",
160+
},
161+
},
169162
},
170163
},
171164
{
@@ -175,7 +168,7 @@ func TestNearest(t *testing.T) {
175168
lon: "-70.1",
176169
content: badNames,
177170
status: http.StatusOK,
178-
want: []string{},
171+
want: []v2.Target{},
179172
},
180173
{
181174
name: "error-no-content",
@@ -241,8 +234,8 @@ func TestNearest(t *testing.T) {
241234
t.Errorf("Nearest() error = %v, wantErr %v", err, tt.wantErr)
242235
return
243236
}
244-
if !reflect.DeepEqual(got, tt.want) {
245-
t.Errorf("Nearest() = %v, want %v", got, tt.want)
237+
if diff := deep.Equal(got, tt.want); diff != nil {
238+
t.Errorf("Nearest() = %#v, want %v", diff, tt.want)
246239
}
247240
})
248241
}

0 commit comments

Comments
 (0)