Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions cmd/fl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,18 @@ import (
"context"
"log"
"math/rand"
"os"
"time"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/weaveworks-experiments/fl/internal/cmd"
)

func main() {
rand.Seed(time.Now().UnixNano())
ctx := context.Background()

cobra.OnInitialize(initConfig)

rootCmd := cmd.NewRootCmd()
if err := rootCmd.ExecuteContext(ctx); err != nil {
log.Fatal("failed executing root command")
app := cmd.NewApp()
if err := app.RunContext(ctx, os.Args); err != nil {
log.Fatalf("failed executing root command: %s", err)
}
}

func initConfig() {
viper.SetEnvPrefix("FL")
viper.AutomaticEnv()
}
28 changes: 10 additions & 18 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,28 @@ go 1.17

require (
github.com/moby/moby v20.10.14+incompatible
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.10.1
github.com/urfave/cli/v2 v2.4.0
github.com/weaveworks/flintlock/api v0.0.0-20220304105853-8fcb8aa2bafb
github.com/weaveworks/flintlock/client v0.0.0-20220304105853-8fcb8aa2bafb
github.com/yitsushi/macpot v1.0.2
go.uber.org/zap v1.21.0
google.golang.org/grpc v1.44.0
google.golang.org/grpc v1.45.0
gopkg.in/yaml.v2 v2.4.0
)

require (
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/testify v1.7.1 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461 // indirect
golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
)
126 changes: 18 additions & 108 deletions go.sum

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions internal/cmd/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cmd

import (
"github.com/urfave/cli/v2"

"github.com/weaveworks-experiments/fl/internal/cmd/microvm"
"github.com/weaveworks-experiments/fl/pkg/logging"
)

const (
logLevelFlag = "log-level"
)

func NewApp() *cli.App {
app := &cli.App{
Name: "fl",
Usage: "The experimental cli for flintlock",
Commands: []*cli.Command{},
Flags: []cli.Flag{
&cli.StringFlag{
Name: logLevelFlag,
Usage: "set the level of the debugger",
Value: "debug",
},
},
Before: func(ctx *cli.Context) error {
logLevelFlag := ctx.String(logLevelFlag)
err := logging.Configure(logLevelFlag)
if err != nil {
return err
}

return nil
},
}

versionCmd := newVersionCommand()
app.Commands = append(app.Commands, versionCmd)

microvmCmd := microvm.NewCommand()
app.Commands = append(app.Commands, microvmCmd)

return app
}
160 changes: 127 additions & 33 deletions internal/cmd/microvm/create.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package microvm

import (
"github.com/moby/moby/pkg/namesgenerator"
"github.com/spf13/cobra"
"errors"
"fmt"

"github.com/urfave/cli/v2"
"go.uber.org/zap"

"github.com/weaveworks-experiments/fl/pkg/app"
"github.com/weaveworks-experiments/fl/pkg/flags"
)

const (
Expand All @@ -18,44 +19,137 @@ const (
defaultRootImage = "ghcr.io/weaveworks/capmvm-kubernetes:1.21.8"
)

func newCreateCommand() *cobra.Command {
func newCreateCommand() *cli.Command {
createInput := &app.CreateInput{}
networkInterfaces := &cli.StringSlice{}
metadataFromFile := &cli.StringSlice{}

cmd := &cli.Command{
Name: "create",
Usage: "create a new microvm",
Before: func(ctx *cli.Context) error {
if createInput.Name != "" && createInput.NameAutogenerate {
return errors.New("only one of --name or --name-autoegenarate can be specified")
}

if createInput.Name == "" && !createInput.NameAutogenerate {
return errors.New("you must supply one of --name or --name-autoegenarate")
}

cmd := &cobra.Command{
Use: "create",
Short: "create a new microvm",
PreRun: func(cmd *cobra.Command, args []string) {
flags.BindFlags(cmd)
return nil
},
Run: func(c *cobra.Command, _ []string) {
Action: func(ctx *cli.Context) error {
a := app.New(zap.S().With("action", "create"))
if err := a.Create(c.Context(), createInput); err != nil {
zap.S().Errorw("failed creating microvm", "error", err)
if err := a.Create(ctx.Context, createInput); err != nil {
return fmt.Errorf("creating microvm: %s", err)
}

return nil
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "host",
Usage: "the flintlock host to create the microvm on",
Destination: &createInput.Host,
Required: true,
},
&cli.StringFlag{
Name: "name",
Usage: "the name of the microvm, cannot be specified if using name-autogenerate",
Destination: &createInput.Name,
},
&cli.BoolFlag{
Name: "name-autogenerate",
Usage: "if true a name is autogenerated for the microvm",
Value: false,
Destination: &createInput.NameAutogenerate,
},
&cli.StringFlag{
Name: "namespace",
Usage: "the namespace for the microvm",
Destination: &createInput.Namespace,
Value: defaultNamespace,
},
&cli.IntFlag{
Name: "vcpu",
Usage: "the number of vcpus",
Value: defaultVCPU,
Destination: &createInput.VCPU,
},
&cli.IntFlag{
Name: "memory",
Usage: "the memory in mb",
Value: defaultMemoryMb,
Destination: &createInput.MemoryInMb,
},
&cli.StringFlag{
Name: "kernel-image",
Usage: "the image to use for the kernel",
Destination: &createInput.KernelImage,
Value: defaultKernelImage,
},
&cli.BoolFlag{
Name: "add-netconf",
Usage: "automatically add network configuration to the kernel cmd line",
Destination: &createInput.KernelAddNetConf,
Value: true,
},
&cli.StringFlag{
Name: "kernel-filename",
Usage: "name of the kernel file in the image",
Destination: &createInput.KernelFileName,
Value: defaultKernelFile,
},
&cli.StringFlag{
Name: "root-image",
Usage: "the image to use for the root volume",
Destination: &createInput.RootImage,
Value: defaultRootImage,
},
&cli.StringFlag{
Name: "initrd-image",
Usage: "the image to use for the initial ramdisk",
Destination: &createInput.InitrdImage,
},
&cli.StringFlag{
Name: "initrd-filename",
Usage: "name of the file in the image to use for the initial ramdisk",
Destination: &createInput.InitrdFilename,
},
&cli.StringSliceFlag{
Name: "network-interface",
Usage: "specify the network interfaces to attach. In the following format: name:type:[macaddress]:[ipaddress]",
Destination: networkInterfaces,
},
&cli.StringSliceFlag{
Name: "metadata-from-file",
Usage: "specify metadata to be available to your microvm. In the following format key=pathtofile",
Destination: metadataFromFile,
},
&cli.StringFlag{
Name: "metadata-hostname",
Usage: "the hostname of the the microvm",
Destination: &createInput.Metadata.Hostname,
},
&cli.StringFlag{
Name: "metadata-ssh-key-file",
Usage: "an ssh key to use",
Destination: &createInput.Metadata.SSHKeyFile,
},
&cli.BoolFlag{
Name: "metadata-resolvd-fix",
Usage: "include a systemd-resolvd fix for container root volumes",
Destination: &createInput.Metadata.ResolvdFix,
Value: true,
},
&cli.StringFlag{
Name: "metadata-final-message",
Usage: "set the cloud-init final message",
Destination: &createInput.Metadata.Message,
},
},
}

cmd.Flags().StringVar(&createInput.Host, "host", "", "the flintlock host to create the microvm on")
cmd.MarkFlagRequired("host")

defaultName := namesgenerator.GetRandomName(10)
cmd.Flags().StringVar(&createInput.Name, "name", defaultName, "the name of the microvm, auto-generated if not supplied")
cmd.Flags().StringVar(&createInput.Namespace, "namespace", defaultNamespace, "the namespace for the microvm")
cmd.Flags().IntVar(&createInput.VCPU, "vcpu", defaultVCPU, "the number of vcpus")
cmd.Flags().IntVar(&createInput.MemoryInMb, "memory", defaultMemoryMb, "the memory in mb")
cmd.Flags().StringVar(&createInput.KernelImage, "kernel-image", defaultKernelImage, "the image to use for the kernel")
cmd.Flags().BoolVar(&createInput.KernelAddNetConf, "add-netconf", true, "automatically add network configuration to the kernel cmd line")
cmd.Flags().StringVar(&createInput.KernelFileName, "kernel-filename", defaultKernelFile, "name of the kernel file in the image")
cmd.Flags().StringVar(&createInput.RootImage, "root-image", defaultRootImage, "the image to use for the root volume")
cmd.Flags().StringVar(&createInput.InitrdImage, "initrd-image", "", "the image to use for the initial ramdisk")
cmd.Flags().StringVar(&createInput.InitrdFilename, "initrd-filename", "", "name of the file in the image to use for the initial ramdisk")
cmd.Flags().StringSliceVar(&createInput.NetworkInterfaces, "network-interface", nil, "specify the network interfaces to attach. In the following format: name:type:[macaddress]:[ipaddress]")
cmd.Flags().StringSliceVar(&createInput.MetadataFromFile, "metadata-from-file", nil, "specify metadata to be available to your microvm. In the following format key=pathtofile")
cmd.Flags().StringVar(&createInput.Metadata.Hostname, "metadata-hostname", "", "the hostname of the the microvm")
cmd.Flags().StringVar(&createInput.Metadata.SSHKeyFile, "metadata-ssh-key-file", "", "an ssh key to use")
cmd.Flags().BoolVar(&createInput.Metadata.ResolvdFix, "metadata-resolvd-fix", true, "include a systemd-resolvd fix for container root volumes")
cmd.Flags().StringVar(&createInput.Metadata.Message, "metadata-final-message", "", "set the cloud-init final message")

//TODO: additional command line args for kernel
//TODO: add additional volumes

Expand Down
44 changes: 25 additions & 19 deletions internal/cmd/microvm/delete.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package microvm

import (
"github.com/spf13/cobra"
"errors"
"fmt"

"github.com/urfave/cli/v2"
"go.uber.org/zap"

"github.com/weaveworks-experiments/fl/pkg/app"
"github.com/weaveworks-experiments/fl/pkg/flags"
)

const (
Expand All @@ -15,31 +17,35 @@ fl microvm delete --host host1:9090 01FZZJV1XD2FKH2KY0NDB4MBRQ
`
)

func newDeleteCommand() *cobra.Command {
func newDeleteCommand() *cli.Command {
deleteInput := &app.DeleteInput{}

cmd := &cobra.Command{
Use: "delete",
Short: "delete a microvm from a host",
Example: deleteExamples,
Args: cobra.ExactValidArgs(1),
PreRun: func(cmd *cobra.Command, args []string) {
flags.BindFlags(cmd)
},
Run: func(c *cobra.Command, args []string) {
deleteInput.UID = args[0]
cmd := &cli.Command{
Name: "delete",
Usage: "delete a microvm from a host",
Action: func(ctx *cli.Context) error {
if ctx.Args().Len() == 0 {
return errors.New("you must supply the uid as an argument")
}
deleteInput.UID = ctx.Args().Get(0)

a := app.New(zap.S().With("action", "delete"))
err := a.Delete(c.Context(), deleteInput)
err := a.Delete(ctx.Context, deleteInput)
if err != nil {
zap.S().Errorw("failed deleting microvm", "error", err)
return
return fmt.Errorf("deleting microvm: %w", err)
}

return nil
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "host",
Usage: "the flintlock host to delete the microvm on",
Destination: &deleteInput.Host,
Required: true,
},
},
}

cmd.Flags().StringVar(&deleteInput.Host, "host", "", "the flintlock host to get the microvms from")
cmd.MarkFlagRequired("host")

return cmd
}
Loading