services/device/device: have publish create new envelope versions
Instead of always using version "0", publish now uploads envelopes at a
new version each time. The version is based on the timestamp.
The envelope from the latest existing version is transfered over to the
new version (keeping with the flag/package preservation behavior of the
old publish command).
Prod and staging need to be updated to fetch updated envelopes from
unversioned object names before checking this in.
MultiPart: 1/2
Change-Id: Id1e059f9bb11c58ea61a9878698b182d29da31b2
diff --git a/services/device/device/publish.go b/services/device/device/publish.go
index 5862d86..f7d84a0 100644
--- a/services/device/device/publish.go
+++ b/services/device/device/publish.go
@@ -140,8 +140,7 @@
// TODO(caprita): use the profile detection machinery and/or let user
// specify the profile by hand.
profile := fmt.Sprintf("%s-%s", goosFlag, goarchFlag)
- // TODO(caprita): use a label e.g. "prod" instead of "0".
- appVON := naming.Join(applicationService, envelopeName, "0")
+ appVON := naming.Join(applicationService, envelopeName)
appClient := repository.ApplicationClient(appVON)
envelope, err := appClient.Match(ctx, []string{profile})
if verror.ErrorID(err) == verror.ErrNoExist.ID {
@@ -173,8 +172,16 @@
envelope.Binary.Signature = security.Signature{}
envelope.Publisher = security.Blessings{}
}
-
- if err := appClient.Put(ctx, profile, envelope, true); err != nil {
+ appVON = naming.Join(appVON, timestamp)
+ appClient = repository.ApplicationClient(appVON)
+ if err := appClient.Put(ctx, profile, envelope, false); err != nil {
+ // NOTE(caprita): We don't retry if an envelope already exists
+ // at the versioned name, as we do when uploading binaries. In
+ // the case of binaries, it's likely that the same binary is
+ // uploaded more than once in a given second, due to apps
+ // sharing the same binary. The scenarios where the same app is
+ // published repeatedly in a short time-frame are expected to be
+ // rare, and the operator can retry manually in such cases.
return err
}
fmt.Fprintf(env.Stdout, "Published %q\n", appVON)
diff --git a/services/device/mgmt_v23_test.go b/services/device/mgmt_v23_test.go
index 5940bcc..78a7795 100644
--- a/services/device/mgmt_v23_test.go
+++ b/services/device/mgmt_v23_test.go
@@ -350,14 +350,14 @@
// Allow publishers to create and update envelopes
deviceBin.Run("acl", "set", appDName, "root/a", "Read,Write,Resolve")
- sampleAppName := appDName + "/testapp/0"
+ sampleAppName := appDName + "/testapp"
appPubName := "testbinaryd"
appEnvelopeFilename := filepath.Join(workDir, "app.envelope")
appEnvelope := fmt.Sprintf("{\"Title\":\"BINARYD\", \"Args\":[\"--name=%s\", \"--root-dir=./binstore\", \"--v23.tcp.address=127.0.0.1:0\", \"--http=127.0.0.1:0\"], \"Binary\":{\"File\":%q}, \"Env\":[]}", appPubName, sampleAppBinName)
ioutil.WriteFile(appEnvelopeFilename, []byte(appEnvelope), 0666)
defer os.Remove(appEnvelopeFilename)
- output := applicationBin.Run("put", sampleAppName, deviceProfile, appEnvelopeFilename)
+ output := applicationBin.Run("put", sampleAppName+"/0", deviceProfile, appEnvelopeFilename)
if got, want := output, fmt.Sprintf("Application envelope added for profile %s.", deviceProfile); got != want {
i.Fatalf("got %q, want %q", got, want)
}