Blame internal/osbuild1/result.go

Packit Service 15f37d
package osbuild1
Packit Service 15f37d
Packit Service 15f37d
import (
Packit Service 15f37d
	"bytes"
Packit Service 15f37d
	"encoding/json"
Packit Service 15f37d
	"fmt"
Packit Service 15f37d
	"io"
Packit Service 15f37d
Packit Service 15f37d
	"github.com/osbuild/osbuild-composer/internal/osbuild2"
Packit Service 15f37d
)
Packit Service 15f37d
Packit Service 15f37d
type rawAssemblerResult struct {
Packit Service 15f37d
	Name    string          `json:"name"`
Packit Service 15f37d
	Options json.RawMessage `json:"options"`
Packit Service 15f37d
	Success bool            `json:"success"`
Packit Service 15f37d
	Output  string          `json:"output"`
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
type StageResult struct {
Packit Service 15f37d
	Name     string          `json:"name"`
Packit Service 15f37d
	Options  json.RawMessage `json:"options"`
Packit Service 15f37d
	Success  bool            `json:"success"`
Packit Service 15f37d
	Output   string          `json:"output"`
Packit Service 15f37d
	Metadata StageMetadata   `json:"metadata"`
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
// StageMetadata specify the metadata of a given stage-type.
Packit Service 15f37d
type StageMetadata interface {
Packit Service 15f37d
	isStageMetadata()
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
type rawStageResult struct {
Packit Service 15f37d
	Name     string          `json:"name"`
Packit Service 15f37d
	Options  json.RawMessage `json:"options"`
Packit Service 15f37d
	Success  bool            `json:"success"`
Packit Service 15f37d
	Output   string          `json:"output"`
Packit Service 15f37d
	Metadata json.RawMessage `json:"metadata"`
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
type buildResult struct {
Packit Service 15f37d
	Stages  []StageResult `json:"stages"`
Packit Service 15f37d
	TreeID  string        `json:"tree_id"`
Packit Service 15f37d
	Success bool          `json:"success"`
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
type Result struct {
Packit Service 15f37d
	TreeID    string              `json:"tree_id"`
Packit Service 15f37d
	OutputID  string              `json:"output_id"`
Packit Service 15f37d
	Build     *buildResult        `json:"build"`
Packit Service 15f37d
	Stages    []StageResult       `json:"stages"`
Packit Service 15f37d
	Assembler *rawAssemblerResult `json:"assembler"`
Packit Service 15f37d
	Success   bool                `json:"success"`
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (result *StageResult) UnmarshalJSON(data []byte) error {
Packit Service 15f37d
	var rawStageResult rawStageResult
Packit Service 15f37d
	err := json.Unmarshal(data, &rawStageResult)
Packit Service 15f37d
	if err != nil {
Packit Service 15f37d
		return err
Packit Service 15f37d
	}
Packit Service 15f37d
	var metadata StageMetadata
Packit Service 15f37d
	switch rawStageResult.Name {
Packit Service 15f37d
	case "org.osbuild.rpm":
Packit Service 15f37d
		metadata = new(RPMStageMetadata)
Packit Service 15f37d
		err = json.Unmarshal(rawStageResult.Metadata, metadata)
Packit Service 15f37d
		if err != nil {
Packit Service 15f37d
			return err
Packit Service 15f37d
		}
Packit Service 15f37d
	default:
Packit Service 15f37d
		metadata = nil
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	result.Name = rawStageResult.Name
Packit Service 15f37d
	result.Options = rawStageResult.Options
Packit Service 15f37d
	result.Success = rawStageResult.Success
Packit Service 15f37d
	result.Output = rawStageResult.Output
Packit Service 15f37d
	result.Metadata = metadata
Packit Service 15f37d
Packit Service 15f37d
	return nil
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (cr *Result) Write(writer io.Writer) error {
Packit Service 15f37d
	if cr.Build == nil && len(cr.Stages) == 0 && cr.Assembler == nil {
Packit Service 15f37d
		fmt.Fprintf(writer, "The compose result is empty.\n")
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if cr.Build != nil {
Packit Service 15f37d
		fmt.Fprintf(writer, "Build pipeline:\n")
Packit Service 15f37d
Packit Service 15f37d
		for _, stage := range cr.Build.Stages {
Packit Service 15f37d
			fmt.Fprintf(writer, "Stage %s\n", stage.Name)
Packit Service 15f37d
			enc := json.NewEncoder(writer)
Packit Service 15f37d
			enc.SetIndent("", "  ")
Packit Service 15f37d
			err := enc.Encode(stage.Options)
Packit Service 15f37d
			if err != nil {
Packit Service 15f37d
				return err
Packit Service 15f37d
			}
Packit Service 15f37d
			fmt.Fprintf(writer, "\nOutput:\n%s\n", stage.Output)
Packit Service 15f37d
		}
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if len(cr.Stages) > 0 {
Packit Service 15f37d
		fmt.Fprintf(writer, "Stages:\n")
Packit Service 15f37d
		for _, stage := range cr.Stages {
Packit Service 15f37d
			fmt.Fprintf(writer, "Stage: %s\n", stage.Name)
Packit Service 15f37d
			enc := json.NewEncoder(writer)
Packit Service 15f37d
			enc.SetIndent("", "  ")
Packit Service 15f37d
			err := enc.Encode(stage.Options)
Packit Service 15f37d
			if err != nil {
Packit Service 15f37d
				return err
Packit Service 15f37d
			}
Packit Service 15f37d
			fmt.Fprintf(writer, "\nOutput:\n%s\n", stage.Output)
Packit Service 15f37d
		}
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	if cr.Assembler != nil {
Packit Service 15f37d
		fmt.Fprintf(writer, "Assembler %s:\n", cr.Assembler.Name)
Packit Service 15f37d
		enc := json.NewEncoder(writer)
Packit Service 15f37d
		enc.SetIndent("", "  ")
Packit Service 15f37d
		err := enc.Encode(cr.Assembler.Options)
Packit Service 15f37d
		if err != nil {
Packit Service 15f37d
			return err
Packit Service 15f37d
		}
Packit Service 15f37d
		fmt.Fprintf(writer, "\nOutput:\n%s\n", cr.Assembler.Output)
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	return nil
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (cr *Result) UnmarshalJSON(data []byte) error {
Packit Service 15f37d
	// NOTE(akoutsou) 1to2t: result format depends on the osbuild version; this
Packit Service 15f37d
	// unmarshaller tries to read both old and new versions
Packit Service 15f37d
	type resultAlias Result
Packit Service 15f37d
	crv1 := new(resultAlias)
Packit Service 15f37d
Packit Service 15f37d
	dec := json.NewDecoder(bytes.NewReader(data))
Packit Service 15f37d
	dec.DisallowUnknownFields()
Packit Service 15f37d
	if err := dec.Decode(&crv1); err == nil {
Packit Service 15f37d
		*cr = Result(*crv1)
Packit Service 15f37d
		return nil
Packit Service 15f37d
	}
Packit Service 15f37d
Packit Service 15f37d
	// try osbuild2 result object
Packit Service 15f37d
	crv2 := new(osbuild2.Result)
Packit Service 15f37d
Packit Service 15f37d
	// NOTE: Using plain (non-strict) Unmarshal here.  The format of the new
Packit Service 15f37d
	// osbuild output schema is not yet fixed and is likely to change, so
Packit Service 15f37d
	// disallowing unknown fields will likely cause failures in the near future.
Packit Service 15f37d
	if err := json.Unmarshal(data, &crv2); err != nil {
Packit Service 15f37d
		return err
Packit Service 15f37d
	}
Packit Service 15f37d
	cr.fromV2(crv2)
Packit Service 15f37d
	return nil
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
// Convert new OSBuild v2 format result into a v1 by copying the most useful
Packit Service 15f37d
// values:
Packit Service 15f37d
// - Compose success status
Packit Service 15f37d
// - Output of Stages (Log) as flattened list of v1 StageResults
Packit Service 15f37d
func (cr *Result) fromV2(crv2 *osbuild2.Result) {
Packit Service 15f37d
	cr.Success = crv2.Success
Packit Service 15f37d
	// Empty build and assembler results for new types of jobs
Packit Service 15f37d
	cr.Build = new(buildResult)
Packit Service 15f37d
	cr.Assembler = new(rawAssemblerResult)
Packit Service 15f37d
Packit Service 15f37d
	// convert all stages logs from all pipelines into v1 StageResult objects
Packit Service 15f37d
	for pname, stages := range crv2.Log {
Packit Service 15f37d
		for idx, stage := range stages {
Packit Service 15f37d
			stageResult := StageResult{
Packit Service 15f37d
				// Create uniquely identifiable name for the stage:
Packit Service 15f37d
				// <pipeline name>:<stage index>-<stage type>
Packit Service 15f37d
				Name:    fmt.Sprintf("%s:%d-%s", pname, idx, stage.Type),
Packit Service 15f37d
				Success: stage.Success,
Packit Service 15f37d
				Output:  stage.Output,
Packit Service 15f37d
			}
Packit Service 15f37d
			cr.Stages = append(cr.Stages, stageResult)
Packit Service 15f37d
		}
Packit Service 15f37d
	}
Packit Service 15f37d
}