-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd: Add kraft setup command #257
base: staging
Are you sure you want to change the base?
Conversation
|
a3aaa9b
to
603dcb3
Compare
Done, sorry 😆 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @StefanJum
Added some quick notes from my side.
One thing I don't get here is what setup
should be doing.
I was under the impression that it should set up the environment, like the config options and other os-specific options.
The installation I thought was handled by the install script:
https://get.kraftkit.sh
Also tagging @nderjung
cmd/kraft/setup/setup.go
Outdated
req := []string{ | ||
"build-essential", | ||
"libncurses-dev", | ||
"libyaml-dev", | ||
"flex", | ||
"git", | ||
"wget", | ||
"socat", | ||
"bison", | ||
"unzip", | ||
"uuid-runtime", | ||
"python3", | ||
"python3-setuptools", | ||
"python3-pip", | ||
"qemu-kvm", | ||
"qemu-system-x86", | ||
"sgabios", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think maybe we should restrict those by versions? Not sure.
At least a lower-bound we should set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these requirements actually necessary? I believe the list is now much smaller now. Plus this should be "switchable" the user may not necessarily want qemu :) so a VMM option, determination, should append this or prompt for it
Thanks, I'll check the comments. From what I understood Does the install script add all the requirements for building and running unikernels or just for building/running @nderjung please correct me if I'm wrong. |
ee6a206
to
2c3d9f3
Compare
Actually you are right. What I wanted to say is that maybe we should be kind-of merging these two together somehow. From my perspective when you first run a tool you should have all dependencies already solved. I would just add an extra check in the install script to ask "Do you want to install building and running dependencies" I'm fine either way. Let's see what Alex has to say |
2c3d9f3
to
b15cabe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @StefanJum. Thanks for putting this together.
To be inline with how logic is approached in the cmd/
directory, each subcommand program essentially calls functionality exposed by the "KraftKit framework". I think the setup
cmd should be similar and therefore the logic for actually performing the checks, running any installation, etc. should occur as an exposed API from a different package. The goal here is to keep the file cmd/setup/setup.go
as simple as possible.
Towards a re-usable API, i'd recommend starting simply and with something like the following:
cmd/setup/setup.go
:
import "kraftkit.sh/internal/setup"
type Setup struct {
OS string `long:"os" usage:"Force the host OS"`
Arch string `long:"arch" usage:"Force the architecture of the host"`
VMM string `long:"vmm" usage:"Force the use of a specific VMM on the host"`
PM string `long:"pm" usage:"Force the use of a specific package manager on the host"`
}
// [...]
var sopts []setup.SetupOption
if opts.OS != "" {
sopts = append(sopts, setup.WithOS(opts.WithOS))
}
// [...etc...]
if err := setup.Setup(ctx, ...sopts); err != nil {
return err
}
internal/setup/setup.go
:
type Setup struct {
arch *HostArch
os *HostOS
pm *HostPackageManager
vmm *HostVMM
}
func Setup(ctx context.Context, sopts ...SetupOption) error {
s := Setup{}
for _, opts := range sopts {
if err := opt(&s); err != nil {
return err
}
}
var err error
if s.arch == nil {
s.arch, err = DetectHostArch()
if err != nil {
return err
}
}
// [...]
}
internal/setup/options.go
:
// [...]
type SetupOption func(*Setup) error
func WithOS(os string) SetupOption {
// This should check if the provided `os` variable is valid in format and
// in support. E.g. providing `ubuntu` and `linux/ubuntu` should work,
// but perhaps providing `windows`, `windows/choco` would not.
}
Additionally, each os/distribution should be a "provider" following an implementation to the following abstract interface:
type HostPackageManager interface {
Install(context.Context, ...string) error
}
The above interface needs a bit more thought, as @craciunoiuc has mentioned, because versions need to be listed. I can imagine the following could be a way to provide the listing:
internal/setup/setup_ubuntu.go
:
var DistUbuntu = [...]HostPackage{
HostPackage{"package", GT, "1.0.0"},
};
That said, I would be surprised if there were no existing Go packages that do not do something similar to what we're trying to achieve.
Additional comments:
- Please can you use the updated copyright preamble, here is an example of what it looks like;
- Use
iostreams.G(ctx).Out
when redirecting information to the user viafmt.Fprintf
, this is the global access point toos.Stdout
, which keeps its configuration and possible redirection globally configurable; - Check
config.G(ctx).NoPrompt
to determine whether to prompt the user for questions, e.g.Would you like to continue? [Yn]
; - Use
kraftkit.sh/exec
for executing commands and not the built-inos/exec
package.
To address the comments by @craciunoiuc, the In my mind, following an installation from I also imagine an extension to import "kraftkit.sh/internal/setup"
// [...]
func main() {
// [...]
if isFirstSetup, _ := setup.IsFirstUse(ctx); isFirstSetup {
if err := setup.Setup(ctx); err != nil {
fmt.Printf("could not perform first-use setup: %v", err)
os.Exit(1)
}
}
// [...]
cmdfactory.Main(ctx)
} |
Yes, you are right. I forgot that many people actually pull the binary from the releases page. |
The `kraft setup` command will install the required dependencies for building and running unikernels. It will also check the virtualization support of the environment, check if we are running kraft from inside a container or a virtual machine and give a warning about enabling nested virtualization Signed-off-by: Stefan Jumarea <stefanjumarea02@gmail.com>
b15cabe
to
4014baa
Compare
@nderjung I did a quick refactoring based on your comments, let me know how it looks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @StefanJum, thanks for the update, I can see this is still WIP, however, see comments inline.
WithOS string `long:"with-os" usage:"Force the host OS"` | ||
WithArch string `long:"with-arch" usage:"Force the architecture of the host"` | ||
WithVMM string `long:"with-vmm" usage:"Force the use of a specific VMM on the host"` | ||
WithPM string `long:"with-pm" usage:"Force the use of a specific package manager on the host"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- WithOS string `long:"with-os" usage:"Force the host OS"`
- WithArch string `long:"with-arch" usage:"Force the architecture of the host"`
- WithVMM string `long:"with-vmm" usage:"Force the use of a specific VMM on the host"`
- WithPM string `long:"with-pm" usage:"Force the use of a specific package manager on the host"`
+ OS string `long:"os" usage:"Force the host OS"`
+ Arch string `long:"arch" usage:"Force the architecture of the host"`
+ VMM string `long:"vmm" usage:"Force the use of a specific VMM on the host"`
+ PM string `long:"pm" usage:"Force the use of a specific package manager on the host"`
return cmdfactory.New(&Setup{}, cobra.Command{ | ||
Short: "Setup the working environment for building and running unikernels", | ||
Use: "setup", | ||
Aliases: []string{"sup"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Aliases: []string{"sup"},
Short: "Setup the working environment for building and running unikernels", | ||
Use: "setup", | ||
Aliases: []string{"sup"}, | ||
Args: cmdfactory.MaxDirArgs(0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Args: cmdfactory.MaxDirArgs(0),
+ Args: cobra. NoArgs(),
# Setup the environment | ||
$ kraft setup`), | ||
Annotations: map[string]string{ | ||
"help:group": "build", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- "help:group": "build",
+ cmdfactory.AnnotationHelpGroup: "build",
sopts = append(sopts, setup.WithOS(opts.WithOS)) | ||
} else { | ||
sopts = append(sopts, setup.WithDetectHostOS()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- sopts = append(sopts, setup.WithOS(opts.WithOS))
- } else {
- sopts = append(sopts, setup.WithDetectHostOS())
- }
+ sopts = append(sopts, setup.WithOS(opts.OS))
+ }
WithOS string `long:"with-os" usage:"Force the host OS"` | ||
WithArch string `long:"with-arch" usage:"Force the architecture of the host"` | ||
WithVMM string `long:"with-vmm" usage:"Force the use of a specific VMM on the host"` | ||
WithPM string `long:"with-pm" usage:"Force the use of a specific package manager on the host"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- WithOS string `long:"with-os" usage:"Force the host OS"`
- WithArch string `long:"with-arch" usage:"Force the architecture of the host"`
- WithVMM string `long:"with-vmm" usage:"Force the use of a specific VMM on the host"`
- WithPM string `long:"with-pm" usage:"Force the use of a specific package manager on the host"`
+ os string
+ arch string
+ vmm string
+ pm string
func DoSetup(ctx context.Context, sopts ...SetupOption) error { | ||
s := Setup{} | ||
for _, opts := range sopts { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- func DoSetup(ctx context.Context, sopts ...SetupOption) error {
+ func Setup(ctx context.Context, sopts ...SetupOption) error {
s := Setup{}
+
for _, opts := range sopts {
func detect_arch() string { | ||
os_info, _ := host.Info() | ||
arch := os_info.KernelArch | ||
|
||
return arch | ||
} | ||
|
||
func detect_vmm() string { | ||
os_virt, role, _ := host.Virtualization() | ||
vmm := os_virt + "/" + role | ||
|
||
return vmm | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functions in Go are never snake_case
and are instead camelBack
.
Additionally, the host.Virtualization()
method is a nice find. Perhaps it's best to serialize all possible outputs into a global list of supported values.
func NotSupported(*Setup) error { | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- func NotSupported(*Setup) error {
- return nil
- }
+ const (
+ ErrNotSupportedVMM = errors.New("virtualization system not supported")
+ ErrNotSupportedPM = errors.New("package manager not supported")
+ ErrNotSupportedOS = errors.New("OS not supported")
+ )
(and place at the top of the file)
@@ -77,6 +78,7 @@ func New() *cobra.Command { | |||
cmd.AddCommand(ps.New()) | |||
cmd.AddCommand(rm.New()) | |||
cmd.AddCommand(run.New()) | |||
cmd.AddCommand(setup.New()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to the misc
section
The
kraft setup
command will install the required dependencies for building and running unikernels. It will also check the virtualization support of the environment, check if we are running kraft from inside a conainter or a virtual machine and give a warning about enabling nested virtualizationPrerequisite checklist
make fmt
on your commit series before opening this PR;Description of changes