services/application/applicationd: return newest envelope
Given multiple applications with different versions, return the
highest one by lexiographic sort order if no version is provied.
Change-Id: I17ab9a95eab557814b115c431de0010d4e7e83a6
diff --git a/services/application/applicationd/impl_test.go b/services/application/applicationd/impl_test.go
index 781403c..aa53303 100644
--- a/services/application/applicationd/impl_test.go
+++ b/services/application/applicationd/impl_test.go
@@ -64,8 +64,10 @@
// Create client stubs for talking to the server.
stub := repository.ApplicationClient(naming.JoinAddressName(endpoint, "search"))
+ stubV0 := repository.ApplicationClient(naming.JoinAddressName(endpoint, "search/v0"))
stubV1 := repository.ApplicationClient(naming.JoinAddressName(endpoint, "search/v1"))
stubV2 := repository.ApplicationClient(naming.JoinAddressName(endpoint, "search/v2"))
+ stubV3 := repository.ApplicationClient(naming.JoinAddressName(endpoint, "search/v3"))
blessings, sig := newPublisherSignature(t, ctx, []byte("binarycontents"))
@@ -88,6 +90,15 @@
},
Publisher: blessings,
}
+ envelopeV3 := application.Envelope{
+ Args: []string{"--verbose", "--spiffynewflag"},
+ Env: []string{"DEBUG=0"},
+ Binary: application.SignedFile{
+ File: "/v23/name/of/binary",
+ Signature: sig,
+ },
+ Publisher: blessings,
+ }
// Test Put(), adding a number of application envelopes.
if err := stubV1.Put(ctx, []string{"base", "media"}, envelopeV1); err != nil {
@@ -121,8 +132,45 @@
if _, err := stubV2.Match(ctx, []string{}); err == nil || verror.ErrorID(err) != verror.ErrNoExist.ID {
t.Fatalf("Unexpected error: expected %v, got %v", verror.ErrNoExist, err)
}
- if _, err := stub.Match(ctx, []string{"media"}); err == nil || verror.ErrorID(err) != appd.ErrInvalidSuffix.ID {
- t.Fatalf("Unexpected error: expected %v, got %v", appd.ErrInvalidSuffix, err)
+
+ // Test that Match() against a name without a version suffix returns the latest.
+ if output, err = stub.Match(ctx, []string{"base", "media"}); err != nil {
+ t.Fatalf("Match() failed: %v", err)
+ }
+ if !reflect.DeepEqual(envelopeV2, output) {
+ t.Fatalf("Incorrect output: expected %v, got %v", envelopeV2, output)
+ }
+
+ // Test that we can add another envelope in sort order and we still get the
+ // correct (i.e. newest) version.
+ if err := stubV3.Put(ctx, []string{"base"}, envelopeV3); err != nil {
+ t.Fatalf("Put() failed: %v", err)
+ }
+ if output, err = stub.Match(ctx, []string{"base", "media"}); err != nil {
+ t.Fatalf("Match() failed: %v", err)
+ }
+ if !reflect.DeepEqual(envelopeV3, output) {
+ t.Fatalf("Incorrect output: expected %v, got %v", envelopeV3, output)
+ }
+
+ // Test that this is not based on time but on sort order.
+ envelopeV0 := application.Envelope{
+ Args: []string{"--help", "--zeroth"},
+ Env: []string{"DEBUG=1"},
+ Binary: application.SignedFile{
+ File: "/v23/name/of/binary",
+ Signature: sig,
+ },
+ Publisher: blessings,
+ }
+ if err := stubV0.Put(ctx, []string{"base"}, envelopeV0); err != nil {
+ t.Fatalf("Put() failed: %v", err)
+ }
+ if output, err = stub.Match(ctx, []string{"base", "media"}); err != nil {
+ t.Fatalf("Match() failed: %v", err)
+ }
+ if !reflect.DeepEqual(envelopeV3, output) {
+ t.Fatalf("Incorrect output: expected %v, got %v", envelopeV3, output)
}
// Test Glob
@@ -133,8 +181,10 @@
expected := []string{
"",
"search",
+ "search/v0",
"search/v1",
"search/v2",
+ "search/v3",
}
if !reflect.DeepEqual(matches, expected) {
t.Errorf("unexpected Glob results. Got %q, want %q", matches, expected)
diff --git a/services/application/applicationd/service.go b/services/application/applicationd/service.go
index e79ff03..6a8ad11 100644
--- a/services/application/applicationd/service.go
+++ b/services/application/applicationd/service.go
@@ -5,6 +5,7 @@
package main
import (
+ "sort"
"strings"
"v.io/x/ref/services/internal/fs"
@@ -66,13 +67,22 @@
if err != nil {
return empty, err
}
- if version == "" {
- return empty, verror.New(ErrInvalidSuffix, ctx)
- }
i.store.Lock()
defer i.store.Unlock()
+ if version == "" {
+ versions, err := i.allAppVersions(name)
+ if err != nil {
+ return empty, err
+ }
+ if len(versions) < 1 {
+ return empty, verror.New(ErrInvalidSuffix, ctx)
+ }
+ sort.Strings(versions)
+ version = versions[len(versions)-1]
+ }
+
for _, profile := range profiles {
path := naming.Join("/applications", name, profile, version)
entry, err := i.store.BindObject(path).Get(call)