X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/8eda8735d7a36f3752f1d426cad1fb0002b30cca..64e387b2f4f0fe6c4c7bf16232706c7cf194caf0:/lib/controller/federation/conn.go diff --git a/lib/controller/federation/conn.go b/lib/controller/federation/conn.go index 1b1ffef24c..42083cb83d 100644 --- a/lib/controller/federation/conn.go +++ b/lib/controller/federation/conn.go @@ -38,7 +38,11 @@ func New(cluster *arvados.Cluster) *Conn { if !remote.Proxy { continue } - remotes[id] = rpc.NewConn(id, &url.URL{Scheme: remote.Scheme, Host: remote.Host}, remote.Insecure, saltedTokenProvider(local, id)) + conn := rpc.NewConn(id, &url.URL{Scheme: remote.Scheme, Host: remote.Host}, remote.Insecure, saltedTokenProvider(local, id)) + // Older versions of controller rely on the Via header + // to detect loops. + conn.SendHeader = http.Header{"Via": {"HTTP/1.1 arvados-controller"}} + remotes[id] = conn } return &Conn{ @@ -116,8 +120,13 @@ func (conn *Conn) chooseBackend(id string) backend { // or "" for the local backend. // // A non-nil error means all backends failed. -func (conn *Conn) tryLocalThenRemotes(ctx context.Context, fn func(context.Context, string, backend) error) error { - if err := fn(ctx, "", conn.local); err == nil || errStatus(err) != http.StatusNotFound { +func (conn *Conn) tryLocalThenRemotes(ctx context.Context, forwardedFor string, fn func(context.Context, string, backend) error) error { + if err := fn(ctx, "", conn.local); err == nil || errStatus(err) != http.StatusNotFound || forwardedFor != "" { + // Note: forwardedFor != "" means this request came + // from a remote cluster, so we don't take a second + // hop. This avoids cycles, redundant calls to a + // mutually reachable remote, and use of double-salted + // tokens. return err } @@ -224,8 +233,10 @@ func (conn *Conn) CollectionGet(ctx context.Context, options arvados.GetOptions) } else { // UUID is a PDH first := make(chan arvados.Collection, 1) - err := conn.tryLocalThenRemotes(ctx, func(ctx context.Context, remoteID string, be backend) error { - c, err := be.CollectionGet(ctx, options) + err := conn.tryLocalThenRemotes(ctx, options.ForwardedFor, func(ctx context.Context, remoteID string, be backend) error { + remoteOpts := options + remoteOpts.ForwardedFor = conn.cluster.ClusterID + "-" + options.ForwardedFor + c, err := be.CollectionGet(ctx, remoteOpts) if err != nil { return err }