136
139
return s.run(flockmode, command, nil, 0)
142
// terminate closes the stdin, and appends any output to the input error.
143
func (s *SSHStorage) terminate(err error) error {
146
for s.scanner.Scan() {
147
output += s.scanner.Text()
150
err = fmt.Errorf("%v (output: %q)", err, output)
139
155
func (s *SSHStorage) run(flockmode flockmode, command string, input io.Reader, inputlen int64) (string, error) {
140
156
const rcPrefix = "JUJU-RC: "
141
157
command = fmt.Sprintf(
155
171
if input != nil {
156
172
wrapper, err := newLineWrapWriter(stdin, base64LineLength)
158
return "", fmt.Errorf("failed to create split writer: %v", err)
160
encoder := base64.NewEncoder(base64.StdEncoding, wrapper)
161
if _, err := io.CopyN(encoder, input, inputlen); err != nil {
162
return "", fmt.Errorf("failed to write input: %v", err)
164
if err := encoder.Close(); err != nil {
165
return "", fmt.Errorf("failed to flush encoder: %v", err)
167
if _, err := stdin.WriteString("\n@EOF\n"); err != nil {
168
return "", fmt.Errorf("failed to terminate input: %v", err)
174
err = fmt.Errorf("failed to create split writer: %v", err)
176
encoder := base64.NewEncoder(base64.StdEncoding, wrapper)
177
if _, err = io.CopyN(encoder, input, inputlen); err != nil {
178
err = fmt.Errorf("failed to write input: %v", err)
179
} else if err = encoder.Close(); err != nil {
180
err = fmt.Errorf("failed to flush encoder: %v", err)
181
} else if _, err = stdin.WriteString("\n@EOF\n"); err != nil {
182
err = fmt.Errorf("failed to terminate input: %v", err)
186
return "", s.terminate(err)
171
189
if err := stdin.Flush(); err != nil {
172
return "", fmt.Errorf("failed to flush input: %v", err)
190
err = fmt.Errorf("failed to flush input: %v", err)
191
return "", s.terminate(err)
174
193
var output []string
175
194
for s.scanner.Scan() {
189
208
output = append(output, line)
192
return "", s.scanner.Err()
212
err := fmt.Errorf("failed to locate %q", rcPrefix)
214
err = fmt.Errorf("%v (output: %q)", err, strings.Join(output, "\n"))
216
if scannerErr := s.scanner.Err(); scannerErr != nil {
217
err = fmt.Errorf("%v (scanner error: %v)", err, scannerErr)
195
222
// path returns a remote absolute path for a storage object name.