discovery: InterfaceName support for global discovery.
MultiPart: 1/3
Change-Id: I9adb2056832035e69a308393cdf61d4b1a001a2e
diff --git a/lib/discovery/global/encoding.go b/lib/discovery/global/encoding.go
index 5d3e324..48e516f 100644
--- a/lib/discovery/global/encoding.go
+++ b/lib/discovery/global/encoding.go
@@ -15,7 +15,7 @@
// encodeAdToSuffix encodes the ad.Id and the ad.Attributes into the suffix at
// which we mount the advertisement.
-// The format of the generated suffix is id/timestamp/attributes.
+// The format of the generated suffix is id/interfaceName/timestamp/attributes.
//
// TODO(suharshs): Currently only the id and the attributes are encoded; we may
// want to encode the rest of the advertisement someday?
@@ -26,28 +26,34 @@
}
// Escape suffixDelim to use it as our delimeter between the id and the attrs.
id := ad.Id.String()
+ // InterfaceName can never be empty as per validate.go.
+ interfaceName := naming.EncodeAsNameElement(ad.InterfaceName)
timestamp := strconv.FormatInt(timestampNs, 10)
attr := naming.EncodeAsNameElement(string(b))
- return naming.Join(id, timestamp, attr), nil
+ return naming.Join(id, interfaceName, timestamp, attr), nil
}
// decodeAdFromSuffix decodes in into an advertisement.
-// The format of the input suffix is id/timestamp/attributes.
+// The format of the input suffix is id/interfaceName/timestamp/attributes.
func decodeAdFromSuffix(in string) (*discovery.Advertisement, int64, error) {
- parts := strings.SplitN(in, "/", 3)
- if len(parts) != 3 {
+ parts := strings.SplitN(in, "/", 4)
+ if len(parts) != 4 {
return nil, 0, NewErrAdInvalidEncoding(nil, in)
}
var err error
+ var ok bool
ad := &discovery.Advertisement{}
if ad.Id, err = discovery.ParseAdId(parts[0]); err != nil {
return nil, 0, err
}
- timestampNs, err := strconv.ParseInt(parts[1], 10, 64)
+ if ad.InterfaceName, ok = naming.DecodeFromNameElement(parts[1]); !ok {
+ return nil, 0, NewErrAdInvalidEncoding(nil, in)
+ }
+ timestampNs, err := strconv.ParseInt(parts[2], 10, 64)
if err != nil {
return nil, 0, err
}
- attrs, ok := naming.DecodeFromNameElement(parts[2])
+ attrs, ok := naming.DecodeFromNameElement(parts[3])
if !ok {
return nil, 0, NewErrAdInvalidEncoding(nil, in)
}
diff --git a/lib/discovery/global/encoding_test.go b/lib/discovery/global/encoding_test.go
index 63f369c..2be8f34 100644
--- a/lib/discovery/global/encoding_test.go
+++ b/lib/discovery/global/encoding_test.go
@@ -14,10 +14,28 @@
func TestAdSuffix(t *testing.T) {
testCases := []testCase{
- {ad: &discovery.Advertisement{}, timestampNs: time.Now().UnixNano()},
- {ad: &discovery.Advertisement{Id: discovery.AdId{1, 2, 3}}, timestampNs: time.Now().UnixNano()},
- {ad: &discovery.Advertisement{Attributes: discovery.Attributes{"k": "v"}}, timestampNs: time.Now().UnixNano()},
- {ad: &discovery.Advertisement{Id: discovery.AdId{1, 2, 3}, Attributes: discovery.Attributes{"k": "v"}}, timestampNs: time.Now().UnixNano()},
+ {
+ ad: &discovery.Advertisement{
+ Id: discovery.AdId{1, 2, 3},
+ InterfaceName: "foo",
+ },
+ timestampNs: time.Now().UnixNano(),
+ },
+ {
+ ad: &discovery.Advertisement{
+ Attributes: discovery.Attributes{"k": "v"},
+ InterfaceName: "foo",
+ },
+ timestampNs: time.Now().UnixNano(),
+ },
+ {
+ ad: &discovery.Advertisement{
+ Id: discovery.AdId{1, 2, 3},
+ Attributes: discovery.Attributes{"k": "v"},
+ InterfaceName: "foo",
+ },
+ timestampNs: time.Now().UnixNano(),
+ },
}
for i, want := range testCases {
encAd, err := encodeAdToSuffix(want.ad, want.timestampNs)
diff --git a/lib/discovery/global/global_test.go b/lib/discovery/global/global_test.go
index b889e7f..5021c85 100644
--- a/lib/discovery/global/global_test.go
+++ b/lib/discovery/global/global_test.go
@@ -29,12 +29,14 @@
ads := []discovery.Advertisement{
{
- Id: discovery.AdId{1, 2, 3},
- Addresses: []string{"/h1:123/x", "/h2:123/y"},
- Attributes: discovery.Attributes{"k": "v"},
+ Id: discovery.AdId{1, 2, 3},
+ InterfaceName: "foo/bar/baz",
+ Addresses: []string{"/h1:123/x", "/h2:123/y"},
+ Attributes: discovery.Attributes{"k": "v"},
},
{
- Addresses: []string{"/h1:123/x", "/h2:123/z"},
+ InterfaceName: "foo/bar/baz",
+ Addresses: []string{"/h1:123/x", "/h2:123/z"},
},
}
@@ -113,7 +115,8 @@
defer shutdown()
ad := discovery.Advertisement{
- Addresses: []string{"/h1:123/x"},
+ InterfaceName: "foo/bar/baz",
+ Addresses: []string{"/h1:123/x"},
}
visibility := []security.BlessingPattern{
security.BlessingPattern("test-blessing:bob"),
@@ -160,7 +163,8 @@
defer shutdown()
ad := discovery.Advertisement{
- Addresses: []string{"/h1:123/x"},
+ InterfaceName: "foo/bar/baz",
+ Addresses: []string{"/h1:123/x"},
}
d, _ := New(ctx, testPath)
@@ -190,7 +194,8 @@
ns.SetRoots(mtserver.Status().Endpoints[0].Name())
ad := discovery.Advertisement{
- Addresses: []string{"/h1:123/x"},
+ InterfaceName: "foo/bar/baz",
+ Addresses: []string{"/h1:123/x"},
}
const mountTTL = 10 * time.Second
diff --git a/lib/discovery/global/scan.go b/lib/discovery/global/scan.go
index 489ada1..ddbaf23 100644
--- a/lib/discovery/global/scan.go
+++ b/lib/discovery/global/scan.go
@@ -28,7 +28,7 @@
var prevFound map[discovery.AdId]*idiscovery.AdInfo
for {
- found, err := d.doScan(ctx, matcher.TargetKey(), matcher)
+ found, err := d.doScan(ctx, matcher)
if found == nil {
if err != nil {
ctx.Error(err)
@@ -48,24 +48,8 @@
return updateCh, nil
}
-func (d *gdiscovery) doScan(ctx *context.T, target string, matcher idiscovery.Matcher) (map[discovery.AdId]*idiscovery.AdInfo, error) {
- // If the target is neither empty nor a valid AdId, we return without an error,
- // since there will be not entries with the requested target length in the namespace.
- if len(target) > 0 {
- if _, err := discovery.ParseAdId(target); err != nil {
- return nil, nil
- }
- }
-
- // In the case of empty, we need to scan for everything.
- // In the case where target is a AdId we need to scan for entries prefixed with
- // the AdId with any encoded attributes afterwards.
- if len(target) == 0 {
- target = naming.Join("*", "*", "*")
- } else {
- target = naming.Join(target, "*", "*")
- }
- scanCh, err := d.ns.Glob(ctx, target)
+func (d *gdiscovery) doScan(ctx *context.T, matcher idiscovery.Matcher) (map[discovery.AdId]*idiscovery.AdInfo, error) {
+ scanCh, err := d.ns.Glob(ctx, generateGlobQuery(matcher))
if err != nil {
return nil, err
}
@@ -110,6 +94,20 @@
}
}
+func generateGlobQuery(matcher idiscovery.Matcher) string {
+ // The suffixes are of the form "id/interfaceName/timestamp/attrs" so we need
+ // to replace wildcards in our query with values based on the query matcher.
+ id, interfaceName, timestamp, attrs := "*", "*", "*", "*"
+ // Currently we support query by id or interfaceName.
+ if targetKey := matcher.TargetKey(); targetKey != "" {
+ id = targetKey
+ }
+ if targetInterface := matcher.TargetInterfaceName(); targetInterface != "" {
+ interfaceName = targetInterface
+ }
+ return naming.Join(id, interfaceName, timestamp, attrs)
+}
+
func (d *gdiscovery) hasAd(ad *discovery.Advertisement) bool {
d.mu.Lock()
_, ok := d.ads[ad.Id]
diff --git a/lib/discovery/global/validate.go b/lib/discovery/global/validate.go
index 83eef8e..52a5689 100644
--- a/lib/discovery/global/validate.go
+++ b/lib/discovery/global/validate.go
@@ -15,8 +15,8 @@
if !ad.Id.IsValid() {
return errors.New("id not valid")
}
- if len(ad.InterfaceName) > 0 {
- return errors.New("interface name not supported")
+ if len(ad.InterfaceName) == 0 {
+ return errors.New("interface name not provided")
}
if len(ad.Addresses) == 0 {
return errors.New("address not provided")
diff --git a/lib/discovery/global/validate_test.go b/lib/discovery/global/validate_test.go
index e9a4a6b..132073c 100644
--- a/lib/discovery/global/validate_test.go
+++ b/lib/discovery/global/validate_test.go
@@ -17,37 +17,40 @@
}{
{
discovery.Advertisement{
- Id: discovery.AdId{1, 2, 3},
- Addresses: []string{"/h:123/x"},
- Attributes: discovery.Attributes{"k": "v"},
+ Id: discovery.AdId{1, 2, 3},
+ Addresses: []string{"/h:123/x"},
+ Attributes: discovery.Attributes{"k": "v"},
+ InterfaceName: "foo/bar/baz",
},
true,
},
{
discovery.Advertisement{
- Id: discovery.AdId{}, // Invalid id.
- Addresses: []string{"/h:123/x"},
+ Id: discovery.AdId{}, // Invalid id.
+ Addresses: []string{"/h:123/x"},
+ InterfaceName: "foo/bar/baz",
},
false,
},
{
discovery.Advertisement{ // No addresses.
- Id: discovery.AdId{1, 2, 3},
+ Id: discovery.AdId{1, 2, 3},
+ InterfaceName: "foo/bar/baz",
+ },
+ false,
+ },
+ {
+ discovery.Advertisement{ // Has no interface name.
+ Id: discovery.AdId{1, 2, 3},
+ Addresses: []string{"/h:123/x"},
},
false,
},
{
discovery.Advertisement{
Id: discovery.AdId{1, 2, 3},
- InterfaceName: "v.io/v23/a", // Has interface name.
+ InterfaceName: "foo/bar/baz",
Addresses: []string{"/h:123/x"},
- },
- false,
- },
- {
- discovery.Advertisement{
- Id: discovery.AdId{1, 2, 3},
- Addresses: []string{"/h:123/x"},
Attachments: discovery.Attachments{ // Has attachments.
"k": []byte{1},
},