Skip to content

Commit

Permalink
feat: artifact and ocitar
Browse files Browse the repository at this point in the history
  • Loading branch information
morlay committed May 15, 2024
1 parent 19cb886 commit 0719d86
Show file tree
Hide file tree
Showing 25 changed files with 1,219 additions and 23 deletions.
10 changes: 7 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ module github.com/octohelm/crkit
go 1.22.2

require (
github.com/containerd/containerd v1.7.16
github.com/distribution/distribution/v3 v3.0.0-alpha.1
github.com/distribution/reference v0.6.0
github.com/go-courier/logr v0.3.0
github.com/google/go-containerregistry v0.19.1
github.com/innoai-tech/infra v0.0.0-20240508041032-12069adfe35c
github.com/octohelm/courier v0.0.0-20240506093745-6b6f6acaf660
github.com/octohelm/gengo v0.0.0-20240409082121-aeffa5400f19
github.com/octohelm/courier v0.0.0-20240510063732-a8aa1af87601
github.com/octohelm/gengo v0.0.0-20240510051519-974fb897453b
github.com/octohelm/kubekit v0.0.0-20240508035712-15cb61729772
github.com/octohelm/kubepkgspec v0.0.0-20240514102555-08917801bb86
github.com/octohelm/storage v0.0.0-20240430010427-f412a0c84f3b
github.com/octohelm/x v0.0.0-20240513022938-1bd86d96adef
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0
github.com/pelletier/go-toml/v2 v2.2.2
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.9.3
Expand All @@ -25,11 +28,13 @@ require (

require (
cuelang.org/go v0.8.2 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
Expand Down Expand Up @@ -76,7 +81,6 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/gomega v1.33.1 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/prometheus/client_golang v1.19.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.53.0 // indirect
Expand Down
16 changes: 12 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e/go.mod h1:ApHc
cuelang.org/go v0.8.2 h1:vWfHI1kQlBvwkna7ktAqXjV5LUEAgU6vyMlJjvZZaDw=
cuelang.org/go v0.8.2/go.mod h1:CoDbYolfMms4BhWUlhD+t5ORnihR7wvjcfgyO9lL5FI=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
Expand All @@ -24,6 +26,10 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg=
github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc=
github.com/containerd/containerd v1.7.16 h1:7Zsfe8Fkj4Wi2My6DXGQ87hiqIrmOXolm72ZEkFU5Mg=
github.com/containerd/containerd v1.7.16/go.mod h1:NL49g7A/Fui7ccmxV6zkBWwqMgmMxFWzujYCc+JLt7k=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
Expand Down Expand Up @@ -178,12 +184,14 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/octohelm/courier v0.0.0-20240506093745-6b6f6acaf660 h1:D3jgAqV+5ObUlj/9JEQWirGZ/oC8liFH6+0Bz9h8tMc=
github.com/octohelm/courier v0.0.0-20240506093745-6b6f6acaf660/go.mod h1:lYPuTnuOSyTHOweXCoDQbPphAZ00ZMRtctUTGSI0YNE=
github.com/octohelm/gengo v0.0.0-20240409082121-aeffa5400f19 h1:l8ahFVtDhXAcKFmR1/6Sevs1R71Kai7dfp95ZlG7raY=
github.com/octohelm/gengo v0.0.0-20240409082121-aeffa5400f19/go.mod h1:Q0f7oofuZJ6T2vk5vsXgjKwKNlOJO0TTrjGfA9yRJwA=
github.com/octohelm/courier v0.0.0-20240510063732-a8aa1af87601 h1:xfvMM+bQ4ONY3DCU7nZiQPqTXnCynvEFB4n2JBHN3v4=
github.com/octohelm/courier v0.0.0-20240510063732-a8aa1af87601/go.mod h1:lYPuTnuOSyTHOweXCoDQbPphAZ00ZMRtctUTGSI0YNE=
github.com/octohelm/gengo v0.0.0-20240510051519-974fb897453b h1:z/XJuBmwnxoPPMl2mY11CsU2w8yiLq5q3bwdmkrPCWo=
github.com/octohelm/gengo v0.0.0-20240510051519-974fb897453b/go.mod h1:mlnC4bXnp0RdKxBf1u4bFQ0pmyDHUfXI9czal6K8lS0=
github.com/octohelm/kubekit v0.0.0-20240508035712-15cb61729772 h1:X+mCc0CTxFo0BMMVeGBEDudulp2fGiftUD9rJS9OmOQ=
github.com/octohelm/kubekit v0.0.0-20240508035712-15cb61729772/go.mod h1:wbxe94x0pWeoE77qvcBDjvn7tnndvZ0pv2VeSz0UscA=
github.com/octohelm/kubepkgspec v0.0.0-20240514102555-08917801bb86 h1:Q46GYugI8+DQGEwUncRVUK/Zes0rEBcLE6TOAN5O7nM=
github.com/octohelm/kubepkgspec v0.0.0-20240514102555-08917801bb86/go.mod h1:ZWxreIiVDp2PA6CrHnZ0HJBu6ibhyL4LqTVigEMjt34=
github.com/octohelm/storage v0.0.0-20240430010427-f412a0c84f3b h1:lLYKRyVNrS+72y4k9ZZohVrJUIyfYIg1un0CtFBCixw=
github.com/octohelm/storage v0.0.0-20240430010427-f412a0c84f3b/go.mod h1:6eArB7GTmErZjXofekKO9Y7zJbUl1dJiQ/JT/jBmuwM=
github.com/octohelm/x v0.0.0-20240513022938-1bd86d96adef h1:BoG/tg33jwNZ8BZA6nFc1wIl88P+2SgTzJmr4c+E8sY=
Expand Down
3 changes: 1 addition & 2 deletions internal/cmd/crkit/zz_generated.runtimedoc.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Package main GENERATED BY gengo:runtimedoc
Package main GENERATED BY gengo:runtimedoc
DON'T EDIT THIS FILE
*/
package main
Expand All @@ -21,7 +21,6 @@ func (v KubeClient) RuntimeDoc(names ...string) ([]string, bool) {
return []string{
"Paths to a kubeconfig. Only required if out-of-cluster.",
}, true

}

return nil, false
Expand Down
29 changes: 29 additions & 0 deletions pkg/artifact/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package artifact

type Config interface {
ArtifactType() (string, error)
ConfigMediaType() (string, error)
RawConfigFile() ([]byte, error)
}

func EmptyConfig(artifactType string) Config {
return &emptyConfigArtifact{
artifactType: artifactType,
}
}

type emptyConfigArtifact struct {
artifactType string
}

func (i *emptyConfigArtifact) ArtifactType() (string, error) {
return i.artifactType, nil
}

func (i *emptyConfigArtifact) ConfigMediaType() (string, error) {
return "application/vnd.oci.empty.v1+json", nil
}

func (i *emptyConfigArtifact) RawConfigFile() ([]byte, error) {
return []byte("{}"), nil
}
148 changes: 148 additions & 0 deletions pkg/artifact/image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package artifact

import (
"bytes"
"encoding/json"
"sync/atomic"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/opencontainers/go-digest"
specv1 "github.com/opencontainers/image-spec/specs-go/v1"
)

func Artifact(img v1.Image, c Config) (v1.Image, error) {
return &artifactImage{
Image: img,
config: c,
}, nil
}

type artifactImage struct {
v1.Image
config Config

m atomic.Pointer[specv1.Manifest]
}

func (img *artifactImage) MediaType() (types.MediaType, error) {
return types.OCIManifestSchema1, nil
}

func (i *artifactImage) ConfigName() (v1.Hash, error) {
return partial.ConfigName(i)
}

func (img *artifactImage) RawConfigFile() ([]byte, error) {
return img.config.RawConfigFile()
}

func (img *artifactImage) Manifest() (*v1.Manifest, error) {
raw, err := img.RawManifest()
if err != nil {
return nil, err
}

m := &v1.Manifest{}

if err := json.Unmarshal(raw, m); err != nil {
return nil, err
}

return m, nil
}

func (img *artifactImage) RawManifest() ([]byte, error) {
m, err := img.OCIManifest()
if err != nil {
return nil, err
}
return json.MarshalIndent(m, "", " ")
}

func (img *artifactImage) OCIManifest() (*specv1.Manifest, error) {
if m := img.m.Load(); m != nil {
return m, nil
}

configRaw, err := img.RawConfigFile()
if err != nil {
return nil, err
}

cfgHash, cfgSize, err := v1.SHA256(bytes.NewReader(configRaw))
if err != nil {
return nil, err
}

mediaType, err := img.MediaType()
if err != nil {
return nil, err
}

artifactType, err := img.config.ArtifactType()
if err != nil {
return nil, err
}

configMediaType, err := img.config.ConfigMediaType()
if err != nil {
return nil, err
}

m := &specv1.Manifest{
MediaType: string(mediaType),
ArtifactType: artifactType,
Config: specv1.Descriptor{
MediaType: configMediaType,
Size: cfgSize,
Digest: digest.Digest(cfgHash.String()),
},
}
m.SchemaVersion = 2

layers, err := img.Image.Layers()
if err != nil {
return nil, err
}

for _, l := range layers {
desc, err := partial.Descriptor(l)
if err != nil {
return nil, err
}

d := specv1.Descriptor{
MediaType: string(desc.MediaType),
Digest: digest.Digest(desc.Digest.String()),
Size: desc.Size,
Annotations: desc.Annotations,
ArtifactType: desc.ArtifactType,
}

if p := desc.Platform; p != nil {
d.Platform = &specv1.Platform{
Architecture: p.Architecture,
OS: p.OS,
OSVersion: p.OSVersion,
OSFeatures: p.OSFeatures,
Variant: p.Variant,
}
}

m.Layers = append(m.Layers, d)
}

img.m.Store(m)

return m, nil
}

func (img *artifactImage) Size() (int64, error) {
return partial.Size(img)
}

func (img *artifactImage) Digest() (v1.Hash, error) {
return partial.Digest(img)
}
101 changes: 101 additions & 0 deletions pkg/artifact/layer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package artifact

import (
"bytes"
"fmt"
"io"
"sync"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/types"
)

type Layer = v1.Layer

func FromBytes(mediaType string, data []byte) (Layer, error) {
return FromOpener(mediaType, func() (io.ReadCloser, error) {
return io.NopCloser(bytes.NewBuffer(data)), nil
})
}

func FromReader(mediaType string, r io.Reader) (Layer, error) {
return FromOpener(mediaType, func() (io.ReadCloser, error) {
return io.NopCloser(r), nil
})
}

func FromOpener(mediaType string, uncompressed func() (io.ReadCloser, error)) (Layer, error) {
return NonCompressedLayer(&artifact{
mediaType: mediaType,
uncompressed: uncompressed,
}), nil
}

type artifact struct {
mediaType string
uncompressed func() (io.ReadCloser, error)
}

func (a *artifact) MediaType() (types.MediaType, error) {
return types.MediaType(a.mediaType), nil
}

func (a *artifact) Uncompressed() (io.ReadCloser, error) {
return a.uncompressed()
}

func Gzipped(l Layer) Layer {
return &compressed{
Layer: l,
compressedLayer: sync.OnceValues(func() (v1.Layer, error) {
return partial.UncompressedToLayer(l)
}),
}
}

type compressed struct {
Layer
compressedLayer func() (v1.Layer, error)
}

func (a *compressed) MediaType() (types.MediaType, error) {
m, err := a.Layer.MediaType()
if err != nil {
return "", err
}
return types.MediaType(fmt.Sprintf("%s+gzip", m)), nil
}

func (a *compressed) Compressed() (io.ReadCloser, error) {
l, err := a.compressedLayer()
if err != nil {
return nil, err
}
return l.Compressed()
}

func (a *compressed) Digest() (v1.Hash, error) {
l, err := a.compressedLayer()
if err != nil {
return v1.Hash{}, err
}
return l.Digest()
}

func WithDescriptor(l Layer, descriptor v1.Descriptor) Layer {
return &artifactWithDescriptor{
desc: descriptor,
Layer: l,
}
}

type artifactWithDescriptor struct {
Layer

desc v1.Descriptor
}

func (w *artifactWithDescriptor) Descriptor() (*v1.Descriptor, error) {
return &w.desc, nil
}
Loading

0 comments on commit 0719d86

Please sign in to comment.