@@ -21,6 +21,7 @@ import (
2121 "crypto"
2222 "crypto/x509"
2323 "encoding/pem"
24+ "errors"
2425 "log/slog"
2526
2627 "github.com/gravitational/trace"
@@ -57,7 +58,7 @@ func Join(ctx context.Context, params JoinParams) (*JoinResult, error) {
5758 }
5859 slog .InfoContext (ctx , "Trying to join with the new join service" )
5960 result , err := joinNew (ctx , params )
60- if trace .IsNotImplemented (err ) {
61+ if trace .IsNotImplemented (err ) || errors . As ( err , new ( * connectionError )) {
6162 // Fall back to joining via legacy service.
6263 slog .InfoContext (ctx , "Falling back to joining via the legacy join service" , "error" , err )
6364 // Non-bots must generate their own host UUID when joining via legacy service.
@@ -129,7 +130,7 @@ func joinViaProxy(ctx context.Context, params JoinParams, proxyAddr string) (*Jo
129130 },
130131 )
131132 if err != nil {
132- return nil , trace .Wrap (err )
133+ return nil , & connectionError { trace .Wrap (err , "building proxy client" )}
133134 }
134135 defer conn .Close ()
135136 return joinWithClient (ctx , params , joinv1 .NewClientFromConn (conn ))
@@ -138,7 +139,7 @@ func joinViaProxy(ctx context.Context, params JoinParams, proxyAddr string) (*Jo
138139func joinViaAuth (ctx context.Context , params JoinParams ) (* JoinResult , error ) {
139140 authClient , err := authjoin .NewAuthClient (ctx , params )
140141 if err != nil {
141- return nil , trace .Wrap (err , "building auth client" )
142+ return nil , & connectionError { trace .Wrap (err , "building auth client" )}
142143 }
143144 defer authClient .Close ()
144145 return joinViaAuthClient (ctx , params , authClient )
@@ -168,7 +169,10 @@ func joinWithClient(ctx context.Context, params JoinParams, client *joinv1.Clien
168169 defer cancel ()
169170 stream , err := client .Join (ctx )
170171 if err != nil {
171- return nil , trace .Wrap (err )
172+ // Connection errors are usually delayed until the first request is
173+ // attempted, wrap with a connectionError here to allow a fallback to
174+ // the legacy join method.
175+ return nil , & connectionError {trace .Wrap (err , "initiating join stream" )}
172176 }
173177 defer stream .CloseSend ()
174178
@@ -363,3 +367,15 @@ func generateKeys(ctx context.Context, suite types.SignatureAlgorithmSuite) (cry
363367 PublicSSHKey : sshPub .Marshal (),
364368 }, nil
365369}
370+
371+ type connectionError struct {
372+ wrapped error
373+ }
374+
375+ func (e * connectionError ) Error () string {
376+ return e .wrapped .Error ()
377+ }
378+
379+ func (e * connectionError ) Unwrap () error {
380+ return e .wrapped
381+ }
0 commit comments