From 007d52f1715ec46aa1c425b50dbd719146990fed Mon Sep 17 00:00:00 2001 From: Achilleas Koutsou Date: Sat, 20 Feb 2021 19:16:40 +0100 Subject: [PATCH] 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. --- internal/osbuild1/result.go | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/internal/osbuild1/result.go b/internal/osbuild1/result.go index b7d51303f..e8e8eda53 100644 --- a/internal/osbuild1/result.go +++ b/internal/osbuild1/result.go @@ -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: + // :- + Name: fmt.Sprintf("%s:%d-%s", pname, idx, stage.Type), + Success: stage.Success, + Output: stage.Output, + } + cr.Stages = append(cr.Stages, stageResult) + } + } +}