debian-forge-composer/internal/osbuild/v1result.go
2022-07-14 16:54:00 +02:00

148 lines
3.8 KiB
Go

package osbuild
// Functions and types for handling old (v1) results.
import (
"encoding/json"
)
type v1StageResult struct {
Name string `json:"name"`
Options json.RawMessage `json:"options"`
Success bool `json:"success"`
Output string `json:"output"`
Metadata json.RawMessage `json:"metadata"`
}
type v1BuildResult struct {
Stages []v1StageResult `json:"stages"`
TreeID string `json:"tree_id"`
Success bool `json:"success"`
}
type v1Result struct {
TreeID string `json:"tree_id"`
OutputID string `json:"output_id"`
Build *v1BuildResult `json:"build"`
Stages []v1StageResult `json:"stages"`
Assembler *v1StageResult `json:"assembler"`
Success bool `json:"success"`
}
func (res *Result) fromV1(resv1 v1Result) error {
res.Success = resv1.Success
res.Type = "result"
log := make(map[string]PipelineResult)
metadata := make(map[string]PipelineMetadata)
// make build pipeline from build result
if resv1.Build != nil {
buildResult, buildMetadata, err := convertStageResults(resv1.Build.Stages)
if err != nil {
return err
}
log["build"] = buildResult
if len(buildMetadata) > 0 {
metadata["build"] = buildMetadata
}
}
// make assembler pipeline from assembler result
if resv1.Assembler != nil {
assemblerResult, assemblerMetadata, err := convertStageResult(resv1.Assembler)
if err != nil {
return err
}
log["assembler"] = []StageResult{*assemblerResult}
if assemblerMetadata != nil {
metadata["assembler"] = map[string]StageMetadata{
resv1.Assembler.Name: assemblerMetadata,
}
}
}
// make os pipeline from main stage results
if len(resv1.Stages) > 0 {
osResult, osMetadata, err := convertStageResults(resv1.Stages)
if err != nil {
return err
}
log["os"] = osResult
if len(osMetadata) > 0 {
metadata["os"] = osMetadata
}
}
res.Log = log
res.Metadata = metadata
return nil
}
func convertStageResults(v1Stages []v1StageResult) (PipelineResult, PipelineMetadata, error) {
result := make([]StageResult, len(v1Stages))
metadata := make(map[string]StageMetadata)
for idx, srv1 := range v1Stages {
// Implicit memory alasing doesn't couse any bug in this case
/* #nosec G601 */
stageResult, stageMetadata, err := convertStageResult(&srv1)
if err != nil {
return nil, nil, err
}
result[idx] = *stageResult
if stageMetadata != nil {
metadata[stageResult.Type] = stageMetadata
}
}
return result, metadata, nil
}
func convertStageResult(sr1 *v1StageResult) (*StageResult, StageMetadata, error) {
sr := &StageResult{
ID: "",
Type: sr1.Name,
Output: sr1.Output,
Success: sr1.Success,
Error: "",
}
var metadata StageMetadata
switch sr1.Name {
case "org.osbuild.rpm":
metadata = new(RPMStageMetadata)
if err := json.Unmarshal(sr1.Metadata, metadata); err != nil {
return nil, nil, err
}
case "org.osbuild.ostree.commit":
metadata = new(OSTreeCommitStageMetadata)
if err := json.Unmarshal(sr1.Metadata, metadata); err != nil {
return nil, nil, err
}
default:
metadata = RawStageMetadata(sr1.Metadata)
}
return sr, metadata, nil
}
// isV1Result returns true if data contains a json-encoded osbuild result
// in version 1 schema.
//
// It detects the schema version by checking if the decoded json contains at
// least one of the three top-level result objects: Build, Stages, or Assembler
//
// error is non-nil when data isn't a json-encoded object.
func isV1Result(data []byte) (bool, error) {
var v1ResultStub struct {
Build interface{} `json:"build"`
Stages interface{} `json:"stages"`
Assembler interface{} `json:"assembler"`
}
err := json.Unmarshal(data, &v1ResultStub)
if err != nil {
return false, err
}
return v1ResultStub.Build != nil || v1ResultStub.Stages != nil || v1ResultStub.Assembler != nil, nil
}