Skip to content

Commit

Permalink
feat(pkg): Introduce --push flag (#946)
Browse files Browse the repository at this point in the history
Reviewed-by: Cezar Craciunoiu <cezar.craciunoiu@unikraft.io>
Approved-by: Cezar Craciunoiu <cezar.craciunoiu@unikraft.io>
  • Loading branch information
craciunoiuc committed Oct 27, 2023
2 parents 6e4bca6 + 1767979 commit 0d09e39
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 36 deletions.
4 changes: 3 additions & 1 deletion internal/cli/kraft/pkg/packager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package pkg
import (
"context"
"fmt"

"kraftkit.sh/pack"
)

// packager is an interface for defining different mechanisms to perform a
Expand All @@ -24,7 +26,7 @@ type packager interface {
Packagable(context.Context, *PkgOptions, ...string) (bool, error)

// Pack performs the packaging based on the determined implementation.
Pack(context.Context, *PkgOptions, ...string) error
Pack(context.Context, *PkgOptions, ...string) ([]pack.Package, error)
}

// packagers is the list of built-in packagers which are checked
Expand Down
48 changes: 28 additions & 20 deletions internal/cli/kraft/pkg/packager_kraftfile_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (p *packagerKraftfileRuntime) Packagable(ctx context.Context, opts *PkgOpti
}

// Pack implements packager.
func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, args ...string) error {
func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, args ...string) ([]pack.Package, error) {
var err error
var targ target.Target

Expand All @@ -70,18 +70,18 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a

switch {
case len(targets) == 0:
return fmt.Errorf("could not detect any project targets based on plat=\"%s\" arch=\"%s\"", opts.Platform, opts.Architecture)
return nil, fmt.Errorf("could not detect any project targets based on plat=\"%s\" arch=\"%s\"", opts.Platform, opts.Architecture)

case len(targets) == 1:
targ = targets[0]

case config.G[config.KraftKit](ctx).NoPrompt && len(targets) > 1:
return fmt.Errorf("could not determine what to run based on provided CLI arguments")
return nil, fmt.Errorf("could not determine what to run based on provided CLI arguments")

default:
targ, err = target.Select(targets)
if err != nil {
return fmt.Errorf("could not select target: %v", err)
return nil, fmt.Errorf("could not select target: %v", err)
}
}
}
Expand Down Expand Up @@ -112,16 +112,16 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a

packs, err := opts.pm.Catalog(ctx, append(qopts, packmanager.WithUpdate(false))...)
if err != nil {
return fmt.Errorf("could not query catalog: %w", err)
return nil, fmt.Errorf("could not query catalog: %w", err)
} else if len(packs) == 0 {
// Try again with a remote update request. Save this to qopts in case we
// need to call `Catalog` again.
qopts = append(qopts, packmanager.WithUpdate(true))
packs, err = opts.pm.Catalog(ctx, qopts...)
if err != nil {
return fmt.Errorf("could not query catalog: %w", err)
return nil, fmt.Errorf("could not query catalog: %w", err)
} else if len(packs) == 0 {
return fmt.Errorf("coud not find runtime '%s'", opts.project.Runtime().Name())
return nil, fmt.Errorf("coud not find runtime '%s'", opts.project.Runtime().Name())
}
}

