Skip to content

Commit aa970d2

Browse files
authored
Merge pull request #392 from baude/addlibartifact
common: add libartifact
2 parents c305063 + 7e74b4c commit aa970d2

File tree

5 files changed

+1069
-0
lines changed

5 files changed

+1069
-0
lines changed

common/pkg/libartifact/artifact.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package libartifact
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/opencontainers/go-digest"
9+
"go.podman.io/common/pkg/libartifact/types"
10+
"go.podman.io/image/v5/manifest"
11+
)
12+
13+
type Artifact struct {
14+
// Manifest is the OCI manifest for the artifact with the name.
15+
// In a valid artifact the Manifest is guaranteed to not be nil.
16+
Manifest *manifest.OCI1
17+
Name string
18+
}
19+
20+
// TotalSizeBytes returns the total bytes of the all the artifact layers.
21+
func (a *Artifact) TotalSizeBytes() int64 {
22+
var s int64
23+
for _, layer := range a.Manifest.Layers {
24+
s += layer.Size
25+
}
26+
return s
27+
}
28+
29+
// GetName returns the "name" or "image reference" of the artifact.
30+
func (a *Artifact) GetName() (string, error) {
31+
if a.Name != "" {
32+
return a.Name, nil
33+
}
34+
// We don't have a concept of None for artifacts yet, but if we do,
35+
// then we should probably not error but return `None`
36+
return "", types.ErrArtifactUnamed
37+
}
38+
39+
// SetName is a accessor for setting the artifact name
40+
// Note: long term this may not be needed, and we would
41+
// be comfortable with simply using the exported field
42+
// called Name.
43+
func (a *Artifact) SetName(name string) {
44+
a.Name = name
45+
}
46+
47+
func (a *Artifact) GetDigest() (*digest.Digest, error) {
48+
b, err := json.Marshal(a.Manifest)
49+
if err != nil {
50+
return nil, err
51+
}
52+
artifactDigest := digest.FromBytes(b)
53+
return &artifactDigest, nil
54+
}
55+
56+
type ArtifactList []*Artifact
57+
58+
// GetByNameOrDigest returns an artifact, if present, by a given name
59+
// Returns an error if not found.
60+
func (al ArtifactList) GetByNameOrDigest(nameOrDigest string) (*Artifact, bool, error) {
61+
// This is the hot route through
62+
for _, artifact := range al {
63+
if artifact.Name == nameOrDigest {
64+
return artifact, false, nil
65+
}
66+
}
67+
// Before giving up, check by digest
68+
for _, artifact := range al {
69+
artifactDigest, err := artifact.GetDigest()
70+
if err != nil {
71+
return nil, false, err
72+
}
73+
// If the artifact's digest matches or is a prefix of ...
74+
if artifactDigest.Encoded() == nameOrDigest || strings.HasPrefix(artifactDigest.Encoded(), nameOrDigest) {
75+
return artifact, true, nil
76+
}
77+
}
78+
return nil, false, fmt.Errorf("%s: %w", nameOrDigest, types.ErrArtifactNotExist)
79+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//go:build !remote
2+
3+
package store
4+
5+
import (
6+
"context"
7+
"encoding/json"
8+
9+
specV1 "github.com/opencontainers/image-spec/specs-go/v1"
10+
"go.podman.io/image/v5/types"
11+
)
12+
13+
// unparsedArtifactImage is an interface based on the UnParsedImage and
14+
// is used only for the commit of the manifest.
15+
type unparsedArtifactImage struct {
16+
ir types.ImageReference
17+
mannyfest specV1.Manifest
18+
}
19+
20+
func (u unparsedArtifactImage) Reference() types.ImageReference {
21+
return u.ir
22+
}
23+
24+
func (u unparsedArtifactImage) Manifest(_ context.Context) ([]byte, string, error) {
25+
b, err := json.Marshal(u.mannyfest)
26+
if err != nil {
27+
return nil, "", err
28+
}
29+
return b, specV1.MediaTypeImageIndex, nil
30+
}
31+
32+
func (u unparsedArtifactImage) Signatures(_ context.Context) ([][]byte, error) {
33+
return [][]byte{}, nil
34+
}
35+
36+
func newUnparsedArtifactImage(ir types.ImageReference, mannyfest specV1.Manifest) unparsedArtifactImage {
37+
return unparsedArtifactImage{
38+
ir: ir,
39+
mannyfest: mannyfest,
40+
}
41+
}

0 commit comments

Comments
 (0)