vscodeSSH is used by the Coder VS Code extension to establish a connection to a workspace. This command needs to remain stable for compatibility with various VS Code versions, so it's kept separate from our standard SSH command.
()
| 30 | // various VS Code versions, so it's kept separate from our |
| 31 | // standard SSH command. |
| 32 | func (r *RootCmd) vscodeSSH() *serpent.Command { |
| 33 | var ( |
| 34 | sessionTokenFile string |
| 35 | urlFile string |
| 36 | logDir string |
| 37 | networkInfoDir string |
| 38 | networkInfoInterval time.Duration |
| 39 | waitEnum string |
| 40 | ) |
| 41 | cmd := &serpent.Command{ |
| 42 | // A SSH config entry is added by the VS Code extension that |
| 43 | // passes %h to ProxyCommand. The prefix of `coder-vscode--` |
| 44 | // is a magical string represented in our VS Code extension. |
| 45 | // It's not important here, only the delimiter `--` is. |
| 46 | Use: "vscodessh <coder-vscode--<owner>--<workspace>--<agent?>>", |
| 47 | Hidden: true, |
| 48 | Middleware: serpent.RequireNArgs(1), |
| 49 | Handler: func(inv *serpent.Invocation) error { |
| 50 | if networkInfoDir == "" { |
| 51 | return xerrors.New("network-info-dir must be specified") |
| 52 | } |
| 53 | if sessionTokenFile == "" { |
| 54 | return xerrors.New("session-token-file must be specified") |
| 55 | } |
| 56 | if urlFile == "" { |
| 57 | return xerrors.New("url-file must be specified") |
| 58 | } |
| 59 | |
| 60 | fs, ok := inv.Context().Value("fs").(afero.Fs) |
| 61 | if !ok { |
| 62 | fs = afero.NewOsFs() |
| 63 | } |
| 64 | |
| 65 | sessionToken, err := afero.ReadFile(fs, sessionTokenFile) |
| 66 | if err != nil { |
| 67 | return xerrors.Errorf("read session token: %w", err) |
| 68 | } |
| 69 | rawURL, err := afero.ReadFile(fs, urlFile) |
| 70 | if err != nil { |
| 71 | return xerrors.Errorf("read url: %w", err) |
| 72 | } |
| 73 | serverURL, err := url.Parse(string(rawURL)) |
| 74 | if err != nil { |
| 75 | return xerrors.Errorf("parse url: %w", err) |
| 76 | } |
| 77 | |
| 78 | ctx, cancel := context.WithCancel(inv.Context()) |
| 79 | defer cancel() |
| 80 | |
| 81 | // Configure HTTP client with transport wrappers |
| 82 | httpClient, err := r.createHTTPClient(ctx, serverURL, inv) |
| 83 | if err != nil { |
| 84 | return xerrors.Errorf("create HTTP client: %w", err) |
| 85 | } |
| 86 | client := codersdk.New(serverURL, |
| 87 | codersdk.WithSessionToken(string(sessionToken)), |
| 88 | codersdk.WithHTTPClient(httpClient), |
| 89 | ) |
no test coverage detected