Skip to content

Commit

Permalink
Rework local storage interface to avoid redefining existing interfaces
Browse files Browse the repository at this point in the history
Add a minimal wrapper over oci.Store to enable working with local
storage and rework previous SaveModel functions to take a oras.Target
interface as a parameter rather than be parts of an interface we define.
  • Loading branch information
amisevsk committed Feb 28, 2024
1 parent 0cee774 commit 0b9778a
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 548 deletions.
17 changes: 10 additions & 7 deletions pkg/cmd/build/build.go
Expand Up @@ -2,13 +2,14 @@ package build

import (
"context"
"fmt"
"kitops/pkg/artifact"
"kitops/pkg/lib/constants"
"kitops/pkg/lib/filesystem"
"kitops/pkg/lib/repo"
"kitops/pkg/lib/storage"
"kitops/pkg/output"
"os"
"path/filepath"
)

func RunBuild(ctx context.Context, options *buildOptions) error {
Expand Down Expand Up @@ -63,21 +64,23 @@ func RunBuild(ctx context.Context, options *buildOptions) error {
}
model.Layers = append(model.Layers, *layer)

modelStorePath := options.storageHome
repo := ""
tag := ""
if options.modelRef != nil {
repo = filepath.Join(options.modelRef.Registry, options.modelRef.Repository)
tag = options.modelRef.Reference
}
store := storage.NewLocalStore(modelStorePath, repo)
manifestDesc, err := store.SaveModel(ctx, model, tag)
storageHome := constants.StoragePath(options.configHome)
localStore, err := repo.NewLocalStore(storageHome, options.modelRef)
if err != nil {
return fmt.Errorf("failed to open local storage: %w", err)
}

manifestDesc, err := storage.SaveModel(ctx, localStore, model, tag)
if err != nil {
return err
}

for _, tag := range options.extraRefs {
if err := store.TagModel(ctx, *manifestDesc, tag); err != nil {
if err := localStore.Tag(ctx, *manifestDesc, tag); err != nil {
return err
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/build/cmd.go
Expand Up @@ -10,7 +10,7 @@ import (

"kitops/pkg/lib/constants"
"kitops/pkg/lib/filesystem"
"kitops/pkg/lib/storage"
"kitops/pkg/lib/repo"
"kitops/pkg/output"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -78,7 +78,7 @@ func (opts *buildOptions) complete(ctx context.Context, args []string) error {
opts.storageHome = constants.StoragePath(opts.configHome)

if opts.fullTagRef != "" {
modelRef, extraRefs, err := storage.ParseReference(opts.fullTagRef)
modelRef, extraRefs, err := repo.ParseReference(opts.fullTagRef)
if err != nil {
return fmt.Errorf("failed to parse reference %s: %w", opts.fullTagRef, err)
}
Expand Down
5 changes: 2 additions & 3 deletions pkg/cmd/export/cmd.go
Expand Up @@ -7,7 +7,6 @@ import (
"kitops/pkg/cmd/options"
"kitops/pkg/lib/constants"
"kitops/pkg/lib/repo"
"kitops/pkg/lib/storage"
"kitops/pkg/output"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -44,7 +43,7 @@ func (opts *exportOptions) complete(ctx context.Context, args []string) error {
return fmt.Errorf("default config path not set on command context")
}
opts.configHome = configHome
modelRef, extraTags, err := storage.ParseReference(args[0])
modelRef, extraTags, err := repo.ParseReference(args[0])
if err != nil {
return fmt.Errorf("failed to parse reference %s: %w", args[0], err)
}
Expand Down Expand Up @@ -112,7 +111,7 @@ func runCommand(opts *exportOptions) func(*cobra.Command, []string) {

func getStoreForRef(ctx context.Context, opts *exportOptions) (oras.Target, error) {
storageHome := constants.StoragePath(opts.configHome)
localStore, err := oci.New(storage.LocalStorePath(storageHome, opts.modelRef))
localStore, err := oci.New(repo.RepoPath(storageHome, opts.modelRef))
if err != nil {
return nil, fmt.Errorf("failed to read local storage: %s\n", err)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/list/cmd.go
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"kitops/pkg/cmd/options"
"kitops/pkg/lib/constants"
"kitops/pkg/lib/storage"
"kitops/pkg/lib/repo"
"kitops/pkg/output"
"os"
"text/tabwriter"
Expand All @@ -32,7 +32,7 @@ func (opts *listOptions) complete(ctx context.Context, args []string) error {
}
opts.configHome = configHome
if len(args) > 0 {
remoteRef, extraTags, err := storage.ParseReference(args[0])
remoteRef, extraTags, err := repo.ParseReference(args[0])
if err != nil {
return fmt.Errorf("invalid reference: %w", err)
}
Expand Down
79 changes: 7 additions & 72 deletions pkg/cmd/list/list.go
Expand Up @@ -5,15 +5,11 @@ package list

import (
"context"
"encoding/json"
"fmt"
"io/fs"
"kitops/pkg/artifact"
"kitops/pkg/lib/constants"
"kitops/pkg/lib/storage"
"kitops/pkg/lib/repo"
"math"
"os"
"path/filepath"
"strings"

ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand All @@ -26,15 +22,13 @@ const (

func listLocalKits(ctx context.Context, opts *listOptions) ([]string, error) {
storageRoot := constants.StoragePath(opts.configHome)
storeDirs, err := findRepos(storageRoot)
stores, err := repo.GetAllLocalStores(storageRoot)
if err != nil {
return nil, err
}

var allInfoLines []string
for _, storeDir := range storeDirs {
store := storage.NewLocalStore(storageRoot, storeDir)

for _, store := range stores {
infolines, err := listKits(ctx, store)
if err != nil {
return nil, err
Expand All @@ -44,56 +38,25 @@ func listLocalKits(ctx context.Context, opts *listOptions) ([]string, error) {
return allInfoLines, nil
}

func listKits(ctx context.Context, store storage.Store) ([]string, error) {
index, err := store.ParseIndexJson()
func listKits(ctx context.Context, store repo.LocalStorage) ([]string, error) {
index, err := store.GetIndex()
if err != nil {
return nil, err
}

var infolines []string
for _, manifestDesc := range index.Manifests {
manifest, err := getManifest(ctx, store, manifestDesc)
if err != nil {
return nil, err
}
if manifest.Config.MediaType != constants.ModelConfigMediaType {
continue
}
manifestConf, err := readManifestConfig(ctx, store, manifest)
manifest, config, err := repo.GetManifestAndConfig(ctx, store, manifestDesc)
if err != nil {
return nil, err
}
infoline := getManifestInfoLine(store.GetRepository(), manifestDesc, manifest, manifestConf)
infoline := getManifestInfoLine(store.GetRepo(), manifestDesc, manifest, config)
infolines = append(infolines, infoline)
}

return infolines, nil
}

func getManifest(ctx context.Context, store storage.Store, manifestDesc ocispec.Descriptor) (*ocispec.Manifest, error) {
manifestBytes, err := store.Fetch(ctx, manifestDesc)
if err != nil {
return nil, fmt.Errorf("failed to read manifest %s: %w", manifestDesc.Digest, err)
}
manifest := &ocispec.Manifest{}
if err := json.Unmarshal(manifestBytes, &manifest); err != nil {
return nil, fmt.Errorf("failed to parse manifest %s: %w", manifestDesc.Digest, err)
}
return manifest, nil
}

func readManifestConfig(ctx context.Context, store storage.Store, manifest *ocispec.Manifest) (*artifact.KitFile, error) {
configBytes, err := store.Fetch(ctx, manifest.Config)
if err != nil {
return nil, fmt.Errorf("failed to read config: %w", err)
}
config := &artifact.KitFile{}
if err := json.Unmarshal(configBytes, config); err != nil {
return nil, fmt.Errorf("failed to parse config: %w", err)
}
return config, nil
}

func getManifestInfoLine(repo string, desc ocispec.Descriptor, manifest *ocispec.Manifest, config *artifact.KitFile) string {
ref := desc.Annotations[ocispec.AnnotationRefName]
if ref == "" {
Expand Down Expand Up @@ -122,34 +85,6 @@ func getManifestInfoLine(repo string, desc ocispec.Descriptor, manifest *ocispec
return info
}

func findRepos(storePath string) ([]string, error) {
var indexPaths []string
err := filepath.WalkDir(storePath, func(file string, info fs.DirEntry, err error) error {
if err != nil {
return err
}
if info.Name() == "index.json" && !info.IsDir() {
dir := filepath.Dir(file)
relDir, err := filepath.Rel(storePath, dir)
if err != nil {
return err
}
if relDir == "." {
relDir = ""
}
indexPaths = append(indexPaths, relDir)
}
return nil
})
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("failed to read local storage: %w", err)
}
return indexPaths, nil
}

func formatBytes(i int64) string {
if i == 0 {
return "0 B"
Expand Down

0 comments on commit 0b9778a

Please sign in to comment.