history: set materials and attachments to json output for inspect

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2025-02-07 10:57:05 +01:00
parent 633e8a0881
commit e236b86297
No known key found for this signature in database
GPG Key ID: ADE44D8C9D44FBE4

View File

@ -88,6 +88,9 @@ type inspectOutput struct {
Config configOutput `json:"config,omitempty"` Config configOutput `json:"config,omitempty"`
Materials []materialOutput `json:"materials,omitempty"`
Attachments []attachmentOutput `json:"attachments,omitempty"`
Errors []string `json:"errors,omitempty"` Errors []string `json:"errors,omitempty"`
} }
@ -111,6 +114,17 @@ type configOutput struct {
RestRaw []keyValueOutput `json:"rest_raw,omitempty"` RestRaw []keyValueOutput `json:"rest_raw,omitempty"`
} }
type materialOutput struct {
URI string `json:"uri,omitempty"`
Digests []string `json:"digests,omitempty"`
}
type attachmentOutput struct {
Digest string `json:"digest,omitempty"`
Platform string `json:"platform,omitempty"`
Type string `json:"type,omitempty"`
}
type errorOutput struct { type errorOutput struct {
Code int `json:"code,omitempty"` Code int `json:"code,omitempty"`
Message string `json:"message,omitempty"` Message string `json:"message,omitempty"`
@ -408,6 +422,46 @@ workers0:
}) })
out.Config.RestRaw = unusedAttrs out.Config.RestRaw = unusedAttrs
attachments, err := allAttachments(ctx, store, *rec)
if err != nil {
return err
}
provIndex := slices.IndexFunc(attachments, func(a attachment) bool {
return descrType(a.descr) == slsa02.PredicateSLSAProvenance
})
if provIndex != -1 {
prov := attachments[provIndex]
dt, err := content.ReadBlob(ctx, store, prov.descr)
if err != nil {
return errors.Errorf("failed to read provenance %s: %v", prov.descr.Digest, err)
}
var pred provenancetypes.ProvenancePredicate
if err := json.Unmarshal(dt, &pred); err != nil {
return errors.Errorf("failed to unmarshal provenance %s: %v", prov.descr.Digest, err)
}
for _, m := range pred.Materials {
out.Materials = append(out.Materials, materialOutput{
URI: m.URI,
Digests: digestSetToDigests(m.Digest),
})
}
}
if len(attachments) > 0 {
for _, a := range attachments {
p := ""
if a.platform != nil {
p = platforms.FormatAll(*a.platform)
}
out.Attachments = append(out.Attachments, attachmentOutput{
Digest: a.descr.Digest.String(),
Platform: p,
Type: descrType(a.descr),
})
}
}
if opts.format == formatter.JSONFormatKey { if opts.format == formatter.JSONFormatKey {
enc := json.NewEncoder(dockerCli.Out()) enc := json.NewEncoder(dockerCli.Out())
enc.SetIndent("", " ") enc.SetIndent("", " ")
@ -526,47 +580,23 @@ workers0:
printTable(dockerCli.Out(), out.BuildArgs, "Build Arg") printTable(dockerCli.Out(), out.BuildArgs, "Build Arg")
printTable(dockerCli.Out(), out.Labels, "Label") printTable(dockerCli.Out(), out.Labels, "Label")
attachments, err := allAttachments(ctx, store, *rec) if len(out.Materials) > 0 {
if err != nil {
return err
}
provIndex := slices.IndexFunc(attachments, func(a attachment) bool {
return descrType(a.descr) == slsa02.PredicateSLSAProvenance
})
if provIndex != -1 {
prov := attachments[provIndex]
dt, err := content.ReadBlob(ctx, store, prov.descr)
if err != nil {
return errors.Errorf("failed to read provenance %s: %v", prov.descr.Digest, err)
}
var pred provenancetypes.ProvenancePredicate
if err := json.Unmarshal(dt, &pred); err != nil {
return errors.Errorf("failed to unmarshal provenance %s: %v", prov.descr.Digest, err)
}
fmt.Fprintln(dockerCli.Out(), "Materials:") fmt.Fprintln(dockerCli.Out(), "Materials:")
tw = tabwriter.NewWriter(dockerCli.Out(), 1, 8, 1, '\t', 0) tw = tabwriter.NewWriter(dockerCli.Out(), 1, 8, 1, '\t', 0)
fmt.Fprintf(tw, "URI\tDIGEST\n") fmt.Fprintf(tw, "URI\tDIGEST\n")
for _, m := range pred.Materials { for _, m := range out.Materials {
fmt.Fprintf(tw, "%s\t%s\n", m.URI, strings.Join(digestSetToDigests(m.Digest), ", ")) fmt.Fprintf(tw, "%s\t%s\n", m.URI, strings.Join(m.Digests, ", "))
} }
tw.Flush() tw.Flush()
fmt.Fprintln(dockerCli.Out()) fmt.Fprintln(dockerCli.Out())
} }
if len(attachments) > 0 { if len(out.Attachments) > 0 {
fmt.Fprintf(tw, "Attachments:\n") fmt.Fprintf(tw, "Attachments:\n")
tw = tabwriter.NewWriter(dockerCli.Out(), 1, 8, 1, '\t', 0) tw = tabwriter.NewWriter(dockerCli.Out(), 1, 8, 1, '\t', 0)
fmt.Fprintf(tw, "DIGEST\tPLATFORM\tTYPE\n") fmt.Fprintf(tw, "DIGEST\tPLATFORM\tTYPE\n")
for _, a := range attachments { for _, a := range out.Attachments {
p := "" fmt.Fprintf(tw, "%s\t%s\t%s\n", a.Digest, a.Platform, a.Type)
if a.platform != nil {
p = platforms.FormatAll(*a.platform)
}
fmt.Fprintf(tw, "%s\t%s\t%s\n", a.descr.Digest, p, descrType(a.descr))
} }
tw.Flush() tw.Flush()
fmt.Fprintln(dockerCli.Out()) fmt.Fprintln(dockerCli.Out())