Merge pull request #102 from joshrwolf/content-location-tagging

standardize content naming for unnamed content
This commit is contained in:
Josh Wolf
2021-12-13 15:32:40 -07:00
committed by GitHub
19 changed files with 218 additions and 148 deletions

View File

@@ -5,7 +5,6 @@ import (
"encoding/json"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
@@ -15,6 +14,7 @@ import (
"github.com/rancherfederal/hauler/internal/mapper"
"github.com/rancherfederal/hauler/pkg/consts"
"github.com/rancherfederal/hauler/pkg/log"
"github.com/rancherfederal/hauler/pkg/reference"
)
type Opts struct {
@@ -36,7 +36,7 @@ func (o *Opts) AddArgs(cmd *cobra.Command) {
f.BoolVar(&o.PlainHTTP, "plain-http", false, "Toggle allowing plain http connections when copying to a remote registry")
}
func Cmd(ctx context.Context, o *Opts, reference string) error {
func Cmd(ctx context.Context, o *Opts, ref string) error {
l := log.FromContext(ctx)
rs, err := content.NewRegistry(content.RegistryOptions{
@@ -49,12 +49,12 @@ func Cmd(ctx context.Context, o *Opts, reference string) error {
return err
}
ref, err := name.ParseReference(reference)
r, err := reference.Parse(ref)
if err != nil {
return err
}
desc, err := remote.Get(ref, remote.WithAuthFromKeychain(authn.DefaultKeychain), remote.WithContext(ctx))
desc, err := remote.Get(r, remote.WithAuthFromKeychain(authn.DefaultKeychain), remote.WithContext(ctx))
if err != nil {
return err
}
@@ -74,7 +74,7 @@ func Cmd(ctx context.Context, o *Opts, reference string) error {
return err
}
pushedDesc, err := oras.Copy(ctx, rs, ref.Name(), mapperStore, "",
pushedDesc, err := oras.Copy(ctx, rs, r.Name(), mapperStore, "",
oras.WithAdditionalCachedMediaTypes(consts.DockerManifestSchema2))
if err != nil {
return err

View File

@@ -155,7 +155,7 @@ func addStoreInfo() *cobra.Command {
Use: "info",
Short: "Print out information about the store",
Args: cobra.ExactArgs(0),
Aliases: []string{"i"},
Aliases: []string{"i", "list", "ls"},
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

View File

@@ -2,11 +2,9 @@ package store
import (
"context"
"fmt"
"os"
"github.com/google/go-containerregistry/pkg/name"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"github.com/rancherfederal/hauler/pkg/apis/hauler.cattle.io/v1alpha1"
@@ -14,6 +12,7 @@ import (
"github.com/rancherfederal/hauler/pkg/content/file"
"github.com/rancherfederal/hauler/pkg/content/image"
"github.com/rancherfederal/hauler/pkg/log"
"github.com/rancherfederal/hauler/pkg/reference"
"github.com/rancherfederal/hauler/pkg/store"
)
@@ -26,68 +25,9 @@ func (o *AddFileOpts) AddFlags(cmd *cobra.Command) {
f.StringVarP(&o.Name, "name", "n", "", "(Optional) Name to assign to file in store")
}
// func addContent(ctx context.Context, o *AddFileOpts, s *store.Store, meta metav1.TypeMeta) error {
// l := log.FromContext(ctx)
//
// var (
// oci artifact.OCI
// loc string
// )
//
// switch cfg := meta.(type) {
// case cfg == v1alpha1.FilesContentKind:
// f := file.NewFile(cfg)
// oci = f
//
// loc = f.Name(reference)
//
// case "chart":
// oci, err := chart.NewThickChart(ch.Name, ch.RepoURL, ch.Version)
// if err != nil {
// return err
// }
//
// tag := ch.Version
// if tag == "" {
// tag = name.DefaultTag
// }
//
// ref, err := name.ParseReference(ch.Name, name.WithDefaultRegistry(""), name.WithDefaultTag(tag))
// if err != nil {
// return err
// }
//
//
// case "image":
// i, err := image.NewImage(reference)
// if err != nil {
// return err
// }
// oci = i
//
// loc = reference
//
// default:
// return nil
//
// }
// ref, err := name.ParseReference(loc, name.WithDefaultRegistry(""))
// if err != nil {
// return err
// }
//
// desc, err := s.AddArtifact(ctx, oci, ref)
// if err != nil {
// return err
// }
//
// l.Infof("added [%s] of type [%s] to store", ref.Name(), s.Identify(ctx, desc))
// return nil
// }
func AddFileCmd(ctx context.Context, o *AddFileOpts, s *store.Store, reference string) error {
cfg := v1alpha1.File{
Ref: reference,
Path: reference,
}
return storeFile(ctx, s, cfg)
@@ -96,14 +36,18 @@ func AddFileCmd(ctx context.Context, o *AddFileOpts, s *store.Store, reference s
func storeFile(ctx context.Context, s *store.Store, fi v1alpha1.File) error {
l := log.FromContext(ctx)
f := file.NewFile(fi.Ref)
desc, err := s.AddArtifact(ctx, f, f.Name(fi.Ref))
f := file.NewFile(fi.Path)
ref, err := reference.NewTagged(f.Name(fi.Path), reference.DefaultTag)
if err != nil {
return err
}
l.With(log.Fields{"type": s.Identify(ctx, desc)}).Infof("added [%s] to store", desc.Annotations[ocispec.AnnotationRefName])
desc, err := s.AddArtifact(ctx, f, ref.Name())
if err != nil {
return err
}
l.Infof("added 'file' to store at [%s], with digest [%s]", ref.Name(), desc.Digest.String())
return nil
}
@@ -118,7 +62,7 @@ func (o *AddImageOpts) AddFlags(cmd *cobra.Command) {
func AddImageCmd(ctx context.Context, o *AddImageOpts, s *store.Store, reference string) error {
cfg := v1alpha1.Image{
Ref: reference,
Name: reference,
}
return storeImage(ctx, s, cfg)
@@ -127,17 +71,22 @@ func AddImageCmd(ctx context.Context, o *AddImageOpts, s *store.Store, reference
func storeImage(ctx context.Context, s *store.Store, i v1alpha1.Image) error {
l := log.FromContext(ctx)
oci, err := image.NewImage(i.Ref)
oci, err := image.NewImage(i.Name)
if err != nil {
return err
}
desc, err := s.AddArtifact(ctx, oci, i.Ref)
r, err := name.ParseReference(i.Name)
if err != nil {
return err
}
l.With(log.Fields{"type": s.Identify(ctx, desc)}).Infof("added [%s] to store", i.Ref)
desc, err := s.AddArtifact(ctx, oci, r.Name())
if err != nil {
return err
}
l.Infof("added 'image' to store at [%s], with digest [%s]", r.Name(), desc.Digest.String())
return nil
}
@@ -178,17 +127,15 @@ func storeChart(ctx context.Context, s *store.Store, cfg v1alpha1.Chart) error {
return err
}
tag := cfg.Version
if tag == "" {
tag = name.DefaultTag
ref, err := reference.NewTagged(cfg.Name, cfg.Version)
if err != nil {
return err
}
ref := fmt.Sprintf("%s:%s", cfg.Name, tag)
desc, err := s.AddArtifact(ctx, oci, ref)
desc, err := s.AddArtifact(ctx, oci, ref.Name())
if err != nil {
return err
}
l.With(log.Fields{"type": s.Identify(ctx, desc)}).Infof("added [%s] to store", ref)
l.Infof("added 'chart' to store at [%s], with digest [%s]", ref.Name(), desc.Digest.String())
return nil
}

View File

@@ -3,14 +3,14 @@ package store
import (
"context"
"encoding/json"
"fmt"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/layout"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
"github.com/rancherfederal/hauler/internal/mapper"
"github.com/rancherfederal/hauler/pkg/log"
"github.com/rancherfederal/hauler/pkg/reference"
"github.com/rancherfederal/hauler/pkg/store"
)
@@ -21,56 +21,55 @@ type ExtractOpts struct {
func (o *ExtractOpts) AddArgs(cmd *cobra.Command) {
f := cmd.Flags()
f.StringVar(&o.DestinationDir, "dir", "", "Directory to save contents to (defaults to current directory)")
f.StringVarP(&o.DestinationDir, "output", "o", "", "Directory to save contents to (defaults to current directory)")
}
func ExtractCmd(ctx context.Context, o *ExtractOpts, s *store.Store, reference string) error {
func ExtractCmd(ctx context.Context, o *ExtractOpts, s *store.Store, ref string) error {
l := log.FromContext(ctx)
ref, err := name.ParseReference(reference, name.WithDefaultRegistry(""), name.WithDefaultTag("latest"))
r, err := reference.Parse(ref)
if err != nil {
return err
}
p, err := layout.FromPath("store")
if err != nil {
return err
}
ii, _ := p.ImageIndex()
im, _ := ii.IndexManifest()
var manifest ocispec.Manifest
for _, m := range im.Manifests {
if r, ok := m.Annotations[ocispec.AnnotationRefName]; !ok || r != ref.Name() {
continue
found := false
if err := s.Content.Walk(func(reference string, desc ocispec.Descriptor) error {
if reference != r.Name() {
return nil
}
found = true
desc, err := p.Image(m.Digest)
rc, err := s.Content.Fetch(ctx, desc)
if err != nil {
return err
}
l.Infof(m.Annotations[ocispec.AnnotationRefName])
defer rc.Close()
manifestData, err := desc.RawManifest()
var m ocispec.Manifest
if err := json.NewDecoder(rc).Decode(&m); err != nil {
return err
}
mapperStore, err := mapper.FromManifest(m, o.DestinationDir)
if err != nil {
return err
}
if err := json.Unmarshal(manifestData, &manifest); err != nil {
pushedDesc, err := s.Copy(ctx, r.Name(), mapperStore, "")
if err != nil {
return err
}
}
mapperStore, err := mapper.FromManifest(manifest, o.DestinationDir)
if err != nil {
l.Infof("extracted [%s] from store with digest [%s]", pushedDesc.MediaType, pushedDesc.Digest.String())
return nil
}); err != nil {
return err
}
desc, err := s.Copy(ctx, ref.Name(), mapperStore, "")
if err != nil {
return err
if !found {
return fmt.Errorf("reference [%s] not found in store (hint: use `hauler store info` to list store contents)", ref)
}
l.Infof("downloaded [%s] with digest [%s]", desc.MediaType, desc.Digest.String())
return nil
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/spf13/cobra"
"github.com/rancherfederal/hauler/pkg/consts"
"github.com/rancherfederal/hauler/pkg/reference"
"github.com/rancherfederal/hauler/pkg/store"
)
@@ -115,8 +116,13 @@ func newItem(s *store.Store, desc ocispec.Descriptor, m ocispec.Manifest) item {
ctype = "unknown"
}
ref, err := reference.Parse(desc.Annotations[ocispec.AnnotationRefName])
if err != nil {
return item{}
}
return item{
Reference: desc.Annotations[ocispec.AnnotationRefName],
Reference: ref.Name(),
Type: ctype,
Layers: len(m.Layers),
Size: byteCountSI(size),

4
go.mod
View File

@@ -95,8 +95,8 @@ require (
github.com/lib/pq v1.10.4 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.8 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect

7
go.sum
View File

@@ -684,11 +684,13 @@ github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2
github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
@@ -1193,6 +1195,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@@ -18,5 +18,11 @@ type FileSpec struct {
}
type File struct {
Ref string `json:"ref"`
// Path is the path to the file contents, can be a local or remote path
Path string `json:"path"`
// Reference is an optionally defined reference to the contents within the store
// If not specified, this will be generated as follows:
// hauler/<path base>:latest
Reference string `json:"reference,omitempty"`
}

View File

@@ -18,5 +18,6 @@ type ImageSpec struct {
}
type Image struct {
Ref string `json:"ref"`
// Name is the full location for the image, can be referenced by tags or digests
Name string `json:"name"`
}

View File

@@ -74,11 +74,11 @@ func (c *tchart) dependentImages() error {
}
for _, img := range imgs.Spec.Images {
i, err := image.NewImage(img.Ref)
i, err := image.NewImage(img.Name)
if err != nil {
return err
}
c.contents[img.Ref] = i
c.contents[img.Name] = i
}
return nil
}

View File

@@ -48,7 +48,7 @@ func ImagesInChart(c *helmchart.Chart) (v1alpha1.Images, error) {
found := find(raw, defaultKnownImagePaths...)
for _, f := range found {
images = append(images, v1alpha1.Image{Ref: f})
images = append(images, v1alpha1.Image{Name: f})
}
}

View File

@@ -16,9 +16,9 @@ import (
var _ artifact.OCI = (*File)(nil)
// File implements the OCI interface for File API objects. API spec information is
// stored into the Ref field.
// stored into the Path field.
type File struct {
Ref string
Path string
client *getter.Client
@@ -29,12 +29,12 @@ type File struct {
annotations map[string]string
}
func NewFile(ref string, opts ...Option) *File {
func NewFile(path string, opts ...Option) *File {
client := getter.NewClient(getter.ClientOptions{})
f := &File{
client: client,
Ref: ref,
Path: path,
}
for _, opt := range opts {
@@ -43,8 +43,8 @@ func NewFile(ref string, opts ...Option) *File {
return f
}
func (f *File) Name(ref string) string {
return f.client.Name(ref)
func (f *File) Name(path string) string {
return f.client.Name(path)
}
func (f *File) MediaType() string {
@@ -80,7 +80,7 @@ func (f *File) compute() error {
}
ctx := context.Background()
blob, err := f.client.LayerFrom(ctx, f.Ref)
blob, err := f.client.LayerFrom(ctx, f.Path)
if err != nil {
return err
}
@@ -90,9 +90,9 @@ func (f *File) compute() error {
return err
}
cfg := f.client.Config(f.Ref)
cfg := f.client.Config(f.Path)
if cfg == nil {
cfg = f.client.Config(f.Ref)
cfg = f.client.Config(f.Path)
}
cfgDesc, err := partial.Descriptor(cfg)

View File

@@ -2,7 +2,7 @@ package image
import (
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
gname "github.com/google/go-containerregistry/pkg/name"
gv1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
@@ -24,14 +24,14 @@ func (i *Image) RawConfig() ([]byte, error) {
}
// Image implements the OCI interface for Image API objects. API spec information
// is stored into the Ref field.
// is stored into the Name field.
type Image struct {
Ref string
Name string
gv1.Image
}
func NewImage(ref string, opts ...remote.Option) (*Image, error) {
r, err := name.ParseReference(ref)
func NewImage(name string, opts ...remote.Option) (*Image, error) {
r, err := gname.ParseReference(name)
if err != nil {
return nil, err
}
@@ -47,7 +47,7 @@ func NewImage(ref string, opts ...remote.Option) (*Image, error) {
}
return &Image{
Ref: ref,
Name: name,
Image: img,
}, nil
}

View File

@@ -14,6 +14,7 @@ type Logger interface {
SetLevel(string)
With(Fields) *logger
WithContext(context.Context) context.Context
Errorf(string, ...interface{})
Infof(string, ...interface{})
Warnf(string, ...interface{})

View File

@@ -0,0 +1,49 @@
// Package reference provides general types to represent oci content within a registry or local oci layout
// Grammar (stolen mostly from containerd's grammar)
//
// reference :=
package reference
import (
"strings"
gname "github.com/google/go-containerregistry/pkg/name"
)
const (
DefaultNamespace = "hauler"
DefaultTag = "latest"
)
type Reference interface {
// FullName is the full name of the reference
FullName() string
// Name is the registryless name
Name() string
}
// NewTagged will create a new docker.NamedTagged given a path-component
func NewTagged(n string, tag string) (gname.Reference, error) {
repo, err := Parse(n)
if err != nil {
return nil, err
}
return repo.Context().Tag(tag), nil
}
// Parse will parse a reference and return a name.Reference namespaced with DefaultNamespace if necessary
func Parse(ref string) (gname.Reference, error) {
r, err := gname.ParseReference(ref, gname.WithDefaultRegistry(""), gname.WithDefaultTag(DefaultTag))
if err != nil {
return nil, err
}
if !strings.ContainsRune(r.String(), '/') {
ref = DefaultNamespace + "/" + r.String()
return gname.ParseReference(ref, gname.WithDefaultRegistry(""), gname.WithDefaultTag(DefaultTag))
}
return r, nil
}

View File

@@ -0,0 +1,57 @@
package reference_test
import (
"reflect"
"testing"
"github.com/rancherfederal/hauler/pkg/reference"
)
func TestParse(t *testing.T) {
type args struct {
ref string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "Should add hauler namespace when doesn't exist",
args: args{
ref: "myfile",
},
want: "hauler/myfile:latest",
wantErr: false,
},
{
name: "shouldn't modify namespaced reference",
args: args{
ref: "rancher/rancher:latest",
},
want: "rancher/rancher:latest",
wantErr: false,
},
{
name: "Shouldn't modify canonical reference",
args: args{
ref: "index.docker.io/library/registry@sha256:42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f",
},
want: "index.docker.io/library/registry@sha256:42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := reference.Parse(tt.args.ref)
if (err != nil) != tt.wantErr {
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got.Name(), tt.want) {
t.Errorf("Parse() got = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -15,6 +15,7 @@ import (
"github.com/rancherfederal/hauler/internal/cache"
"github.com/rancherfederal/hauler/pkg/artifact"
"github.com/rancherfederal/hauler/pkg/consts"
"github.com/rancherfederal/hauler/pkg/reference"
)
type Store struct {
@@ -46,7 +47,7 @@ func NewStore(rootdir string, opts ...Options) (*Store, error) {
// saved, the entirety of the layout is copied to the store (which is just a registry). This allows us to not only use
// strict types to define generic content, but provides a processing pipeline suitable for extensibility. In the
// future we'll allow users to define their own content that must adhere either by artifact.OCI or simply an OCI layout.
func (s *Store) AddArtifact(ctx context.Context, oci artifact.OCI, reference string) (ocispec.Descriptor, error) {
func (s *Store) AddArtifact(ctx context.Context, oci artifact.OCI, r string) (ocispec.Descriptor, error) {
stage, err := newLayout()
if err != nil {
return ocispec.Descriptor{}, err
@@ -57,10 +58,10 @@ func (s *Store) AddArtifact(ctx context.Context, oci artifact.OCI, reference str
oci = cached
}
// Ensure that index.docker.io isn't prepended
ref, err := name.ParseReference(reference, name.WithDefaultRegistry(""), name.WithDefaultTag("latest"))
// Validate we have a locatable reference
ref, err := reference.Parse(r)
if err != nil {
return ocispec.Descriptor{}, fmt.Errorf("%w", ErrInvalidReference)
return ocispec.Descriptor{}, err
}
if err := stage.add(ctx, oci, ref); err != nil {

View File

@@ -51,7 +51,7 @@ func TestStore_AddArtifact(t *testing.T) {
name: "should add artifact with a valid tagged reference",
args: args{
ctx: ctx,
reference: "random:v1",
reference: "hauler/random:v1",
},
wantErr: false,
},

View File

@@ -5,17 +5,17 @@ metadata:
spec:
files:
# hauler can save/redistribute files on disk (be careful! paths are relative)
- ref: testdata/contents.yaml
- path: testdata/contents.yaml
# TODO: when directories are specified, they will be archived and stored as a file
# - ref: testdata/
# - path: testdata/
# hauler can also fetch remote content, and will "smartly" identify filenames _when possible_
# filename below = "k3s-images.txt"
- ref: "https://github.com/k3s-io/k3s/releases/download/v1.22.2%2Bk3s2/k3s-images.txt"
- path: "https://github.com/k3s-io/k3s/releases/download/v1.22.2%2Bk3s2/k3s-images.txt"
# when filenames are not appropriate, a name should be specified
- ref: https://get.k3s.io?filename=get-k3s.sh
- path: https://get.k3s.io?filename=get-k3s.sh
---
apiVersion: content.hauler.cattle.io/v1alpha1
@@ -25,16 +25,16 @@ metadata:
spec:
images:
# images can be referenced shorthanded without a tag
- ref: hello-world
- name: hello-world
# or namespaced with a tag
- ref: rancher/cowsay:latest
- name: rancher/cowsay:latest
# or by their digest:
# - ref: registry@sha256:42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f
- name: registry@sha256:42043edfae481178f07aa077fa872fcc242e276d302f4ac2026d9d2eb65b955f
# or fully qualified from any OCI compliant registry registry
- ref: ghcr.io/fluxcd/flux-cli:v0.22.0
- name: ghcr.io/fluxcd/flux-cli:v0.22.0
---
apiVersion: content.hauler.cattle.io/v1alpha1