Expand All @@ -133,13 +133,13 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a
if opts.Architecture == "" {
opts.Architecture, err = ukarch.HostArchitecture()
if err != nil {
return fmt.Errorf("could not get host architecture: %w", err)
return nil, fmt.Errorf("could not get host architecture: %w", err)
}
}
if opts.Platform == "" {
plat, _, err := platform.Detect(ctx)
if err != nil {
return fmt.Errorf("could not get host platform: %w", err)
return nil, fmt.Errorf("could not get host platform: %w", err)
}

opts.Platform = plat.String()
Expand All @@ -152,11 +152,11 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a

packs, err = opts.pm.Catalog(ctx, qopts...)
if err != nil {
return fmt.Errorf("could not query catalog: %w", err)
return nil, fmt.Errorf("could not query catalog: %w", err)
} else if len(packs) == 0 {
return fmt.Errorf("coud not find runtime '%s'", opts.project.Runtime().Name())
return nil, fmt.Errorf("coud not find runtime '%s'", opts.project.Runtime().Name())
} else if len(packs) > 1 {
return fmt.Errorf("could not find runtime: too many options")
return nil, fmt.Errorf("could not find runtime: too many options")
}

log.G(ctx).
Expand All @@ -169,7 +169,7 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a
// pulling and extracting the identified package.
tempDir, err := os.MkdirTemp("", "kraft-pkg-")
if err != nil {
return fmt.Errorf("could not create temporary directory: %w", err)
return nil, fmt.Errorf("could not create temporary directory: %w", err)
}

defer func() {
Expand Down Expand Up @@ -201,19 +201,19 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a
paraprogress.WithFailFast(true),
)
if err != nil {
return err
return nil, err
}

if err := paramodel.Start(); err != nil {
return err
return nil, err
}

// Crucially, the catalog should return an interface that also implements
// target.Target. This demonstrates that the implementing package can
// resolve application kernels.
targ, ok := packs[0].(target.Target)
if !ok {
return fmt.Errorf("package does not convert to target")
return nil, fmt.Errorf("package does not convert to target")
}

// If no arguments have been specified, use the ones which are default and
Expand All @@ -224,9 +224,10 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a

cmdShellArgs, err := shellwords.Parse(strings.Join(opts.Args, " "))
if err != nil {
return err
return nil, err
}

var result []pack.Package
norender := log.LoggerTypeFromString(config.G[config.KraftKit](ctx).Log.Type) != log.FANCY

model, err := processtree.NewProcessTree(
Expand Down Expand Up @@ -254,17 +255,24 @@ func (p *packagerKraftfileRuntime) Pack(ctx context.Context, opts *PkgOptions, a
)
}

if _, err := opts.pm.Pack(ctx, targ, popts...); err != nil {
more, err := opts.pm.Pack(ctx, targ, popts...)
if err != nil {
return err
}

result = append(result, more...)

return nil
},
),
)
if err != nil {
return err
return nil, err
}

if err := model.Start(); err != nil {
return nil, err
}

return model.Start()
return result, nil
}
32 changes: 21 additions & 11 deletions internal/cli/kraft/pkg/packager_kraftfile_unikraft.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/mattn/go-shellwords"
"kraftkit.sh/config"
"kraftkit.sh/log"
"kraftkit.sh/pack"
"kraftkit.sh/packmanager"
"kraftkit.sh/tui/multiselect"
"kraftkit.sh/tui/processtree"
Expand Down Expand Up @@ -43,7 +44,7 @@ func (p *packagerKraftfileUnikraft) Packagable(ctx context.Context, opts *PkgOpt
}

