17944: Fixes tests. Improves health funcs handling.
[arvados.git] / lib / controller / federation / user_test.go
index 993be9b0b836707ecc2361c4e2f6bad3e7372d37..064f8ce5d09e8e931f0769a23970ee676ba4e6ca 100644 (file)
@@ -5,15 +5,19 @@
 package federation
 
 import (
+       "context"
        "encoding/json"
        "errors"
+       "math"
        "net/url"
        "os"
        "strings"
 
-       "git.curoverse.com/arvados.git/lib/controller/rpc"
-       "git.curoverse.com/arvados.git/sdk/go/arvados"
-       "git.curoverse.com/arvados.git/sdk/go/arvadostest"
+       "git.arvados.org/arvados.git/lib/controller/rpc"
+       "git.arvados.org/arvados.git/sdk/go/arvados"
+       "git.arvados.org/arvados.git/sdk/go/arvadostest"
+       "git.arvados.org/arvados.git/sdk/go/auth"
+       "git.arvados.org/arvados.git/sdk/go/ctxlog"
        check "gopkg.in/check.v1"
 )
 
@@ -26,12 +30,13 @@ type UserSuite struct {
 func (s *UserSuite) TestLoginClusterUserList(c *check.C) {
        s.cluster.ClusterID = "local"
        s.cluster.Login.LoginCluster = "zzzzz"
-       s.fed = New(s.cluster)
+       s.fed = New(s.cluster, nil)
        s.addDirectRemote(c, "zzzzz", rpc.NewConn("zzzzz", &url.URL{Scheme: "https", Host: os.Getenv("ARVADOS_API_HOST")}, true, rpc.PassthroughTokenProvider))
 
        for _, updateFail := range []bool{false, true} {
                for _, opts := range []arvados.ListOptions{
                        {Offset: 0, Limit: -1, Select: nil},
+                       {Offset: 0, Limit: math.MaxInt64, Select: nil},
                        {Offset: 1, Limit: 1, Select: nil},
                        {Offset: 0, Limit: 2, Select: []string{"uuid"}},
                        {Offset: 0, Limit: 2, Select: []string{"uuid", "email"}},
@@ -45,6 +50,9 @@ func (s *UserSuite) TestLoginClusterUserList(c *check.C) {
                                s.fed.local = rpc.NewConn(s.cluster.ClusterID, spy.URL, true, rpc.PassthroughTokenProvider)
                        }
                        userlist, err := s.fed.UserList(s.ctx, opts)
+                       if err != nil {
+                               c.Logf("... UserList failed %q", err)
+                       }
                        if updateFail && err == nil {
                                // All local updates fail, so the only
                                // cases expected to succeed are the
@@ -53,7 +61,7 @@ func (s *UserSuite) TestLoginClusterUserList(c *check.C) {
                                c.Check(stub.Calls(nil), check.HasLen, 0)
                        } else if updateFail {
                                c.Logf("... err %#v", err)
-                               calls := stub.Calls(stub.UserUpdate)
+                               calls := stub.Calls(stub.UserBatchUpdate)
                                if c.Check(calls, check.HasLen, 1) {
                                        c.Logf("... stub.UserUpdate called with options: %#v", calls[0].Options)
                                        shouldUpdate := map[string]bool{
@@ -84,8 +92,11 @@ func (s *UserSuite) TestLoginClusterUserList(c *check.C) {
                                                        }
                                                }
                                        }
+                                       var uuid string
+                                       for uuid = range calls[0].Options.(arvados.UserBatchUpdateOptions).Updates {
+                                       }
                                        for k, shouldFind := range shouldUpdate {
-                                               _, found := calls[0].Options.(arvados.UpdateOptions).Attrs[k]
+                                               _, found := calls[0].Options.(arvados.UserBatchUpdateOptions).Updates[uuid][k]
                                                c.Check(found, check.Equals, shouldFind, check.Commentf("offending attr: %s", k))
                                        }
                                }
@@ -93,19 +104,103 @@ func (s *UserSuite) TestLoginClusterUserList(c *check.C) {
                                updates := 0
                                for _, d := range spy.RequestDumps {
                                        d := string(d)
-                                       if strings.Contains(d, "PATCH /arvados/v1/users/zzzzz-tpzed-") {
+                                       if strings.Contains(d, "PATCH /arvados/v1/users/batch") {
                                                c.Check(d, check.Matches, `(?ms).*Authorization: Bearer `+arvadostest.SystemRootToken+`.*`)
                                                updates++
                                        }
                                }
                                c.Check(err, check.IsNil)
-                               c.Check(updates, check.Equals, len(userlist.Items))
+                               c.Check(updates, check.Equals, 1)
                                c.Logf("... response items %#v", userlist.Items)
                        }
                }
        }
 }
 
+func (s *UserSuite) TestLoginClusterUserGet(c *check.C) {
+       s.cluster.ClusterID = "local"
+       s.cluster.Login.LoginCluster = "zzzzz"
+       s.fed = New(s.cluster, nil)
+       s.addDirectRemote(c, "zzzzz", rpc.NewConn("zzzzz", &url.URL{Scheme: "https", Host: os.Getenv("ARVADOS_API_HOST")}, true, rpc.PassthroughTokenProvider))
+
+       opts := arvados.GetOptions{UUID: "zzzzz-tpzed-xurymjxw79nv3jz", Select: []string{"uuid", "email"}}
+
+       stub := &arvadostest.APIStub{Error: errors.New("local cluster failure")}
+       s.fed.local = stub
+       s.fed.UserGet(s.ctx, opts)
+
+       calls := stub.Calls(stub.UserBatchUpdate)
+       if c.Check(calls, check.HasLen, 1) {
+               c.Logf("... stub.UserUpdate called with options: %#v", calls[0].Options)
+               shouldUpdate := map[string]bool{
+                       "uuid":       false,
+                       "email":      true,
+                       "first_name": true,
+                       "last_name":  true,
+                       "is_admin":   true,
+                       "is_active":  true,
+                       "prefs":      true,
+                       // can't safely update locally
+                       "owner_uuid":   false,
+                       "identity_url": false,
+                       // virtual attrs
+                       "full_name":  false,
+                       "is_invited": false,
+               }
+               if opts.Select != nil {
+                       // Only the selected
+                       // fields (minus uuid)
+                       // should be updated.
+                       for k := range shouldUpdate {
+                               shouldUpdate[k] = false
+                       }
+                       for _, k := range opts.Select {
+                               if k != "uuid" {
+                                       shouldUpdate[k] = true
+                               }
+                       }
+               }
+               var uuid string
+               for uuid = range calls[0].Options.(arvados.UserBatchUpdateOptions).Updates {
+               }
+               for k, shouldFind := range shouldUpdate {
+                       _, found := calls[0].Options.(arvados.UserBatchUpdateOptions).Updates[uuid][k]
+                       c.Check(found, check.Equals, shouldFind, check.Commentf("offending attr: %s", k))
+               }
+       }
+
+}
+
+func (s *UserSuite) TestLoginClusterUserListBypassFederation(c *check.C) {
+       s.cluster.ClusterID = "local"
+       s.cluster.Login.LoginCluster = "zzzzz"
+       s.fed = New(s.cluster, nil)
+       s.addDirectRemote(c, "zzzzz", rpc.NewConn("zzzzz", &url.URL{Scheme: "https", Host: os.Getenv("ARVADOS_API_HOST")},
+               true, rpc.PassthroughTokenProvider))
+
+       spy := arvadostest.NewProxy(c, s.cluster.Services.RailsAPI)
+       s.fed.local = rpc.NewConn(s.cluster.ClusterID, spy.URL, true, rpc.PassthroughTokenProvider)
+
+       _, err := s.fed.UserList(s.ctx, arvados.ListOptions{Offset: 0, Limit: math.MaxInt64, Select: nil, BypassFederation: true})
+       // this will fail because it is not using a root token
+       c.Check(err.(*arvados.TransactionError).StatusCode, check.Equals, 403)
+
+       // Now use SystemRootToken
+       ctx := context.Background()
+       ctx = ctxlog.Context(ctx, ctxlog.TestLogger(c))
+       ctx = auth.NewContext(ctx, &auth.Credentials{Tokens: []string{arvadostest.SystemRootToken}})
+
+       // Assert that it did not try to batch update users.
+       _, err = s.fed.UserList(ctx, arvados.ListOptions{Offset: 0, Limit: math.MaxInt64, Select: nil, BypassFederation: true})
+       for _, d := range spy.RequestDumps {
+               d := string(d)
+               if strings.Contains(d, "PATCH /arvados/v1/users/batch") {
+                       c.Fail()
+               }
+       }
+       c.Check(err, check.IsNil)
+}
+
 // userAttrsCachedFromLoginCluster must have an entry for every field
 // in the User struct.
 func (s *UserSuite) TestUserAttrsUpdateWhitelist(c *check.C) {