osbuild1/result: read v2 output and convert to v1

Log output from osbuild has a very different format when using the
new schema.  The osbuild1.Result object now supports unmarshalling the
new format and adapting it to the old format.

The most important field to set is the Success field to signal whether
the build succeeded.

Secondarily, it also copies over the output from each stage in order to
provide build job log output through the weldr API.
Since the new format contains multiple pipelines with multiple stages
each, the stages are flattened to fit the old format.  A unique name for
each stage is created by prepending the name of the pipeline to its
index in the pipeline and its type.
This commit is contained in:
Achilleas Koutsou 2021-02-20 19:16:40 +01:00 committed by Tom Gundersen
parent 2cce81093f
commit 007d52f171

View file

@ -1,9 +1,12 @@
package osbuild1
import (
"bytes"
"encoding/json"
"fmt"
"io"
"github.com/osbuild/osbuild-composer/internal/osbuild2"
)
type rawAssemblerResult struct {
@ -123,3 +126,54 @@ func (cr *Result) Write(writer io.Writer) error {
return nil
}
func (cr *Result) UnmarshalJSON(data []byte) error {
// NOTE(akoutsou) 1to2t: result format depends on the osbuild version; this
// unmarshaller tries to read both old and new versions
type resultAlias Result
crv1 := new(resultAlias)
dec := json.NewDecoder(bytes.NewReader(data))
dec.DisallowUnknownFields()
if err := dec.Decode(&crv1); err == nil {
*cr = Result(*crv1)
return nil
}
// try osbuild2 result object
crv2 := new(osbuild2.Result)
// NOTE: Using plain (non-strict) Unmarshal here. The format of the new
// osbuild output schema is not yet fixed and is likely to change, so
// disallowing unknown fields will likely cause failures in the near future.
if err := json.Unmarshal(data, &crv2); err != nil {
return err
}
cr.fromV2(crv2)
return nil
}
// Convert new OSBuild v2 format result into a v1 by copying the most useful
// values:
// - Compose success status
// - Output of Stages (Log) as flattened list of v1 StageResults
func (cr *Result) fromV2(crv2 *osbuild2.Result) {
cr.Success = crv2.Success
// Empty build and assembler results for new types of jobs
cr.Build = new(buildResult)
cr.Assembler = new(rawAssemblerResult)
// convert all stages logs from all pipelines into v1 StageResult objects
for pname, stages := range crv2.Log {
for idx, stage := range stages {
stageResult := StageResult{
// Create uniquely identifiable name for the stage:
// <pipeline name>:<stage index>-<stage type>
Name: fmt.Sprintf("%s:%d-%s", pname, idx, stage.Type),
Success: stage.Success,
Output: stage.Output,
}
cr.Stages = append(cr.Stages, stageResult)
}
}
}