[ARVADOS] created: 1.3.0-3085-g51d7a5b2a

Git user git at public.arvados.org
Thu Sep 3 22:08:57 UTC 2020


        at  51d7a5b2a23074a130aa6dd74cbaf5f335920769 (commit)


commit 51d7a5b2a23074a130aa6dd74cbaf5f335920769
Author: Peter Amstutz <peter.amstutz at curii.com>
Date:   Thu Sep 3 18:08:29 2020 -0400

    16778: Setup federated users with VM and repo with LoginCluster set
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>

diff --git a/lib/controller/federation/conn.go b/lib/controller/federation/conn.go
index 418b6811b..b2d158b9a 100644
--- a/lib/controller/federation/conn.go
+++ b/lib/controller/federation/conn.go
@@ -111,6 +111,14 @@ func (conn *Conn) chooseBackend(id string) backend {
 	}
 }
 
+func (conn *Conn) localOrLoginCluster() backend {
+	if conn.cluster.Login.LoginCluster != "" {
+		return conn.chooseBackend(conn.cluster.Login.LoginCluster)
+	} else {
+		return conn.local
+	}
+}
+
 // Call fn with the local backend; then, if fn returned 404, call fn
 // on the available remote backends (possibly concurrently) until one
 // succeeds.
@@ -462,15 +470,48 @@ func (conn *Conn) UserMerge(ctx context.Context, options arvados.UserMergeOption
 }
 
 func (conn *Conn) UserActivate(ctx context.Context, options arvados.UserActivateOptions) (arvados.User, error) {
-	return conn.chooseBackend(options.UUID).UserActivate(ctx, options)
+	return conn.localOrLoginCluster().UserActivate(ctx, options)
 }
 
 func (conn *Conn) UserSetup(ctx context.Context, options arvados.UserSetupOptions) (map[string]interface{}, error) {
-	return conn.chooseBackend(options.UUID).UserSetup(ctx, options)
+	var setupVM string
+	var setupRepo string
+	if conn.cluster.Login.LoginCluster != "" {
+		if options.VMUUID != "" && options.VMUUID[0:5] != options.UUID[0:5] {
+			// When LoginCluster is in effect, and we're
+			// setting up a remote user, and we want to
+			// give that user access to a local VM, then
+			// we need to set up the user on the remote
+			// LoginCluster first, followed by calling
+			// setup on the local instance to give access
+			// to the VM.
+			setupVM = options.VMUUID
+			options.VMUUID = ""
+		}
+		if options.RepoName != "" {
+			// Similarly, if we want to create a git repo,
+			// it should be created on the local cluster,
+			// not the remote one.
+			setupRepo = options.RepoName
+			options.RepoName = ""
+		}
+	}
+
+	ret, err := conn.localOrLoginCluster().UserSetup(ctx, options)
+	if err != nil {
+		return ret, err
+	}
+
+	if setupVM != "" || setupRepo != "" {
+		options.VMUUID = setupVM
+		options.RepoName = setupRepo
+		ret, err = conn.local.UserSetup(ctx, options)
+	}
+	return ret, err
 }
 
 func (conn *Conn) UserUnsetup(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-	return conn.chooseBackend(options.UUID).UserUnsetup(ctx, options)
+	return conn.localOrLoginCluster().UserUnsetup(ctx, options)
 }
 
 func (conn *Conn) UserGet(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
diff --git a/lib/controller/integration_test.go b/lib/controller/integration_test.go
index 03c885092..90d1c3f17 100644
--- a/lib/controller/integration_test.go
+++ b/lib/controller/integration_test.go
@@ -169,7 +169,7 @@ func (s *IntegrationSuite) clientsWithToken(clusterID string, token string) (con
 // initialize clients with the API token, set up the user and
 // optionally activate the user.  Return client structs for
 // communicating with the cluster on behalf of the 'example' user.
-func (s *IntegrationSuite) userClients(rootctx context.Context, c *check.C, conn *rpc.Conn, clusterID string, activate bool) (context.Context, *arvados.Client, *keepclient.KeepClient) {
+func (s *IntegrationSuite) userClients(rootctx context.Context, c *check.C, conn *rpc.Conn, clusterID string, activate bool) (context.Context, *arvados.Client, *keepclient.KeepClient, arvados.User) {
 	login, err := conn.UserSessionCreate(rootctx, rpc.UserSessionCreateOptions{
 		ReturnTo: ",https://example.com",
 		AuthInfo: rpc.UserSessionAuthInfo{
@@ -199,7 +199,7 @@ func (s *IntegrationSuite) userClients(rootctx context.Context, c *check.C, conn
 			c.Fatalf("failed to activate user -- %#v", user)
 		}
 	}
-	return ctx, ac, kc
+	return ctx, ac, kc, user
 }
 
 // Return Context, arvados.Client and keepclient structs initialized
@@ -218,7 +218,7 @@ func (s *IntegrationSuite) TestGetCollectionByPDH(c *check.C) {
 	conn1 := s.conn("z1111")
 	rootctx1, _, _ := s.rootClients("z1111")
 	conn3 := s.conn("z3333")
-	userctx1, ac1, kc1 := s.userClients(rootctx1, c, conn1, "z1111", true)
+	userctx1, ac1, kc1, _ := s.userClients(rootctx1, c, conn1, "z1111", true)
 
 	// Create the collection to find its PDH (but don't save it
 	// anywhere yet)
@@ -322,7 +322,7 @@ func (s *IntegrationSuite) TestGetCollectionAsAnonymous(c *check.C) {
 func (s *IntegrationSuite) TestCreateContainerRequestWithFedToken(c *check.C) {
 	conn1 := s.conn("z1111")
 	rootctx1, _, _ := s.rootClients("z1111")
-	_, ac1, _ := s.userClients(rootctx1, c, conn1, "z1111", true)
+	_, ac1, _, _ := s.userClients(rootctx1, c, conn1, "z1111", true)
 
 	// Use ac2 to get the discovery doc with a blank token, so the
 	// SDK doesn't magically pass the z1111 token to z2222 before
@@ -393,7 +393,7 @@ func (s *IntegrationSuite) TestListUsers(c *check.C) {
 	rootctx1, _, _ := s.rootClients("z1111")
 	conn1 := s.conn("z1111")
 	conn3 := s.conn("z3333")
-	userctx1, _, _ := s.userClients(rootctx1, c, conn1, "z1111", true)
+	userctx1, _, _, _ := s.userClients(rootctx1, c, conn1, "z1111", true)
 
 	// Make sure LoginCluster is properly configured
 	for cls := range s.testClusters {
@@ -457,3 +457,67 @@ func (s *IntegrationSuite) TestListUsers(c *check.C) {
 	c.Assert(err, check.IsNil)
 	c.Check(user1.IsActive, check.Equals, false)
 }
+
+func (s *IntegrationSuite) TestSetupUserWithVM(c *check.C) {
+	conn1 := s.conn("z1111")
+	conn3 := s.conn("z3333")
+	rootctx1, rootac1, _ := s.rootClients("z1111")
+
+	// Create user on LoginCluster z1111
+	_, _, _, user := s.userClients(rootctx1, c, conn1, "z1111", false)
+
+	// Make a new root token (because rootClients() uses SystemRootToken)
+	var outAuth arvados.APIClientAuthorization
+	err := rootac1.RequestAndDecode(&outAuth, "POST", "/arvados/v1/api_client_authorizations", nil, nil)
+	c.Check(err, check.IsNil)
+
+	// Make a v2 root token to communicate with z3333
+	rootctx3, rootac3, _ := s.clientsWithToken("z3333", fmt.Sprintf("v2/%v/%v", outAuth.UUID, outAuth.APIToken))
+
+	// Create VM on z3333
+	var outVM arvados.VirtualMachine
+	err = rootac3.RequestAndDecode(&outVM, "POST", "/arvados/v1/virtual_machines", nil,
+		map[string]interface{}{"virtual_machine": map[string]interface{}{
+			"hostname": "example",
+		},
+		})
+	c.Check(outVM.UUID[0:5], check.Equals, "z3333")
+	c.Check(err, check.IsNil)
+
+	// Make sure z3333 user list is up to date
+	_, err = conn3.UserList(rootctx3, arvados.ListOptions{Limit: 1000})
+	c.Check(err, check.IsNil)
+
+	// Try to set up user on z3333 with the VM
+	_, err = conn3.UserSetup(rootctx3, arvados.UserSetupOptions{UUID: user.UUID, VMUUID: outVM.UUID})
+	c.Check(err, check.IsNil)
+
+	var outLinks arvados.LinkList
+	err = rootac3.RequestAndDecode(&outLinks, "GET", "/arvados/v1/links", nil,
+		arvados.ListOptions{
+			Limit: 1000,
+			Filters: []arvados.Filter{
+				{
+					Attr:     "tail_uuid",
+					Operator: "=",
+					Operand:  user.UUID,
+				},
+				{
+					Attr:     "head_uuid",
+					Operator: "=",
+					Operand:  outVM.UUID,
+				},
+				{
+					Attr:     "name",
+					Operator: "=",
+					Operand:  "can_login",
+				},
+				{
+					Attr:     "link_class",
+					Operator: "=",
+					Operand:  "permission",
+				}}})
+	c.Check(err, check.IsNil)
+
+	c.Check(len(outLinks.Items), check.Equals, 1)
+}

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list