TBR: allocator: add more information about each instance

Creation time is extracted from deployment json.

Blessing patterns are currently reconstructed at list time (like the
mount name); TODO left to persist them when the instance is created.

Other changes:

Make it a requirement to have a namespace root set (either explicitly
via a new flag, or having the default namespace root be set).  Some of
the logic in name manipulation already assume that, and it's better to
just be able to rely on it always.

Instead of a self-signed blessing, use a blessing derived from
allocatord's own blessing when running without cluster agent.  This
ensures that the blessing is recognized by all (since it will be rooted
at dev.v.io).  To make this harmless, use a caveat that's always
'off' (Asim's suggestion).

Change-Id: Ide750c89cba979d1387ac1f355b0b931624fc5db
diff --git a/services/allocator/allocatord/assets/assets.go b/services/allocator/allocatord/assets/assets.go
index c13984e..433a5c5 100644
--- a/services/allocator/allocatord/assets/assets.go
+++ b/services/allocator/allocatord/assets/assets.go
@@ -204,7 +204,7 @@
 	return a, nil
 }
 
-var _homeTmplHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\x55\x5d\x8f\xdb\x36\x10\x7c\xf7\xaf\xd8\x10\x01\x94\x43\x4e\x12\xd2\xbc\xa5\x92\x80\xa6\x0d\xd0\x00\x39\x17\x68\xd3\x02\x7d\x2a\x28\x71\x6d\x11\xa6\x49\x81\xa4\xec\xaa\x82\xff\x7b\x97\xfa\xb2\xae\xb0\x5b\x5c\x9f\x7c\x94\x46\xb3\x33\x3b\xdc\xbd\xec\x95\x30\x95\xef\x1a\x84\xda\x1f\x55\xb1\xc9\xe6\x1f\xe4\xa2\xd8\x00\x64\x5e\x7a\x85\xc5\x6f\x5c\x73\x21\xdb\x23\xf4\xfd\xf0\x00\x92\x5f\xd0\x9e\xd0\x6e\xf9\x11\x2f\x17\xf8\x4e\x29\x53\x71\x6f\x6c\x96\x8e\x78\xfa\x92\x90\x78\x6c\x14\xf7\x08\x2c\xb0\x31\x48\x2e\x97\x4d\x96\x8e\xcc\xd9\xab\x38\x86\xed\x4f\x5f\x3f\x7d\x80\x33\x42\x54\x1a\x6b\xcd\x39\x02\x0e\xca\x78\x30\x3b\xf0\x35\x82\xf3\x9d\x92\x7a\x1f\x8e\x52\xa0\x26\xe6\x4e\x3c\x42\x8d\xba\xc2\xf0\x7e\xe3\xb0\x6a\x2d\x3d\x8c\x2d\x86\x32\x02\x3c\xda\xa3\xd4\x46\x99\x7d\x07\x52\x2f\x1c\x08\xa8\xf0\x48\x04\xee\x11\x94\x3c\xe0\xc2\x06\x5c\x8b\x4d\xa9\xd0\x39\x2a\x93\x40\x1c\x93\xae\xd2\x88\x0e\x2a\xc5\x9d\xcb\xd9\x8c\x6b\xac\x39\xd1\xdf\x36\x56\xbc\x33\xad\x67\xb7\xec\xa1\x1d\x0d\x52\xcb\x5c\x65\x65\xe3\x03\x08\x60\xd7\xea\xca\x4b\xa3\xa1\xaa\xb9\xde\xe3\x47\xaf\xdf\x48\x32\xa1\xf1\xfc\xe3\xd7\xa7\x2f\x0f\xd0\x0f\x28\x00\x4a\xa1\x0d\x12\x93\x3d\xfa\x4f\xa3\xda\x8f\xdd\x67\x41\xe0\x87\x44\x6a\x8d\x36\xc0\x21\x07\x96\xed\x8c\xf6\x50\x91\x49\x9b\x47\x7b\xcb\xbb\xa8\x60\x6f\x27\xba\xb7\x2c\x4b\xc3\xeb\x82\x7d\x3b\xd0\x0e\x6a\xd2\xab\x9c\xec\xc8\xa5\x1e\x75\x65\xf5\xbb\xd9\x65\xc3\xf7\x18\x0f\x09\x15\xdf\x5b\x0c\x86\xa8\x2d\xf0\x44\x89\xef\x11\x3e\x6b\xe7\x39\x35\xdc\x85\x14\x6e\x86\x4f\x89\xbe\x9b\x38\x85\x3c\xcd\xa4\x73\x57\x5d\xac\xa4\x1b\x3b\x76\x1f\x32\xf5\x6f\x06\x0d\xea\x8a\xdf\x4d\x6b\x29\xc5\xa9\xfc\xb5\x4a\xb0\x44\x2c\xe3\xa1\xef\x6d\x68\x2b\xbc\x96\x5a\xe0\x9f\x8f\xf0\x7a\x4a\x1a\x3e\xe4\x90\x2c\xda\x87\x58\xee\x97\x97\x94\xe4\xba\xf8\x0d\x50\x2c\xd0\x73\xa9\xdc\x0a\x16\x54\xbe\x2f\xfa\xfe\xd0\x96\x18\x3a\x01\xc9\xd2\x8f\xf7\xcf\x50\xcd\xfa\x44\xe7\xb2\x78\x32\x2d\x49\x0c\xf0\x2c\x2d\x8b\xac\xb4\xcf\x11\x7d\x3f\x51\xad\x59\xd2\x15\xcd\xaa\x01\x77\x05\x5b\x3c\x99\x03\x52\xa6\x2f\x02\xaf\x2b\x72\xa8\x2d\xee\x72\x46\x72\x7e\xe0\xae\x2e\x0d\xb7\xe2\xd7\x9f\xbf\x5c\x2e\x6c\xf9\xbe\xf5\xde\xe8\xb8\xa1\x83\x3c\x21\x03\xcf\x2d\x5d\xdf\x9c\xfd\x51\x2a\xae\x0f\xac\x58\x3e\xcb\x52\xfe\xff\xd4\xd3\xa8\xe6\x4c\xa0\xf3\xd6\x74\x34\x3b\x7d\x3f\x06\x4d\x1a\xee\x4a\x1d\xc1\xff\x2e\xd4\xe8\x4a\xc9\xea\x90\xb3\xeb\x54\x46\xb7\xaa\x44\x8f\x10\x4d\x84\x61\x11\xbd\xf1\xfc\x40\x93\xc0\x61\x87\x67\xa0\xed\x63\xb4\x70\x0f\x90\x24\x49\xf4\x40\x66\x47\xdc\x7d\xab\xcf\xae\x2d\x2a\x77\x0d\x78\x6b\x34\xc2\x8e\x2e\x85\x48\xe6\xd7\x5a\x4c\x6f\xaf\xd7\x27\x73\x0d\xd7\x43\x43\xaa\x61\x4c\x49\x29\xa5\xbb\xb2\x3e\x4e\xef\xcb\x9d\x2f\x74\xc1\xee\x40\xf2\x9f\x66\xa7\x45\xb1\xc5\x73\xf0\x4b\x3b\x86\xa4\x4d\x4b\x60\xbe\xa8\x7d\x7f\x96\xbe\x86\xe4\x89\x22\x0d\x9b\x24\x9e\x0d\xd5\xd3\x75\x5f\x39\x1b\x76\x9a\x93\x7f\x61\xce\xbe\x61\x34\x53\x49\x18\xa3\x61\x93\xfd\x93\x73\xd5\x98\x05\x90\xa5\xe3\x5e\xa3\x61\xa2\xe5\x1d\x7e\xc7\x7f\x62\x7f\x07\x00\x00\xff\xff\x73\x0a\x07\x93\xdc\x06\x00\x00")
+var _homeTmplHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x9c\x56\x5d\x8f\xdb\x36\x10\x7c\xf7\xaf\xd8\x10\x01\x9c\x43\x4e\x12\xd2\xbc\xa5\x94\x80\x5e\x1b\xa0\x01\x72\xd7\x22\xb9\x14\xe8\x53\x41\x8b\x6b\x9b\x30\x4d\x1a\x24\x65\xc7\x15\xf4\xdf\xbb\x14\x25\x7f\xdc\xd9\x57\xb4\x4f\x3e\xda\xa3\xd9\x99\xd9\xe5\xea\xf8\x2b\x69\xeb\xb0\xdf\x20\x2c\xc3\x5a\x57\x13\x3e\x7e\xa0\x90\xd5\x04\x80\x07\x15\x34\x56\x7f\x08\x23\xa4\x6a\xd6\xd0\xb6\xfd\x17\x90\x7f\x45\xb7\x45\xf7\x20\xd6\xd8\x75\xf0\x93\xd6\xb6\x16\xc1\x3a\x5e\x24\x3c\x3d\x49\x48\x5c\x6f\xb4\x08\x08\x2c\xb2\x31\xc8\xbb\x6e\xc2\x8b\xc4\xcc\x5f\x65\x19\x3c\xfc\xf6\xf8\xf1\x03\xec\x10\xa6\x33\xeb\x9c\xdd\x4d\x41\x80\xb6\x01\xec\x1c\xc2\x12\xc1\x87\xbd\x56\x66\x11\x8f\x4a\xa2\x21\xe6\xbd\xbc\x85\x25\x9a\x1a\xe3\xef\x13\x8f\x75\xe3\xe8\xcb\xcc\x61\x2c\x23\x21\xa0\x5b\x2b\x63\xb5\x5d\xec\x41\x99\x03\x07\x02\x6a\x5c\x13\x81\xbf\x05\xad\x56\x78\x60\x03\x61\xe4\x64\xa6\xd1\x7b\x2a\x93\x43\x96\x91\xae\x99\x95\x7b\xa8\xb5\xf0\xbe\x64\x23\x6e\xe3\xec\x96\xfe\x76\x99\x16\x7b\xdb\x04\x76\xc9\x1e\xba\x64\x90\x22\xf3\xb5\x53\x9b\x10\x41\x00\xf3\xc6\xd4\x41\x59\x03\xf5\x52\x98\x05\xde\x05\xf3\x46\x91\x09\x83\xbb\x5f\x1f\xef\x3f\xdf\x40\xdb\xa3\x00\xa8\x0b\x4d\x94\x98\x2f\x30\x7c\x4c\x6a\xef\xf6\x9f\x24\x81\x6f\x72\x65\x0c\xba\x08\x87\x12\x18\x9f\x5b\x13\xa0\x26\x93\xae\x9c\x2e\x9c\xd8\x4f\x2b\xf6\x76\xa0\x7b\xcb\x78\x11\x7f\xae\xd8\x8f\x3d\x6d\xaf\xa6\x38\xca\xe1\x6b\xa1\x4c\xd2\xc5\x97\xef\x46\x97\x1b\xb1\xc0\xac\xef\x50\xf5\xb3\xc3\x68\x88\x62\x81\x7b\xea\xf8\x02\xe1\x93\xf1\x41\x50\xe0\x3e\x76\xe1\x62\xf3\xa9\xa3\xef\x06\x4e\xa9\xb6\x23\xe9\x98\xaa\xcf\xb4\xf2\x29\xb1\xeb\x90\x21\xbf\x11\xd4\xab\xab\xfe\xb4\x8d\xa3\x2e\x0e\xe5\x8f\x55\xa2\x25\x62\x49\x87\xb6\x75\x31\x56\x78\xad\x8c\xc4\xef\xb7\xf0\x7a\xe8\x34\x7c\x28\x21\x3f\x68\xef\xdb\x72\xbd\xbc\xa2\x4e\x9e\x16\xbf\x00\xca\x24\x06\xa1\xb4\x3f\x81\x45\x95\xef\xab\xb6\x5d\x35\x33\x8c\x49\x40\x7e\xc8\xe3\xfd\x19\x6a\xf3\x8c\xac\x16\x5b\xca\xd9\x43\x63\xd4\xf7\xa0\xd6\xc8\x40\x8a\x20\xb2\xf1\x58\xb6\x6d\xde\x77\x82\xe6\xe6\x91\xce\xf9\x37\xfa\xa1\xeb\x4e\x49\x89\x76\x56\x8d\x18\x88\x20\x5e\xcc\x2a\x3e\x73\xc5\x39\xea\x29\xd3\xd7\xe0\x48\xc0\x21\x8f\x94\xe6\xe6\x5c\xee\xb3\x3a\xf7\xb6\xa1\x44\xa3\xbb\xcb\x45\xb8\xa2\x18\x7a\xf7\x5f\xac\x0d\x5d\x57\xf0\x42\x55\x7c\x17\x71\xd4\x9f\x78\x37\xd5\xf6\x2c\xa2\x97\xaa\x5f\x0b\x8b\x3d\x93\x75\x37\x20\xe0\x77\x11\xe8\xe6\x1b\x7f\x2d\x82\x34\x22\xf9\x88\x1f\xe1\x67\x3a\x86\xb0\xa8\x7d\x17\x08\xd0\xc8\xeb\xa2\x4f\xa6\xb1\x3f\x5e\x9a\x1e\x87\x5b\xbb\x42\x79\x3e\x3d\x02\x96\x0e\xe7\x25\xa3\xb2\xbf\x08\xbf\x9c\x59\xe1\xe4\xb7\x2f\x9f\xbb\x8e\x1d\x9e\x6f\x42\xb0\x26\xdb\xd0\x81\x12\x64\x10\x84\xa3\xf5\x50\xb2\xbf\x66\x5a\x98\x15\xab\x0e\x8f\xf1\x42\xfc\x3f\x41\xb4\x0a\x4b\x26\xd1\x07\x67\xf7\xb4\x9b\xda\x36\x5d\x24\xd2\x70\x55\x6a\x02\xbf\x2c\xd4\x9a\x5a\xab\x7a\x55\xb2\xe3\xd6\x9b\x5e\xaa\x32\xbd\x85\xe9\x40\x18\x1b\xf9\x26\x88\x15\x6d\x1a\x01\x73\xdc\x01\x6d\x77\x6b\xa4\xbf\x81\x3c\xcf\xa7\x37\x64\x36\xe1\xae\x5b\x3d\x5b\x0b\xa8\xfd\x71\xd0\x1e\xac\x41\x98\xd3\x14\xcb\x7c\xf2\xb4\xa3\xc7\x79\xe7\x7e\x23\x4c\x1f\x48\xdd\xaf\x41\x52\xca\xaa\x53\xeb\x69\x3b\xfe\x77\xe7\x07\xba\x68\x37\x5d\xc7\x7f\x33\x3b\x2c\xe2\x07\xdc\x45\xbf\xb4\xc3\x49\xda\xb0\x64\xc7\xd9\x6b\xdb\x9d\x0a\x4b\xc8\xef\xa9\xa5\x71\x53\x67\xa3\xa1\xa5\xab\x9e\x3a\xeb\xdf\x19\x5e\xfd\x8d\x25\xfb\x81\x55\x69\xce\xd3\x9b\xe2\x29\xe7\x49\x30\x07\x00\x2f\xd2\x7b\x83\xee\x17\xbd\x1c\xe3\x67\xfa\x27\xe1\x9f\x00\x00\x00\xff\xff\x4f\x04\x96\x5e\x3c\x08\x00\x00")
 
 func homeTmplHtmlBytes() ([]byte, error) {
 	return bindataRead(
diff --git a/services/allocator/allocatord/assets/home.tmpl.html b/services/allocator/allocatord/assets/home.tmpl.html
index ab88699..1ae4eb2 100644
--- a/services/allocator/allocatord/assets/home.tmpl.html
+++ b/services/allocator/allocatord/assets/home.tmpl.html
@@ -24,12 +24,21 @@
       <div class="blessings-item">
         <div class="blessing-details">
           <h3>{{kubeName .Name}}</h3>
+          <p class="blessing-caveats unixtime" data-unixtime={{.CreationTime.Unix}}>
+            <b>Creation Time</b><br/>
+            {{.CreationTime.String}}
+          </p>
           <p>
-            <b>Mount Name</b><br>
-            {{.Name}}
+            <b>Mount Name</b><br/>
+            <i>{{.NameRoot}}/</i><wbr/>{{relativeName .Name}}
+          </p>
+          <p class="blessing-caveats">
+            <b>Blessing Patterns</b><br/>
+            {{range .BlessingPatterns}}
+              {{.}}<br/>
+            {{end}}
           </p>
         </div>
-        <div class="blessing-revoked"></div>
         <div class="blessing-revoked">
           <a href="{{.DashboardURL}}" class="button-passive" target="_blank">Dashboard</a>
         </div>
diff --git a/services/allocator/allocatord/assets_helper.go b/services/allocator/allocatord/assets_helper.go
index 13eb089..12ef337 100644
--- a/services/allocator/allocatord/assets_helper.go
+++ b/services/allocator/allocatord/assets_helper.go
@@ -106,8 +106,9 @@
 		return nil, err
 	}
 	t, err := template.New(name).Funcs(template.FuncMap{
-		"title":    strings.Title,
-		"kubeName": kubeNameFromMountName,
+		"title":        strings.Title,
+		"kubeName":     kubeNameFromMountName,
+		"relativeName": relativeMountName,
 	}).Parse(string(data))
 	if err != nil {
 		return nil, err
diff --git a/services/allocator/allocatord/doc.go b/services/allocator/allocatord/doc.go
index c28d718..bf35adb 100644
--- a/services/allocator/allocatord/doc.go
+++ b/services/allocator/allocatord/doc.go
@@ -58,6 +58,9 @@
  -server-name=
    Name of the servers to allocate. This name is part of the published names in
    the Vanadium namespace and the names of the Deployments in Kubernetes.
+ -server-name-root=
+   Namespace root for allocated servers to use when publishing in the Vanadium
+   namespace.  If not set, the namespace root of the allocator server is used.
  -static-assets-prefix=
    Host serving the web assets.
  -vkube=vkube
diff --git a/services/allocator/allocatord/http.go b/services/allocator/allocatord/http.go
index 3b321e1..c9d3901 100644
--- a/services/allocator/allocatord/http.go
+++ b/services/allocator/allocatord/http.go
@@ -10,8 +10,10 @@
 	"net"
 	"net/http"
 	"net/url"
+	"strings"
 	"time"
 
+	"v.io/v23"
 	"v.io/v23/context"
 	"v.io/v23/security"
 )
@@ -234,7 +236,14 @@
 	if err != nil {
 		return fmt.Errorf("list error: %v", err)
 	}
-	type instanceArg struct{ Name, DestroyURL, DashboardURL string }
+	type instanceArg struct {
+		Name,
+		NameRoot,
+		DestroyURL,
+		DashboardURL string
+		BlessingPatterns []string
+		CreationTime     time.Time
+	}
 	tmplArgs := struct {
 		AssetsPrefix,
 		ServerName,
@@ -250,10 +259,19 @@
 		Message:      rs.r.FormValue(paramMessage),
 	}
 	for _, instance := range instances {
+		var patterns []string
+		for _, b := range security.BlessingNames(v23.GetPrincipal(ctx), ss.args.baseBlessings) {
+			bName := strings.Join([]string{b, instance.name}, security.ChainSeparator)
+			patterns = append(patterns, bName)
+		}
+
 		tmplArgs.Instances = append(tmplArgs.Instances, instanceArg{
-			Name:         instance,
-			DestroyURL:   makeURL(ctx, routeDestroy, params{paramName: instance, paramCSRF: rs.csrfToken}),
-			DashboardURL: makeURL(ctx, routeDashboard, params{paramDashboardName: relativeMountName(instance), paramCSRF: rs.csrfToken}),
+			Name:             instance.mountName,
+			NameRoot:         nameRoot(ctx),
+			CreationTime:     instance.creationTime,
+			BlessingPatterns: patterns,
+			DestroyURL:       makeURL(ctx, routeDestroy, params{paramName: instance.mountName, paramCSRF: rs.csrfToken}),
+			DashboardURL:     makeURL(ctx, routeDashboard, params{paramDashboardName: relativeMountName(instance.mountName), paramCSRF: rs.csrfToken}),
 		})
 	}
 	if err := ss.args.assets.executeTemplate(rs.w, homeTmpl, tmplArgs); err != nil {
diff --git a/services/allocator/allocatord/main.go b/services/allocator/allocatord/main.go
index 4f6e808..661c5c6 100644
--- a/services/allocator/allocatord/main.go
+++ b/services/allocator/allocatord/main.go
@@ -27,6 +27,7 @@
 var (
 	nameFlag                string
 	serverNameFlag          string
+	serverNameRootFlag      string
 	deploymentTemplateFlag  string
 	globalAdminsFlag        string
 	maxInstancesFlag        int
@@ -59,12 +60,14 @@
 
 const (
 	serverNameFlagName     = "server-name"
+	serverNameRootFlagName = "server-name-root"
 	oauthCredsFileFlagName = "oauth-client-creds-file"
 )
 
 func main() {
 	cmdRoot.Flags.StringVar(&nameFlag, "name", "", "Name to publish for this service.")
 	cmdRoot.Flags.StringVar(&serverNameFlag, serverNameFlagName, "", "Name of the servers to allocate. This name is part of the published names in the Vanadium namespace and the names of the Deployments in Kubernetes.")
+	cmdRoot.Flags.StringVar(&serverNameRootFlag, serverNameRootFlagName, "", "Namespace root for allocated servers to use when publishing in the Vanadium namespace.  If not set, the namespace root of the allocator server is used.")
 	cmdRoot.Flags.StringVar(&deploymentTemplateFlag, "deployment-template", "", "The template for the deployment of the servers to allocate.")
 	cmdRoot.Flags.StringVar(&globalAdminsFlag, "global-admins", "", "A comma-separated list of blessing patterns that have access to all the server instances.")
 	cmdRoot.Flags.IntVar(&maxInstancesFlag, "max-instances", 10, "The maximum total number of server instances to create.")
@@ -94,12 +97,21 @@
 		// use <server-name>-<md5> as name, where "-<md5>" is 33 chars.
 		return env.UsageErrorf("--%s value too long. Must be <= 30 characters", serverNameFlagName)
 	}
+	if nameRoot(ctx) == "" {
+		return env.UsageErrorf("--%s not specified, and no default namespace root found", serverNameRootFlagName)
+	}
 
 	var baseBlessings security.Blessings
 	if clusterAgentFlag == "" || blessingSecretFlag == "" {
-		fmt.Fprintln(env.Stderr, "WARNING: Using self-blessed blessings for allocated servers")
-		var err error
-		if baseBlessings, err = v23.GetPrincipal(ctx).BlessSelf("allocator"); err != nil {
+		fmt.Fprintln(env.Stderr, "WARNING: Using disabled blessings for allocated servers")
+		p := v23.GetPrincipal(ctx)
+		defaultB, _ := p.BlessingStore().Default()
+		// This caveat ensures that the blessing we create cannot be used.
+		disabled, err := security.NewCaveat(security.ConstCaveat, false)
+		if err != nil {
+			return err
+		}
+		if baseBlessings, err = p.Bless(p.PublicKey(), defaultB, "allocator", disabled); err != nil {
 			return err
 		}
 	} else {
diff --git a/services/allocator/allocatord/names.go b/services/allocator/allocatord/names.go
index 7e806ba..c1ad7b1 100644
--- a/services/allocator/allocatord/names.go
+++ b/services/allocator/allocatord/names.go
@@ -32,11 +32,18 @@
 	return serverNameFlag + "-" + hex.EncodeToString(b), nil
 }
 
-func mountNameFromKubeName(ctx *context.T, kName string) string {
-	if roots := v23.GetNamespace(ctx).Roots(); len(roots) > 0 {
-		return naming.Join(roots[0], serverMountPrefix, kName)
+func nameRoot(ctx *context.T) string {
+	if serverNameRootFlag != "" {
+		return serverNameRootFlag
 	}
-	return naming.Join(serverMountPrefix, kName)
+	if roots := v23.GetNamespace(ctx).Roots(); len(roots) > 0 {
+		return roots[0]
+	}
+	return ""
+}
+
+func mountNameFromKubeName(ctx *context.T, kName string) string {
+	return naming.Join(nameRoot(ctx), serverMountPrefix, kName)
 }
 
 func kubeNameFromMountName(mName string) string {
diff --git a/services/allocator/allocatord/service.go b/services/allocator/allocatord/service.go
index f649b15..d673456 100644
--- a/services/allocator/allocatord/service.go
+++ b/services/allocator/allocatord/service.go
@@ -70,12 +70,20 @@
 	if email == "" {
 		return nil, verror.New(verror.ErrNoAccess, ctx, "unable to determine caller's email address")
 	}
-	return list(ctx, email)
+	instances, err := list(ctx, email)
+	if err != nil {
+		return nil, err
+	}
+	mNames := make([]string, len(instances))
+	for i, instance := range instances {
+		mNames[i] = instance.mountName
+	}
+	return mNames, nil
 }
 
 func create(ctx *context.T, email string, baseBlessings security.Blessings) (string, error) {
 	// Enforce a limit on the number of instances. These tests are a little
-	// bit racy. It's possible that multiple calls to Create() will run
+	// bit racy. It's possible that multiple calls to create() will run
 	// concurrently and that we'll end up with too many instances.
 	if n, err := serverInstances(email); err != nil {
 		return "", err
@@ -150,16 +158,15 @@
 	return nil
 }
 
-func list(ctx *context.T, email string) ([]string, error) {
-	kNames, err := serverInstances(email)
+func list(ctx *context.T, email string) ([]serverInstance, error) {
+	instances, err := serverInstances(email)
 	if err != nil {
 		return nil, err
 	}
-	mNames := make([]string, len(kNames))
-	for i, n := range kNames {
-		mNames[i] = mountNameFromKubeName(ctx, n)
+	for i, instance := range instances {
+		instances[i].mountName = mountNameFromKubeName(ctx, instance.name)
 	}
-	return mNames, nil
+	return instances, err
 }
 
 func createDeploymentConfig(ctx *context.T, email, deploymentName, mountName string) (string, func(), error) {
@@ -263,7 +270,17 @@
 	return hex.EncodeToString(h[:])
 }
 
-func serverInstances(email string) ([]string, error) {
+type serverInstance struct {
+	name         string
+	mountName    string
+	creationTime time.Time
+}
+
+func serverInstances(email string) ([]serverInstance, error) {
+	// TODO(caprita): Store the mount name and server blessing name(s) as
+	// annotations in the deployment, and retrieve them here.  This should
+	// ensure that the values are accurate, and do not depend on the version
+	// of allocatord that is presenting them.
 	args := []string{"kubectl", "get", "deployments", "-o", "json"}
 	if email != "" {
 		args = append(args, "-l", "ownerHash="+emailHash(email))
@@ -284,20 +301,24 @@
 	var list struct {
 		Items []struct {
 			Metadata struct {
-				Name string `json:"name"`
+				Name         string    `json:"name"`
+				CreationTime time.Time `json:"creationTimestamp"`
 			} `json:"metadata"`
 		} `json:"items"`
 	}
 	if err := json.Unmarshal(out, &list); err != nil {
 		return nil, err
 	}
-	kNames := []string{}
+	instances := []serverInstance{}
 	for _, l := range list.Items {
 		if strings.HasPrefix(l.Metadata.Name, serverNameFlag+"-") {
-			kNames = append(kNames, l.Metadata.Name)
+			instances = append(instances, serverInstance{
+				name:         l.Metadata.Name,
+				creationTime: l.Metadata.CreationTime,
+			})
 		}
 	}
-	return kNames, nil
+	return instances, nil
 }
 
 func isOwnerOfInstance(email, kName string) (bool, error) {
@@ -306,7 +327,7 @@
 		return false, err
 	}
 	for _, i := range instances {
-		if i == kName {
+		if i.name == kName {
 			return true, nil
 		}
 	}