Skip to content

Commit

Permalink
refactor(pkg): Migrate the procedures in Run to Pkg (#963)
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 Nov 1, 2023
2 parents 99cb86e + 2fa9ace commit 8b365e0
Showing 1 changed file with 86 additions and 79 deletions.
165 changes: 86 additions & 79 deletions internal/cli/kraft/pkg/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,95 +57,32 @@ type PkgOptions struct {
}

// Pkg a Unikraft project.
func Pkg(ctx context.Context, opts *PkgOptions, args ...string) error {
func Pkg(ctx context.Context, opts *PkgOptions, args ...string) ([]pack.Package, error) {
var err error

if opts == nil {
opts = &PkgOptions{}
}

return opts.Run(ctx, args)
}

func NewCmd() *cobra.Command {
cmd, err := cmdfactory.New(&PkgOptions{}, cobra.Command{
Short: "Package and distribute Unikraft unikernels and their dependencies",
Use: "pkg [FLAGS] [SUBCOMMAND|DIR]",
Args: cmdfactory.MaxDirArgs(1),
Long: heredoc.Docf(`
Package and distribute Unikraft unikernels and their dependencies.
With %[1]skraft pkg%[1]s you are able to turn output artifacts from %[1]skraft build%[1]s
into a distributable archive ready for deployment. At the same time,
%[1]skraft pkg%[1]s allows you to manage these archives: pulling, pushing, or
adding them to a project.
The default behaviour of %[1]skraft pkg%[1]s is to package a project. Given no
arguments, you will be guided through interactive mode.
`, "`"),
Example: heredoc.Doc(`
# Package a project as an OCI archive and embed the target's KConfig.
$ kraft pkg --as oci --name unikraft.org/nginx:latest`),
Annotations: map[string]string{
cmdfactory.AnnotationHelpGroup: "pkg",
},
})
if err != nil {
panic(err)
}

cmd.AddCommand(list.NewCmd())
cmd.AddCommand(pull.NewCmd())
cmd.AddCommand(push.NewCmd())
cmd.AddCommand(remove.NewCmd())
cmd.AddCommand(source.NewCmd())
cmd.AddCommand(unsource.NewCmd())
cmd.AddCommand(update.NewCmd())

cmd.Flags().Var(
cmdfactory.NewEnumFlag[packmanager.MergeStrategy](
append(packmanager.MergeStrategies(), packmanager.StrategyPrompt),
packmanager.StrategyPrompt,
),
"strategy",
"When a package of the same name exists, use this strategy when applying targets.",
)

return cmd
}

func (opts *PkgOptions) Pre(cmd *cobra.Command, args []string) error {
ctx, err := packmanager.WithDefaultUmbrellaManagerInContext(cmd.Context())
if err != nil {
return err
}

cmd.SetContext(ctx)

opts.Strategy = packmanager.MergeStrategy(cmd.Flag("strategy").Value.String())

return nil
}

func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
var err error
if len(args) == 0 {
opts.Workdir, err = os.Getwd()
if err != nil {
return err
return nil, err
}
} else {
} else if len(opts.Workdir) == 0 {
opts.Workdir = args[0]
}

if opts.Name == "" {
return fmt.Errorf("cannot package without setting --name")
return nil, fmt.Errorf("cannot package without setting --name")
}

if (len(opts.Architecture) > 0 || len(opts.Platform) > 0) && len(opts.Target) > 0 {
return fmt.Errorf("the `--arch` and `--plat` options are not supported in addition to `--target`")
return nil, fmt.Errorf("the `--arch` and `--plat` options are not supported in addition to `--target`")
}

if config.G[config.KraftKit](ctx).NoPrompt && opts.Strategy == packmanager.StrategyPrompt {
return fmt.Errorf("cannot mix --strategy=prompt when --no-prompt is enabled in settings")
return nil, fmt.Errorf("cannot mix --strategy=prompt when --no-prompt is enabled in settings")
}

opts.Platform = platform.PlatformByName(opts.Platform).String()
Expand All @@ -154,7 +91,7 @@ func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
// Switch the package manager the desired format for this target
opts.pm, err = packmanager.G(ctx).From(pack.PackageFormat(opts.Format))
if err != nil {
return err
return nil, err
}
} else {
opts.pm = packmanager.G(ctx)
Expand All @@ -170,15 +107,15 @@ func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
packmanager.MergeStrategies()...,
)
if err != nil {
return err
return nil, err
}

opts.Strategy = *strategy
}

switch opts.Strategy {
case packmanager.StrategyExit:
return fmt.Errorf("package already exists and merge strategy set to exit on conflict")
return nil, fmt.Errorf("package already exists and merge strategy set to exit on conflict")

// Set the merge strategy as an option that is then passed to the
// package manager.
Expand Down Expand Up @@ -218,16 +155,16 @@ func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
}

if pkgr == nil {
return fmt.Errorf("could not determine what or how to package from the given context")
return nil, 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)
return nil, fmt.Errorf("could not build rootfs: %w", err)
}

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

if opts.Push {
Expand Down Expand Up @@ -264,10 +201,80 @@ func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
paraprogress.WithFailFast(true),
)
if err != nil {
return err
return packs, err
}

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

return packs, nil
}

func NewCmd() *cobra.Command {
cmd, err := cmdfactory.New(&PkgOptions{}, cobra.Command{
Short: "Package and distribute Unikraft unikernels and their dependencies",
Use: "pkg [FLAGS] [SUBCOMMAND|DIR]",
Args: cmdfactory.MaxDirArgs(1),
Long: heredoc.Docf(`
Package and distribute Unikraft unikernels and their dependencies.
With %[1]skraft pkg%[1]s you are able to turn output artifacts from %[1]skraft build%[1]s
into a distributable archive ready for deployment. At the same time,
%[1]skraft pkg%[1]s allows you to manage these archives: pulling, pushing, or
adding them to a project.
The default behaviour of %[1]skraft pkg%[1]s is to package a project. Given no
arguments, you will be guided through interactive mode.
`, "`"),
Example: heredoc.Doc(`
# Package a project as an OCI archive and embed the target's KConfig.
$ kraft pkg --as oci --name unikraft.org/nginx:latest`),
Annotations: map[string]string{
cmdfactory.AnnotationHelpGroup: "pkg",
},
})
if err != nil {
panic(err)
}

cmd.AddCommand(list.NewCmd())
cmd.AddCommand(pull.NewCmd())
cmd.AddCommand(push.NewCmd())
cmd.AddCommand(remove.NewCmd())
cmd.AddCommand(source.NewCmd())
cmd.AddCommand(unsource.NewCmd())
cmd.AddCommand(update.NewCmd())

cmd.Flags().Var(
cmdfactory.NewEnumFlag[packmanager.MergeStrategy](
append(packmanager.MergeStrategies(), packmanager.StrategyPrompt),
packmanager.StrategyPrompt,
),
"strategy",
"When a package of the same name exists, use this strategy when applying targets.",
)

return cmd
}

func (opts *PkgOptions) Pre(cmd *cobra.Command, args []string) error {
ctx, err := packmanager.WithDefaultUmbrellaManagerInContext(cmd.Context())
if err != nil {
return err
}

cmd.SetContext(ctx)

opts.Strategy = packmanager.MergeStrategy(cmd.Flag("strategy").Value.String())

return nil
}

func (opts *PkgOptions) Run(ctx context.Context, args []string) error {
if _, err := Pkg(ctx, opts, args...); err != nil {
return fmt.Errorf("could not package: %w", err)
}

return nil
Expand Down

0 comments on commit 8b365e0

Please sign in to comment.