(ctx context.Context, client *ssh.Client, clientOs string, clientArch string)
| 98 | var installTemplate = template.Must(template.New("wsh-install-template").Parse(installTemplateRawDefault)) |
| 99 | |
| 100 | func CpWshToRemote(ctx context.Context, client *ssh.Client, clientOs string, clientArch string) error { |
| 101 | deadline, ok := ctx.Deadline() |
| 102 | if ok { |
| 103 | blocklogger.Debugf(ctx, "[conndebug] CpWshToRemote, timeout: %v\n", time.Until(deadline)) |
| 104 | } |
| 105 | wshLocalPath, err := shellutil.GetLocalWshBinaryPath(wavebase.WaveVersion, clientOs, clientArch) |
| 106 | if err != nil { |
| 107 | return err |
| 108 | } |
| 109 | input, err := os.Open(wshLocalPath) |
| 110 | if err != nil { |
| 111 | return fmt.Errorf("cannot open local file %s: %w", wshLocalPath, err) |
| 112 | } |
| 113 | defer input.Close() |
| 114 | installWords := map[string]string{ |
| 115 | "installDir": filepath.ToSlash(filepath.Dir(wavebase.RemoteFullWshBinPath)), |
| 116 | "tempPath": wavebase.RemoteFullWshBinPath + ".temp", |
| 117 | "installPath": wavebase.RemoteFullWshBinPath, |
| 118 | } |
| 119 | var installCmd bytes.Buffer |
| 120 | if err := installTemplate.Execute(&installCmd, installWords); err != nil { |
| 121 | return fmt.Errorf("failed to prepare install command: %w", err) |
| 122 | } |
| 123 | blocklogger.Infof(ctx, "[conndebug] copying %q to remote server %q\n", wshLocalPath, wavebase.RemoteFullWshBinPath) |
| 124 | genCmd, err := genconn.MakeSSHCmdClient(client, genconn.CommandSpec{ |
| 125 | Cmd: installCmd.String(), |
| 126 | }) |
| 127 | if err != nil { |
| 128 | return fmt.Errorf("failed to create remote command: %w", err) |
| 129 | } |
| 130 | stdin, err := genCmd.StdinPipe() |
| 131 | if err != nil { |
| 132 | return fmt.Errorf("failed to get stdin pipe: %w", err) |
| 133 | } |
| 134 | defer stdin.Close() |
| 135 | stderrBuf, err := genconn.MakeStderrSyncBuffer(genCmd) |
| 136 | if err != nil { |
| 137 | return fmt.Errorf("failed to get stderr pipe: %w", err) |
| 138 | } |
| 139 | if err := genCmd.Start(); err != nil { |
| 140 | return fmt.Errorf("failed to start remote command: %w", err) |
| 141 | } |
| 142 | copyDone := make(chan error, 1) |
| 143 | go func() { |
| 144 | defer close(copyDone) |
| 145 | defer stdin.Close() |
| 146 | if _, err := io.Copy(stdin, input); err != nil && err != io.EOF { |
| 147 | copyDone <- fmt.Errorf("failed to copy data: %w", err) |
| 148 | } else { |
| 149 | copyDone <- nil |
| 150 | } |
| 151 | }() |
| 152 | procErr := genconn.ProcessContextWait(ctx, genCmd) |
| 153 | if procErr != nil { |
| 154 | return fmt.Errorf("remote command failed: %w (stderr: %s)", procErr, stderrBuf.String()) |
| 155 | } |
| 156 | copyErr := <-copyDone |
| 157 | if copyErr != nil { |
no test coverage detected