17170: Add "arvados-client shell" subcommand and backend support.
[arvados.git] / lib / controller / federation / conn.go
index 61cac9bbabcd1d5128417fe0ab91041981afd207..a32382ce254afa9a8018792fa9fbee932f73476b 100644 (file)
@@ -79,6 +79,14 @@ func saltedTokenProvider(local backend, remoteID string) rpc.TokenProvider {
                                } else if err != nil {
                                        return nil, err
                                }
+                               if strings.HasPrefix(aca.UUID, remoteID) {
+                                       // We have it cached here, but
+                                       // the token belongs to the
+                                       // remote target itself, so
+                                       // pass it through unmodified.
+                                       tokens = append(tokens, token)
+                                       continue
+                               }
                                salted, err := auth.SaltToken(aca.TokenV2(), remoteID)
                                if err != nil {
                                        return nil, err
@@ -328,6 +336,10 @@ func (conn *Conn) ContainerUnlock(ctx context.Context, options arvados.GetOption
        return conn.chooseBackend(options.UUID).ContainerUnlock(ctx, options)
 }
 
+func (conn *Conn) ContainerSSH(ctx context.Context, options arvados.ContainerSSHOptions) (arvados.ContainerSSHConnection, error) {
+       return conn.chooseBackend(options.UUID).ContainerSSH(ctx, options)
+}
+
 func (conn *Conn) SpecimenList(ctx context.Context, options arvados.ListOptions) (arvados.SpecimenList, error) {
        return conn.generated_SpecimenList(ctx, options)
 }
@@ -454,7 +466,18 @@ func (conn *Conn) UserUpdate(ctx context.Context, options arvados.UpdateOptions)
        if options.BypassFederation {
                return conn.local.UserUpdate(ctx, options)
        }
-       return conn.chooseBackend(options.UUID).UserUpdate(ctx, options)
+       resp, err := conn.chooseBackend(options.UUID).UserUpdate(ctx, options)
+       if err != nil {
+               return resp, err
+       }
+       if !strings.HasPrefix(options.UUID, conn.cluster.ClusterID) {
+               // Copy the updated user record to the local cluster
+               err = conn.batchUpdateUsers(ctx, arvados.ListOptions{}, []arvados.User{resp})
+               if err != nil {
+                       return arvados.User{}, err
+               }
+       }
+       return resp, err
 }
 
 func (conn *Conn) UserUpdateUUID(ctx context.Context, options arvados.UpdateUUIDOptions) (arvados.User, error) {
@@ -500,11 +523,24 @@ func (conn *Conn) UserUnsetup(ctx context.Context, options arvados.GetOptions) (
 }
 
 func (conn *Conn) UserGet(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-       return conn.chooseBackend(options.UUID).UserGet(ctx, options)
+       resp, err := conn.chooseBackend(options.UUID).UserGet(ctx, options)
+       if err != nil {
+               return resp, err
+       }
+       if options.UUID != resp.UUID {
+               return arvados.User{}, httpErrorf(http.StatusBadGateway, "Had requested %v but response was for %v", options.UUID, resp.UUID)
+       }
+       if options.UUID[:5] != conn.cluster.ClusterID {
+               err = conn.batchUpdateUsers(ctx, arvados.ListOptions{Select: options.Select}, []arvados.User{resp})
+               if err != nil {
+                       return arvados.User{}, err
+               }
+       }
+       return resp, nil
 }
 
 func (conn *Conn) UserGetCurrent(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {
-       return conn.chooseBackend(options.UUID).UserGetCurrent(ctx, options)
+       return conn.local.UserGetCurrent(ctx, options)
 }
 
 func (conn *Conn) UserGetSystem(ctx context.Context, options arvados.GetOptions) (arvados.User, error) {