Skip to content

Commit

Permalink
feat(manifest): Introduce tarball manifest provider
Browse files Browse the repository at this point in the history
This provider allows for supplying sources which represent
paths to a tarball.  For example:

```yaml
unikraft:
  source: ./unikraft.tar.gz

libraries:
  lwip:
    source: ./lib-lwip.tar.gz
```

Signed-off-by: Alexander Jung <alex@unikraft.io>
  • Loading branch information
nderjung committed Jan 8, 2025
1 parent 74a274b commit 7913826
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
11 changes: 11 additions & 0 deletions manifest/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ func NewProvider(ctx context.Context, path string, mopts ...ManifestOption) (Pro
return provider, nil
}

log.G(ctx).WithFields(logrus.Fields{
"path": path,
}).Trace("trying tarball provider")
provider, err = NewTarballProvider(ctx, path, mopts...)
if err == nil {
log.G(ctx).WithFields(logrus.Fields{
"path": path,
}).Trace("using tarball provider")
return provider, nil
}

// First attempt to detect whether the provided input is a Git repository. If
// it is, it could potentially be from GitHub as well.
log.G(ctx).WithFields(logrus.Fields{
Expand Down
117 changes: 117 additions & 0 deletions manifest/tarball.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2022, Unikraft GmbH and The KraftKit Authors.
// Licensed under the BSD-3-Clause License (the "License").
// You may not use this file except in compliance with the License.

package manifest

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

"kraftkit.sh/archive"
"kraftkit.sh/pack"
"kraftkit.sh/unikraft"
"kraftkit.sh/unikraft/app"
)

type TarballProvider struct {
typ unikraft.ComponentType
name string
path string
mopts *ManifestOptions
}

func NewTarballProvider(ctx context.Context, path string, opts ...ManifestOption) (Provider, error) {
if ok, err := archive.IsTarGz(path); !ok {
return nil, fmt.Errorf("'%s' is not a tarball: %s: %w", path, err)

Check failure on line 30 in manifest/tarball.go

View workflow job for this annotation

GitHub Actions / go

printf: fmt.Errorf format %w reads arg #3, but call has 2 args (govet)
}

// Determine the type preemptively
n := strings.TrimSuffix(path, ".tar.gz")
n = filepath.Base(n)
t, n, _, err := unikraft.GuessTypeNameVersion(n)
if err != nil || t == unikraft.ComponentTypeUnknown {
for _, f := range app.DefaultFileNames {
if f, err := os.Stat(filepath.Join(path, f)); err == nil && f.Size() > 0 {
t = unikraft.ComponentTypeApp
break
}
}
}

if t == unikraft.ComponentTypeUnknown {
return nil, fmt.Errorf("unknown type for tarball: %s", path)
}

return &TarballProvider{
typ: t,
name: n,
path: path,
mopts: NewManifestOptions(opts...),
}, nil
}

func (provider TarballProvider) Manifests() ([]*Manifest, error) {
return []*Manifest{
{
Type: provider.typ,
Name: provider.name,
Provider: provider,
Origin: provider.path,
Channels: []ManifestChannel{
{
Name: "default",
Default: true,
Resource: provider.path,
},
},
},
}, nil
}

func (provider TarballProvider) PullManifest(ctx context.Context, manifest *Manifest, opts ...pack.PullOption) error {
popts, err := pack.NewPullOptions(opts...)
if err != nil {
return err
}

if len(popts.Workdir()) == 0 {
return fmt.Errorf("cannot pull without without working directory")
}

// The directory provider only has one channel, exploit this knowledge
if len(manifest.Channels) != 1 {
return fmt.Errorf("cannot determine channel for directory provider")
}

local, err := unikraft.PlaceComponent(
popts.Workdir(),
manifest.Type,
manifest.Name,
)
if err != nil {
return fmt.Errorf("could not place component package: %s", err)
}

if err := archive.UntarGz(provider.path, local, archive.StripIfSingleTopLevelDir()); err != nil {
return fmt.Errorf("could not untar: %s: %w", provider.path, err)
}

return nil
}

func (provider TarballProvider) DeleteManifest(context.Context) error {
return nil
}

func (provider TarballProvider) String() string {
return "tarball"
}

func (provider TarballProvider) MarshalJSON() ([]byte, error) {
return []byte(`"tarball"`), nil
}

0 comments on commit 7913826

Please sign in to comment.