worker/osbuild: print raw osbuild output if it cannot be parsed

osbuild output should be always JSON-parsable. However, if a user has a weird
installation of osbuild, it can return malformed JSON. In this case, it's
very hard to debug what happened because the worker doesn't provide any
useful information. This commit adds the non-parsable osbuild output to the
error so there's at least some clue in the logs what happened.

Let me reiterate: In 99% these cases, this shouldn't be needed. It will give
us some hints in these 1% cases though.

You may want to ask if using json.Decoder isn't better because it doesn't
buffer the input. However, it does buffer. Firstly, json.Decoder.Decode()
buffers the whole JSON value (it contains kinda cool state machine to do it)
and in the second run, it parses the buffer. Therefore, the only thing that
this commit actually does is that it moves the buffer out of json.Decoder.

Signed-off-by: Ondřej Budai <ondrej@budai.cz>
This commit is contained in:
Ondřej Budai 2020-11-20 09:52:41 +01:00 committed by Tom Gundersen
parent 8e86d9dcae
commit 2070800244

View file

@ -1,6 +1,7 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
@ -29,10 +30,8 @@ func RunOSBuild(manifest distro.Manifest, store, outputDirectory string, errorWr
return nil, fmt.Errorf("error setting up stdin for osbuild: %v", err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("error setting up stdout for osbuild: %v", err)
}
var stdoutBuffer bytes.Buffer
cmd.Stdout = &stdoutBuffer
err = cmd.Start()
if err != nil {
@ -49,13 +48,15 @@ func RunOSBuild(manifest distro.Manifest, store, outputDirectory string, errorWr
return nil, fmt.Errorf("error closing osbuild's stdin: %v", err)
}
err = cmd.Wait()
// try to decode the output even though the job could have failed
var result osbuild.Result
err = json.NewDecoder(stdout).Decode(&result)
if err != nil {
return nil, fmt.Errorf("error decoding osbuild output: %#v", err)
decodeErr := json.Unmarshal(stdoutBuffer.Bytes(), &result)
if decodeErr != nil {
return nil, fmt.Errorf("error decoding osbuild output: %v\nthe raw output:\n%s", decodeErr, stdoutBuffer.String())
}
err = cmd.Wait()
if err != nil {
// ignore ExitError if output could be decoded correctly
if _, isExitError := err.(*exec.ExitError); !isExitError {