Merge branch '15933-setup-uuid-param' refs #15933
authorPeter Amstutz <peter.amstutz@curii.com>
Wed, 18 Dec 2019 14:36:09 +0000 (09:36 -0500)
committerPeter Amstutz <peter.amstutz@curii.com>
Wed, 18 Dec 2019 14:36:09 +0000 (09:36 -0500)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

25 files changed:
AUTHORS
README.md
apps/workbench/fpm-info.sh
lib/config/config.default.yml
lib/config/export.go
lib/config/generated_config.go
lib/controller/federation/conn.go
lib/controller/federation_test.go
lib/controller/handler.go
lib/controller/handler_test.go
lib/controller/router/request.go
lib/controller/router/response.go
lib/controller/router/router.go
lib/controller/router/router_test.go
lib/controller/rpc/conn.go
lib/controller/server_test.go
sdk/go/arvados/api.go
sdk/go/arvados/collection.go
sdk/go/arvados/config.go
sdk/go/arvados/container.go
sdk/go/arvados/fs_collection.go
sdk/go/arvados/user.go
sdk/python/tests/run_test_server.py
services/keepproxy/keepproxy_test.go
services/login-sync/arvados-login-sync.gemspec

diff --git a/AUTHORS b/AUTHORS
index fad165356273ef81745f4b0bd2929869b6a5aedd..436a504c36ab9f93d89e0742c9f9414032b6b8b6 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -18,4 +18,4 @@ President and Fellows of Harvard College <*@harvard.edu>
 Thomas Mooney <tmooney@genome.wustl.edu>
 Chen Chen <aflyhorse@gmail.com>
 Veritas Genetics, Inc. <*@veritasgenetics.com>
-Curii Corporation <*@curii.com>
\ No newline at end of file
+Curii Corporation, Inc. <*@curii.com>
index 6b520b1af5e2c3fe10f016e3a3def8e1a3f2d702..08c102557c94bc3639df66ee2cf1b71394e4a579 100644 (file)
--- a/README.md
+++ b/README.md
@@ -58,7 +58,7 @@ contributors to Arvados.
 
 ## Development
 