// Build implements packager.
func (p *packagerKraftfileUnikraft) Pack(ctx context.Context, opts *PkgOptions, args ...string) error {
func (p *packagerKraftfileUnikraft) Pack(ctx context.Context, opts *PkgOptions, args ...string) ([]pack.Package, error) {
var err error

var tree []*processtree.ProcessTreeItem
Expand All @@ -58,16 +59,18 @@ func (p *packagerKraftfileUnikraft) Pack(ctx context.Context, opts *PkgOptions,
if len(selected) > 1 && !config.G[config.KraftKit](ctx).NoPrompt {
selected, err = multiselect.MultiSelect[target.Target]("select what to package", opts.project.Targets()...)
if err != nil {
return err
return nil, err
}
}

if len(selected) == 0 {
return fmt.Errorf("nothing selected to package")
return nil, fmt.Errorf("nothing selected to package")
}

i := 0

var result []pack.Package

for _, targ := range selected {
// See: https://github.com/golang/go/wiki/CommonMistakes#using-reference-to-loop-iterator-variable
targ := targ
Expand All @@ -82,7 +85,7 @@ func (p *packagerKraftfileUnikraft) Pack(ctx context.Context, opts *PkgOptions,

cmdShellArgs, err := shellwords.Parse(strings.Join(opts.Args, " "))
if err != nil {
return err
return nil, err
}

// When i > 0, we have already applied the merge strategy. Now, for all
Expand Down Expand Up @@ -112,10 +115,13 @@ func (p *packagerKraftfileUnikraft) Pack(ctx context.Context, opts *PkgOptions,
)
}

if _, err := opts.pm.Pack(ctx, targ, popts...); err != nil {
more, err := opts.pm.Pack(ctx, targ, popts...)
if err != nil {
return err
}

result = append(result, more...)

return nil
},
))
Expand All @@ -126,13 +132,13 @@ func (p *packagerKraftfileUnikraft) Pack(ctx context.Context, opts *PkgOptions,
if len(tree) == 0 {
switch true {
case len(opts.Target) > 0:
return fmt.Errorf("no matching targets found for: %s", opts.Target)
return nil, fmt.Errorf("no matching targets found for: %s", opts.Target)
case len(opts.Architecture) > 0 && len(opts.Platform) == 0:
return fmt.Errorf("no matching targets found for architecture: %s", opts.Architecture)
return nil, fmt.Errorf("no matching targets found for architecture: %s", opts.Architecture)
case len(opts.Architecture) == 0 && len(opts.Platform) > 0:
return fmt.Errorf("no matching targets found for platform: %s", opts.Platform)
return nil, fmt.Errorf("no matching targets found for platform: %s", opts.Platform)
default:
return fmt.Errorf("no matching targets found for: %s/%s", opts.Platform, opts.Architecture)
return nil, fmt.Errorf("no matching targets found for: %s/%s", opts.Platform, opts.Architecture)
}
}

Expand All @@ -145,8 +151,12 @@ func (p *packagerKraftfileUnikraft) Pack(ctx context.Context, opts *PkgOptions,
tree...,
)
if err != nil {
return err
return nil, err
}

if err := model.Start(); err != nil {
return nil, err
}

return model.Start()
return result, nil
}
52 changes: 48 additions & 4 deletions internal/cli/kraft/pkg/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"fmt"
"os"
"strings"

"github.com/MakeNowJust/heredoc"
"github.com/spf13/cobra"
Expand All @@ -16,6 +17,7 @@ import (
"kraftkit.sh/log"
"kraftkit.sh/machine/platform"
"kraftkit.sh/pack"
"kraftkit.sh/tui/paraprogress"
"kraftkit.sh/tui/selection"
"kraftkit.sh/unikraft/app"

Expand Down Expand Up @@ -43,6 +45,7 @@ type PkgOptions struct {
NoKConfig bool `local:"true" long:"no-kconfig" usage:"Do not include target .config as metadata"`
Output string `local:"true" long:"output" short:"o" usage:"Save the package at the following output"`
Platform string `local:"true" long:"plat" short:"p" usage:"Filter the creation of the package by platform of known targets"`
Push bool `local:"true" long:"push" short:"P" usage:"Push the package on if successfully packaged"`
Rootfs string `local:"true" long:"rootfs" usage:"Specify a path to use as root file system (can be volume or initramfs)"`
Target string `local:"true" long:"target" short:"t" usage:"Package a particular known target"`

Expand Down Expand Up @@ -190,7 +193,7 @@ func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
)
}

var pack packager
var pkgr packager

packagers := packagers()

Expand All @@ -204,7 +207,7 @@ func (opts *PkgOptions) Run(ctx context.Context, args []string) error {

capable, err := candidate.Packagable(ctx, opts, args...)
if capable && err == nil {
pack = candidate
pkgr = candidate
break
}

Expand All @@ -214,17 +217,58 @@ func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
Trace("incompatbile")
}

if pack == nil {
if pkgr == nil {
return fmt.Errorf("could not determine what or how to package from the given context")
}

if err := opts.buildRootfs(ctx); err != nil {
return fmt.Errorf("could not build rootfs: %w", err)
}

if err := pack.Pack(ctx, opts, args...); err != nil {
packs, err := pkgr.Pack(ctx, opts, args...)
if err != nil {
return fmt.Errorf("could not package: %w", err)
}

if opts.Push {
var processes []*paraprogress.Process

for _, p := range packs {
p := p

var title []string
for _, column := range p.Columns() {
if len(column.Value) > 12 {
continue
}

title = append(title, column.Value)
}

processes = append(processes, paraprogress.NewProcess(
fmt.Sprintf("pushing %s:%s (%s)", p.Name(), p.Version(), strings.Join(title, ", ")),
func(ctx context.Context, w func(progress float64)) error {
return p.Push(
ctx,
pack.WithPushProgressFunc(w),
)
},
))
}

paramodel, err := paraprogress.NewParaProgress(
ctx,
processes,
paraprogress.IsParallel(false),
paraprogress.WithRenderer(log.LoggerTypeFromString(config.G[config.KraftKit](ctx).Log.Type) != log.FANCY),
paraprogress.WithFailFast(true),
)
if err != nil {
return err
}

return paramodel.Start()
}

return nil
}

0 comments on commit 0d09e39

Please sign in to comment.