File: schema1.go

package info (click to toggle)
singularity-container 4.1.5%2Bds4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 43,876 kB
  • sloc: asm: 14,840; sh: 3,190; ansic: 1,751; awk: 414; makefile: 413; python: 99
file content (88 lines) | stat: -rw-r--r-- 2,567 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package imageutil

import (
	"context"
	"encoding/json"
	"io"
	"strings"
	"time"

	"github.com/containerd/containerd/remotes"
	dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
	digest "github.com/opencontainers/go-digest"
	ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
)

func readSchema1Config(ctx context.Context, desc ocispecs.Descriptor, fetcher remotes.Fetcher) (digest.Digest, []byte, error) {
	rc, err := fetcher.Fetch(ctx, desc)
	if err != nil {
		return "", nil, err
	}
	defer rc.Close()
	dt, err := io.ReadAll(rc)
	if err != nil {
		return "", nil, errors.Wrap(err, "failed to fetch schema1 manifest")
	}
	dt, err = convertSchema1ConfigMeta(dt)
	if err != nil {
		return "", nil, err
	}
	return desc.Digest, dt, nil
}

func convertSchema1ConfigMeta(in []byte) ([]byte, error) {
	type history struct {
		V1Compatibility string `json:"v1Compatibility"`
	}
	var m struct {
		History []history `json:"history"`
	}
	if err := json.Unmarshal(in, &m); err != nil {
		return nil, errors.Wrap(err, "failed to unmarshal schema1 manifest")
	}
	if len(m.History) == 0 {
		return nil, errors.Errorf("invalid schema1 manifest")
	}

	var img dockerspec.DockerOCIImage
	if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), &img); err != nil {
		return nil, errors.Wrap(err, "failed to unmarshal image from schema 1 history")
	}

	img.RootFS = ocispecs.RootFS{
		Type: "layers", // filled in by exporter
	}
	img.History = make([]ocispecs.History, len(m.History))

	for i := range m.History {
		var h v1History
		if err := json.Unmarshal([]byte(m.History[i].V1Compatibility), &h); err != nil {
			return nil, errors.Wrap(err, "failed to unmarshal history")
		}
		img.History[len(m.History)-i-1] = ocispecs.History{
			Author:     h.Author,
			Comment:    h.Comment,
			Created:    &h.Created,
			CreatedBy:  strings.Join(h.ContainerConfig.Cmd, " "),
			EmptyLayer: (h.ThrowAway != nil && *h.ThrowAway) || (h.Size != nil && *h.Size == 0),
		}
	}

	dt, err := json.MarshalIndent(img, "", "  ")
	if err != nil {
		return nil, errors.Wrap(err, "failed to marshal schema1 config")
	}
	return dt, nil
}

type v1History struct {
	Author          string    `json:"author,omitempty"`
	Created         time.Time `json:"created"`
	Comment         string    `json:"comment,omitempty"`
	ThrowAway       *bool     `json:"throwaway,omitempty"`
	Size            *int      `json:"Size,omitempty"` // used before ThrowAway field
	ContainerConfig struct {
		Cmd []string `json:"Cmd,omitempty"`
	} `json:"container_config,omitempty"`
}