-[![Build Status](https://ci.curoverse.com/buildStatus/icon?job=run-tests)](https://ci.curoverse.com/job/run-tests/)
+[![Build Status](https://ci.arvados.org/buildStatus/icon?job=run-tests)](https://ci.arvados.org/job/run-tests/)
 [![Go Report Card](https://goreportcard.com/badge/github.com/arvados/arvados)](https://goreportcard.com/report/github.com/arvados/arvados)
 
 The Arvados public bug tracker is located at https://dev.arvados.org/projects/arvados/issues
index 22ec1ba14c6dad9a83cc3594aa0353f835331e91..bb7c624cae20f436263ffc0f787a14ffab3c1bb1 100644 (file)
@@ -4,9 +4,9 @@
 
 case "$TARGET" in
     centos*)
-        fpm_depends+=(git)
+        fpm_depends+=(git bison make automake gcc gcc-c++)
         ;;
     debian* | ubuntu*)
-        fpm_depends+=(git g++)
+        fpm_depends+=(git g++ bison zlib1g-dev make)
         ;;
 esac
index 98e6bd3720506232d1764979f46c45ea650a4b38..7779d7ebf2a26b11a0ca4225a6cdfe865abd8a3d 100644 (file)
@@ -512,7 +512,7 @@ Clusters:
       # "https://zzzzz.example.com/login") as an authorized redirect
       # URL.
       #
-      # Requires EnableBetaController14287. ProviderAppID must be
+      # Incompatible with ForceLegacyAPI14. ProviderAppID must be
       # blank.
       GoogleClientID: ""
       GoogleClientSecret: ""
@@ -1109,5 +1109,9 @@ Clusters:
         <p>An administrator must activate your account before you can get
         any further.</p>
 
-    # Use experimental controller code (see https://dev.arvados.org/issues/14287)
-    EnableBetaController14287: false
+    # Bypass new (Arvados 1.5) API implementations, and hand off
+    # requests directly to Rails instead. This can provide a temporary
+    # workaround for clients that are incompatible with the new API
+    # implementation. Note that it also disables some new federation
+    # features and will be removed in a future release.
+    ForceLegacyAPI14: false
index c8bbbe1a5f3c734eb52531834bac05606b60e0e1..e7278c5f32b9a8de1c5d5ec3e47d0d4838813603 100644 (file)
@@ -124,7 +124,7 @@ var whitelist = map[string]bool{
        "Containers.SupportedDockerImageFormats":       true,
        "Containers.SupportedDockerImageFormats.*":     true,
        "Containers.UsePreemptibleInstances":           true,
-       "EnableBetaController14287":                    false,
+       "ForceLegacyAPI14":                             false,
        "Git":                                          false,
        "InstanceTypes":                                true,
        "InstanceTypes.*":                              true,
index ece3a627fd6a5b7ed2fe5179068b6a10ba20439f..3e58d249bf4dee7526ea1bbab74b259b85d2d4ab 100644 (file)
@@ -518,7 +518,7 @@ Clusters:
       # "https://zzzzz.example.com/login") as an authorized redirect
       # URL.
       #
-      # Requires EnableBetaController14287. ProviderAppID must be
+      # Incompatible with ForceLegacyAPI14. ProviderAppID must be
       # blank.
       GoogleClientID: ""
       GoogleClientSecret: ""
@@ -1115,6 +1115,10 @@ Clusters:
         <p>An administrator must activate your account before you can get
         any further.</p>
 
-    # Use experimental controller code (see https://dev.arvados.org/issues/14287)
-    EnableBetaController14287: false
+    # Bypass new (Arvados 1.5) API implementations, and hand off
+    # requests directly to Rails instead. This can provide a temporary
+    # workaround for clients that are incompatible with the new API
+    # implementation. Note that it also disables some new federation
+    # features and will be removed in a future release.
+    ForceLegacyAPI14: false
 `)
index 174ece134ff95cc5eeb78fa8153eaaad917929c0..1b1ffef24cf3a1c6bb2245f3d4c9cb258118e620 100644 (file)
@@ -340,11 +340,13 @@ var userAttrsCachedFromLoginCluster = map[string]bool{
        "prefs":                   true,
        "username":                true,
 
+       "etag":         false,
        "full_name":    false,
        "identity_url": false,
        "is_invited":   false,
        "owner_uuid":   false,
        "uuid":         false,
+       "writable_by":  false,
 }
 
 func (conn *Conn) UserList(ctx context.Context, options arvados.ListOptions) (arvados.UserList, error) {
index 9dc4a3b814c22c0c34940e9efcb2dcf8f497e7b7..d0bff84eaf5eb3387450f6e12de28ca6167eeffd 100644 (file)
@@ -57,9 +57,9 @@ func (s *FederationSuite) SetUpTest(c *check.C) {
        c.Assert(s.remoteMock.Start(), check.IsNil)
 
        cluster := &arvados.Cluster{
-               ClusterID:                 "zhome",
-               PostgreSQL:                integrationTestCluster().PostgreSQL,
-               EnableBetaController14287: enableBetaController14287,
+               ClusterID:        "zhome",
+               PostgreSQL:       integrationTestCluster().PostgreSQL,
+               ForceLegacyAPI14: forceLegacyAPI14,
        }
        cluster.TLS.Insecure = true
        cluster.API.MaxItemsPerResponse = 1000
index 28c616aa631733ef9010598e1499870e90d2e4e0..935a1b6cb683a57a2da99b4d4f7285b1bc1ae7f5 100644 (file)
@@ -80,7 +80,7 @@ func (h *Handler) setup() {
        rtr := router.New(federation.New(h.Cluster))
        mux.Handle("/arvados/v1/config", rtr)
 
-       if h.Cluster.EnableBetaController14287 {
+       if !h.Cluster.ForceLegacyAPI14 {
                mux.Handle("/arvados/v1/collections", rtr)
                mux.Handle("/arvados/v1/collections/", rtr)
                mux.Handle("/arvados/v1/users", rtr)
index 5243002256c1d743b4b2a1b1925ca096ddff1bad..201c5ec02d305cf513b0e734d51f57f98730fef7 100644 (file)
@@ -23,11 +23,11 @@ import (
        check "gopkg.in/check.v1"
 )
 
-var enableBetaController14287 bool
+var forceLegacyAPI14 bool
 
 // Gocheck boilerplate
 func Test(t *testing.T) {
-       for _, enableBetaController14287 = range []bool{false, true} {
+       for _, forceLegacyAPI14 = range []bool{false, true} {
                check.TestingT(t)
        }
 }
@@ -45,10 +45,9 @@ func (s *HandlerSuite) SetUpTest(c *check.C) {
        s.ctx, s.cancel = context.WithCancel(context.Background())
        s.ctx = ctxlog.Context(s.ctx, ctxlog.New(os.Stderr, "json", "debug"))
        s.cluster = &arvados.Cluster{
-               ClusterID:  "zzzzz",
-               PostgreSQL: integrationTestCluster().PostgreSQL,
-
-               EnableBetaController14287: enableBetaController14287,
+               ClusterID:        "zzzzz",
+               PostgreSQL:       integrationTestCluster().PostgreSQL,
+               ForceLegacyAPI14: forceLegacyAPI14,
        }
        s.cluster.TLS.Insecure = true
        arvadostest.SetServiceURL(&s.cluster.Services.RailsAPI, "https://"+os.Getenv("ARVADOS_TEST_API_HOST"))
index cc6379486893742ff1f9464fcc8c62b1b5f8add7..39b4c5100608ebf6a14b250ec26185886aed3ad3 100644 (file)
@@ -163,10 +163,12 @@ var intParams = map[string]bool{
 }
 
 var boolParams = map[string]bool{
-       "distinct":             true,
-       "ensure_unique_name":   true,
-       "include_trash":        true,
-       "include_old_versions": true,
+       "distinct":                true,
+       "ensure_unique_name":      true,
+       "include_trash":           true,
+       "include_old_versions":    true,
+       "redirect_to_new_user":    true,
+       "send_notification_email": true,
 }
 
 func stringToBool(s string) bool {
index 23462bcb0c5feee76a5f7bea368eb29f97a57dba..543e25d0ce44f73c6cd87cc221aaace564f41a2c 100644 (file)
@@ -45,9 +45,11 @@ func applySelectParam(selectParam []string, orig map[string]interface{}) map[str
                        selected[attr] = v
                }
        }
-       // Preserve "kind" even if not requested
-       if v, ok := orig["kind"]; ok {
-               selected["kind"] = v
+       // Some keys are always preserved, even if not requested
+       for _, k := range []string{"etag", "kind", "writable_by"} {
+               if v, ok := orig[k]; ok {
+                       selected[k] = v
+               }
        }
        return selected
 }
index bc70963dab1f4c1bb68f791719b1ff1b1d2a5a4d..c41f103dc464be41be43002b24e11a59a9968c8c 100644 (file)
@@ -298,12 +298,6 @@ func (rtr *router) addRoutes() {
                },
        } {
                rtr.addRoute(route.endpoint, route.defaultOpts, route.exec)
-               if route.endpoint.Method == "PATCH" {
-                       // Accept PUT as a synonym for PATCH.
-                       endpointPUT := route.endpoint
-                       endpointPUT.Method = "PUT"
-                       rtr.addRoute(endpointPUT, route.defaultOpts, route.exec)
-               }
        }
        rtr.mux.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
                httpserver.Errors(w, []string{"API endpoint not found"}, http.StatusNotFound)
@@ -313,8 +307,17 @@ func (rtr *router) addRoutes() {
        })
 }
 
+var altMethod = map[string]string{
+       "PATCH": "PUT",  // Accept PUT as a synonym for PATCH
+       "GET":   "HEAD", // Accept HEAD at any GET route
+}
+
 func (rtr *router) addRoute(endpoint arvados.APIEndpoint, defaultOpts func() interface{}, exec routableFunc) {
-       rtr.mux.Methods(endpoint.Method).Path("/" + endpoint.Path).HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+       methods := []string{endpoint.Method}
+       if alt, ok := altMethod[endpoint.Method]; ok {
+               methods = append(methods, alt)
+       }
+       rtr.mux.Methods(methods...).Path("/" + endpoint.Path).HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
                logger := ctxlog.FromContext(req.Context())
                params, err := rtr.loadRequestParams(req, endpoint.AttrsKey)
                if err != nil {
index 7a7e3dd6fcfb90857480521c4b9931ac92c6a401..4cabe70f162a6f36360da58f7c820e1712e0728f 100644 (file)
@@ -286,6 +286,12 @@ func (s *RouterIntegrationSuite) TestContainerLock(c *check.C) {
        c.Check(jresp["uuid"], check.IsNil)
 }
 
+func (s *RouterIntegrationSuite) TestWritableBy(c *check.C) {
+       _, rr, jresp := doRequest(c, s.rtr, arvadostest.ActiveTokenV2, "GET", `/arvados/v1/users/`+arvadostest.ActiveUserUUID, nil, nil)
+       c.Check(rr.Code, check.Equals, http.StatusOK)
+       c.Check(jresp["writable_by"], check.DeepEquals, []interface{}{"zzzzz-tpzed-000000000000000", "zzzzz-tpzed-xurymjxw79nv3jz", "zzzzz-j7d0g-48foin4vonvc2at"})
+}
+
 func (s *RouterIntegrationSuite) TestFullTimestampsInResponse(c *check.C) {
        uuid := arvadostest.CollectionReplicationDesired2Confirmed2UUID
        token := arvadostest.ActiveTokenV2
@@ -321,6 +327,8 @@ func (s *RouterIntegrationSuite) TestSelectParam(c *check.C) {
                c.Check(rr.Code, check.Equals, http.StatusOK)
 
                c.Check(resp["kind"], check.Equals, "arvados#container")
+               c.Check(resp["etag"], check.FitsTypeOf, "")
+               c.Check(resp["etag"], check.Not(check.Equals), "")
                c.Check(resp["uuid"], check.HasLen, 27)
                c.Check(resp["command"], check.HasLen, 2)
                c.Check(resp["mounts"], check.IsNil)
@@ -329,6 +337,11 @@ func (s *RouterIntegrationSuite) TestSelectParam(c *check.C) {
        }
 }
 
+func (s *RouterIntegrationSuite) TestHEAD(c *check.C) {
+       _, rr, _ := doRequest(c, s.rtr, arvadostest.ActiveTokenV2, "HEAD", "/arvados/v1/containers/"+arvadostest.QueuedContainerUUID, nil, nil)
+       c.Check(rr.Code, check.Equals, http.StatusOK)
+}
+
 func (s *RouterIntegrationSuite) TestRouteNotFound(c *check.C) {
        token := arvadostest.ActiveTokenV2
        req := (&testReq{
index 06e70efb77e5ac34005317d2b35ec9f9127ccfe3..bf6166f44ffd649691d317eed302e31bee35b5cf 100644 (file)
@@ -327,25 +327,25 @@ func (conn *Conn) UserUpdateUUID(ctx context.Context, options arvados.UpdateUUID
        return resp, err
 }
 func (conn *Conn) UserMerge(ctx context.Context, options arvados.UserMergeOptions) (arvados.User, error) {
-       ep := arvados.EndpointUserUpdateUUID
+       ep := arvados.EndpointUserMerge
        var resp arvados.User
        err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
        return resp, err
 }
 func (conn *Conn) UserActivate(ctx context.Context, options arvados.UserActivateOptions) (arvados.User, error) {
-       ep := arvados.EndpointUserUpdateUUID
+       ep := arvados.EndpointUserActivate
        var resp arvados.User
        err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
        return resp, err
 }
 func (conn *Conn) UserSetup(ctx context.Context, options arvados.UserSetupOptions) (map[string]interface{}, error) {
-       ep := arvados.EndpointUserUpdateUUID
+       ep := arvados.EndpointUserSetup
        var resp map[string]interface{}
        err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
        return resp, err
 }
 func (conn *Conn) UserUnsetup(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-       ep := arvados.EndpointUserUpdateUUID
+       ep := arvados.EndpointUserUnsetup
        var resp arvados.User
        err := conn.requestAndDecode(ctx, &resp, ep, nil, options)
        return resp, err
index 37f148eb6eb8a08e69d5a9b4c75163d236b02b12..838de35563e60fb1a994e8cee8c28dd2b9321fbe 100644 (file)
@@ -35,10 +35,9 @@ func newServerFromIntegrationTestEnv(c *check.C) *httpserver.Server {
        log := ctxlog.TestLogger(c)
 
        handler := &Handler{Cluster: &arvados.Cluster{
-               ClusterID:  "zzzzz",
-               PostgreSQL: integrationTestCluster().PostgreSQL,
-
-               EnableBetaController14287: enableBetaController14287,
+               ClusterID:        "zzzzz",
+               PostgreSQL:       integrationTestCluster().PostgreSQL,
+               ForceLegacyAPI14: forceLegacyAPI14,
        }}
        handler.Cluster.TLS.Insecure = true
        arvadostest.SetServiceURL(&handler.Cluster.Services.RailsAPI, "https://"+os.Getenv("ARVADOS_TEST_API_HOST"))
index 7d6ddb317621fde9800c385cc024218d16eb4630..6e115a15f6f6232c5e7add504e04aff09309e759 100644 (file)
@@ -49,7 +49,7 @@ var (
        EndpointUserGetSystem                 = APIEndpoint{"GET", "arvados/v1/users/system", ""}
        EndpointUserList                      = APIEndpoint{"GET", "arvados/v1/users", ""}
        EndpointUserMerge                     = APIEndpoint{"POST", "arvados/v1/users/merge", ""}
-       EndpointUserSetup                     = APIEndpoint{"POST", "arvados/v1/users/setup", ""}
+       EndpointUserSetup                     = APIEndpoint{"POST", "arvados/v1/users/setup", "user"}
        EndpointUserSystem                    = APIEndpoint{"GET", "arvados/v1/users/system", ""}
        EndpointUserUnsetup                   = APIEndpoint{"POST", "arvados/v1/users/{uuid}/unsetup", ""}
        EndpointUserUpdate                    = APIEndpoint{"PATCH", "arvados/v1/users/{uuid}", "user"}
@@ -105,19 +105,21 @@ type UserActivateOptions struct {
 }
 
 type UserSetupOptions struct {
-       UUID                  string                 `json:"uuid"`
-       Email                 string                 `json:"email"`
-       OpenIDPrefix          string                 `json:"openid_prefix"`
-       RepoName              string                 `json:"repo_name"`
-       VMUUID                string                 `json:"vm_uuid"`
-       SendNotificationEmail bool                   `json:"send_notification_email"`
+       UUID                  string                 `json:"uuid,omitempty"`
+       Email                 string                 `json:"email,omitempty"`
+       OpenIDPrefix          string                 `json:"openid_prefix,omitempty"`
+       RepoName              string                 `json:"repo_name,omitempty"`
+       VMUUID                string                 `json:"vm_uuid,omitempty"`
+       SendNotificationEmail bool                   `json:"send_notification_email,omitempty"`
        Attrs                 map[string]interface{} `json:"attrs"`
 }
 
 type UserMergeOptions struct {
-       NewUserUUID  string `json:"new_user_uuid,omitempty"`
-       OldUserUUID  string `json:"old_user_uuid,omitempty"`
-       NewUserToken string `json:"new_user_token,omitempty"`
+       NewUserUUID       string `json:"new_user_uuid,omitempty"`
+       OldUserUUID       string `json:"old_user_uuid,omitempty"`
+       NewOwnerUUID      string `json:"new_owner_uuid,omitempty"`
+       NewUserToken      string `json:"new_user_token,omitempty"`
+       RedirectToNewUser bool   `json:"redirect_to_new_user"`
 }
 
 type UserBatchUpdateOptions struct {
index 4c9305f3f7a7e0fb7b4ac2e38898a7eb0441ac07..5ac35e2292e97809cdb68e6d06ab937193cdba4f 100644 (file)
@@ -36,6 +36,7 @@ type Collection struct {
        DeleteAt                  *time.Time             `json:"delete_at"`
        IsTrashed                 bool                   `json:"is_trashed"`
        Properties                map[string]interface{} `json:"properties"`
+       WritableBy                []string               `json:"writable_by,omitempty"`
 }
 
 func (c Collection) resourceName() string {
index 5c1314532bda7237fcf0fddeb047ed62b5e3ca71..433e361e11032a78aaaac44e43e9f30a46daf6f4 100644 (file)
@@ -215,7 +215,7 @@ type Cluster struct {
                InactivePageHTML       string
        }
 
-       EnableBetaController14287 bool
+       ForceLegacyAPI14 bool
 }
 
 type Volume struct {
index 1d3b0962f7da1ff93d386f067195b977ef02de10..653312d86cbe52cc31ab36e025ef4c6e0d53af41 100644 (file)
@@ -9,6 +9,7 @@ import "time"
 // Container is an arvados#container resource.
 type Container struct {
        UUID                 string                 `json:"uuid"`
+       Etag                 string                 `json:"etag"`
        CreatedAt            time.Time              `json:"created_at"`
        ModifiedByClientUUID string                 `json:"modified_by_client_uuid"`
        ModifiedByUserUUID   string                 `json:"modified_by_user_uuid"`
index 3d0928b84ea77ef3817ac9c3d2cfe3679bd970e0..d0e97f2ad184b44e7800a577247704e8af717581 100644 (file)
@@ -698,21 +698,9 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize
        go func() {
                defer close(done)
                defer close(errs)
-               locked := map[*filenode]bool{}
                locator, _, err := dn.fs.PutB(block)
                dn.fs.throttle().Release()
                {
-                       if !sync {
-                               dn.Lock()
-                               defer dn.Unlock()
-                               for _, name := range dn.sortedNames() {
-                                       if fn, ok := dn.inodes[name].(*filenode); ok {
-                                               fn.Lock()
-                                               defer fn.Unlock()
-                                               locked[fn] = true
-                                       }
-                               }
-                       }
                        defer func() {
                                for _, seg := range segs {
                                        if seg.flushing == done {
@@ -727,6 +715,7 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize
                }
                for idx, ref := range refs {
                        if !sync {
+                               ref.fn.Lock()
                                // In async mode, fn's lock was
                                // released while we were waiting for
                                // PutB(); lots of things might have
@@ -735,17 +724,15 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize
                                        // file segments have
                                        // rearranged or changed in
                                        // some way
+                                       ref.fn.Unlock()
                                        continue
                                } else if seg, ok := ref.fn.segments[ref.idx].(*memSegment); !ok || seg != segs[idx] {
                                        // segment has been replaced
+                                       ref.fn.Unlock()
                                        continue
                                } else if seg.flushing != done {
                                        // seg.buf has been replaced
-                                       continue
-                               } else if !locked[ref.fn] {
-                                       // file was renamed, moved, or
-                                       // deleted since we called
-                                       // PutB
+                                       ref.fn.Unlock()
                                        continue
                                }
                        }
@@ -763,6 +750,9 @@ func (dn *dirnode) commitBlock(ctx context.Context, refs []fnSegmentRef, bufsize
                        // lock, writing different segments from the
                        // same file.
                        atomic.AddInt64(&ref.fn.memsize, -int64(len(data)))
+                       if !sync {
+                               ref.fn.Unlock()
+                       }
                }
        }()
        if sync {
index 30bc094d07c95e91b9a930c0bb923e4d4d6d908e..68960144a8a3dae092c604bfa4a256efcc8a669b 100644 (file)
@@ -9,6 +9,7 @@ import "time"
 // User is an arvados#user record
 type User struct {
        UUID                 string                 `json:"uuid"`
+       Etag                 string                 `json:"etag"`
        IsActive             bool                   `json:"is_active"`
        IsAdmin              bool                   `json:"is_admin"`
        Username             string                 `json:"username"`
@@ -24,6 +25,7 @@ type User struct {
        ModifiedByUserUUID   string                 `json:"modified_by_user_uuid"`
        ModifiedByClientUUID string                 `json:"modified_by_client_uuid"`
        Prefs                map[string]interface{} `json:"prefs"`
+       WritableBy           []string               `json:"writable_by,omitempty"`
 }
 
 // UserList is an arvados#userList resource.
index dd74df2367812d48272e6be28827e7e0b806c398..2e093b396dfa22991332368db61a8e9f5904a5d5 100644 (file)
@@ -717,7 +717,6 @@ def setup_config():
     config = {
         "Clusters": {
             "zzzzz": {
-                "EnableBetaController14287": ('14287' in os.environ.get('ARVADOS_EXPERIMENTAL', '')),
                 "ManagementToken": "e687950a23c3a9bceec28c6223a06c79",
                 "SystemRootToken": auth_token('system_user'),
                 "API": {
index 1c86a461aaf14da4c5801f617d20e364d3c11e2d..aa32356806abdb32e73ea0de9534e76567e5e83e 100644 (file)
@@ -142,6 +142,7 @@ func (s *ServerRequiredSuite) TestResponseViaHeader(c *C) {
        resp, err := (&http.Client{}).Do(req)
        c.Assert(err, Equals, nil)
        c.Check(resp.Header.Get("Via"), Equals, "HTTP/1.1 keepproxy")
+       c.Assert(resp.StatusCode, Equals, http.StatusOK)
        locator, err := ioutil.ReadAll(resp.Body)
        c.Assert(err, Equals, nil)
        resp.Body.Close()
index f580d529d8a658b2e1a2a57f706aa3bff5fa89e2..f6485d695fcfe27b61f1b866c8c14085156480f9 100644 (file)
@@ -26,6 +26,9 @@ Gem::Specification.new do |s|
   s.add_runtime_dependency 'arvados', '~> 1.3.0', '>= 1.3.0'
   # arvados-google-api-client 0.8.7.2 is incompatible with faraday 0.16.2
   s.add_dependency('faraday', '< 0.16')
+  # arvados-google-api-client (and thus arvados) gems
+  # depend on signet, but signet 0.12 is incompatible with ruby 2.3.
+  s.add_dependency('signet', '< 0.12')
   s.homepage    =
     'https://arvados.org'
 end