func main() { repo := util.NewRepo() app := cli.NewApp() app.Name = "capstan" app.Version = VERSION app.Usage = "pack, ship, and run applications in light-weight VMs" app.Commands = []cli.Command{ { Name: "info", Usage: "show disk image information", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan info [image-file]") return } image := c.Args()[0] cmd.Info(image) }, }, { Name: "push", Usage: "push an image to a repository", Action: func(c *cli.Context) { if len(c.Args()) != 2 { fmt.Println("usage: capstan push [image-name] [image-file]") return } err := repo.PushImage(c.Args()[0], c.Args()[1]) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "pull", Usage: "pull an image from a repository", Flags: []cli.Flag{ cli.StringFlag{"p", hypervisor.Default(), "hypervisor"}, }, Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan pull [image-name]") return } err := cmd.Pull(repo, c.String("p"), c.Args().First()) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "rmi", Usage: "delete an image from a repository", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan rmi [image-name]") return } err := repo.RemoveImage(c.Args().First()) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "run", Usage: "launch a VM", Flags: []cli.Flag{ cli.StringFlag{"p", hypervisor.Default(), "hypervisor"}, cli.StringFlag{"m", "1G", "memory size"}, cli.IntFlag{"c", 2, "number of CPUs"}, cli.BoolFlag{"v", "verbose mode"}, cli.StringSliceFlag{"f", new(cli.StringSlice), "port forwarding rules"}, }, Action: func(c *cli.Context) { config := &cmd.RunConfig{ ImageName: c.Args().First(), Hypervisor: c.String("p"), Verbose: c.Bool("v"), Memory: c.String("m"), Cpus: c.Int("c"), NatRules: nat.Parse(c.StringSlice("f")), } err := cmd.Run(repo, config) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "build", Usage: "build an image", Flags: []cli.Flag{ cli.StringFlag{"p", hypervisor.Default(), "hypervisor"}, cli.BoolFlag{"v", "verbose mode"}, }, Action: func(c *cli.Context) { image := c.Args().First() if len(c.Args()) != 1 { image = repo.DefaultImage() } if image == "" { fmt.Println("usage: capstan build [image-name]") return } hypervisor := c.String("p") err := cmd.Build(repo, hypervisor, image, c.Bool("v")) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "images", Usage: "list images", Action: func(c *cli.Context) { repo.ListImages() }, }, { Name: "search", Usage: "search a remote images", Action: func(c *cli.Context) { image := "" if len(c.Args()) > 0 { image = c.Args()[0] } util.ListImagesRemote(image) }, }, { Name: "instances", Usage: "list instances", Action: func(c *cli.Context) { cmd.Instances() }, }, { Name: "stop", Usage: "stop an instance", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan info [instance_name]") return } instance := c.Args()[0] cmd.Stop(instance) }, }, } app.Run(os.Args) }
func main() { repo := util.NewRepo() app := cli.NewApp() app.Name = "capstan" app.Version = VERSION app.Usage = "pack, ship, and run applications in light-weight VMs" app.Commands = []cli.Command{ { Name: "info", Usage: "show disk image information", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan info [image-file]") return } image := c.Args()[0] err := cmd.Info(image) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "import", Usage: "import an image to the local repository", Flags: []cli.Flag{ cli.StringFlag{Name: "v", Value: "", Usage: "image version"}, cli.StringFlag{Name: "c", Value: "", Usage: "image creation date"}, cli.StringFlag{Name: "d", Value: "", Usage: "image description"}, cli.StringFlag{Name: "b", Value: "", Usage: "image build command"}, }, Action: func(c *cli.Context) { if len(c.Args()) != 2 { fmt.Println("usage: capstan import [image-name] [image-file]") return } err := repo.ImportImage(c.Args()[0], c.Args()[1], c.String("v"), c.String("c"), c.String("d"), c.String("b")) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "pull", Usage: "pull an image from a repository", Flags: []cli.Flag{ cli.StringFlag{Name: "p", Value: hypervisor.Default(), Usage: "hypervisor: qemu|vbox|vmw|gce"}, }, Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan pull [image-name]") return } hypervisor := c.String("p") if !isValidHypervisor(hypervisor) { fmt.Printf("error: '%s' is not a supported hypervisor\n", c.String("p")) return } err := cmd.Pull(repo, hypervisor, c.Args().First()) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "rmi", Usage: "delete an image from a repository", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan rmi [image-name]") return } err := repo.RemoveImage(c.Args().First()) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "run", Usage: "launch a VM. You may pass the image name as the first argument.", Flags: []cli.Flag{ cli.StringFlag{Name: "i", Value: "", Usage: "image_name"}, cli.StringFlag{Name: "p", Value: hypervisor.Default(), Usage: "hypervisor: qemu|vbox|vmw|gce"}, cli.StringFlag{Name: "m", Value: "1G", Usage: "memory size"}, cli.IntFlag{Name: "c", Value: 2, Usage: "number of CPUs"}, cli.StringFlag{Name: "n", Value: "nat", Usage: "networking: nat|bridge|tap"}, cli.BoolFlag{Name: "v", Usage: "verbose mode"}, cli.StringFlag{Name: "b", Value: "", Usage: "networking device (bridge or tap): e.g., virbr0, vboxnet0, tap0"}, cli.StringSliceFlag{Name: "f", Value: new(cli.StringSlice), Usage: "port forwarding rules"}, cli.StringFlag{Name: "gce-upload-dir", Value: "", Usage: "Directory to upload local image to: e.g., gs://osvimg"}, cli.StringFlag{Name: "mac", Value: "", Usage: "MAC address. If not specified, the MAC address will be generated automatically."}, }, Action: func(c *cli.Context) { config := &cmd.RunConfig{ InstanceName: c.Args().First(), ImageName: c.String("i"), Hypervisor: c.String("p"), Verbose: c.Bool("v"), Memory: c.String("m"), Cpus: c.Int("c"), Networking: c.String("n"), Bridge: c.String("b"), NatRules: nat.Parse(c.StringSlice("f")), GCEUploadDir: c.String("gce-upload-dir"), MAC: c.String("mac"), } if !isValidHypervisor(config.Hypervisor) { fmt.Printf("error: '%s' is not a supported hypervisor\n", config.Hypervisor) return } err := cmd.Run(repo, config) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "build", Usage: "build an image", Flags: []cli.Flag{ cli.StringFlag{Name: "p", Value: hypervisor.Default(), Usage: "hypervisor: qemu|vbox|vmw|gce"}, cli.StringFlag{Name: "m", Value: "512M", Usage: "memory size"}, cli.BoolFlag{Name: "v", Usage: "verbose mode"}, }, Action: func(c *cli.Context) { imageName := c.Args().First() if len(c.Args()) != 1 { imageName = repo.DefaultImage() } if imageName == "" { fmt.Println("usage: capstan build [image-name]") return } hypervisor := c.String("p") if !isValidHypervisor(hypervisor) { fmt.Printf("error: '%s' is not a supported hypervisor\n", c.String("p")) return } image := &core.Image{ Name: imageName, Hypervisor: hypervisor, } template, err := core.ReadTemplateFile("Capstanfile") if err != nil { fmt.Println(err.Error()) return } if err := cmd.Build(repo, image, template, c.Bool("v"), c.String("m")); err != nil { fmt.Println(err.Error()) return } }, }, { Name: "images", ShortName: "i", Usage: "list images", Action: func(c *cli.Context) { repo.ListImages() }, }, { Name: "search", Usage: "search a remote images", Action: func(c *cli.Context) { image := "" if len(c.Args()) > 0 { image = c.Args()[0] } util.ListImagesRemote(image) }, }, { Name: "instances", ShortName: "I", Usage: "list instances", Action: func(c *cli.Context) { cmd.Instances() }, }, { Name: "stop", Usage: "stop an instance", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan stop [instance_name]") return } instance := c.Args()[0] cmd.Stop(instance) }, }, { Name: "delete", Usage: "delete an instance", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan delete [instance_name]") return } instance := c.Args()[0] cmd.Delete(instance) }, }, } app.Run(os.Args) }
func main() { repo := util.NewRepo() app := cli.NewApp() app.Name = "capstan" app.Version = VERSION app.Usage = "pack, ship, and run applications in light-weight VMs" app.Commands = []cli.Command{ { Name: "info", Usage: "show disk image information", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan info [image-file]") return } image := c.Args()[0] cmd.Info(image) }, }, { Name: "push", Usage: "push an image to a repository", Action: func(c *cli.Context) { if len(c.Args()) != 2 { fmt.Println("usage: capstan push [image-name] [image-file]") return } err := repo.PushImage(c.Args()[0], c.Args()[1]) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "pull", Usage: "pull an image from a repository", Flags: []cli.Flag{ cli.StringFlag{"p", hypervisor.Default(), "hypervisor"}, }, Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan pull [image-name]") return } err := cmd.Pull(repo, c.String("p"), c.Args().First()) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "rmi", Usage: "delete an image from a repository", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan rmi [image-name]") return } err := repo.RemoveImage(c.Args().First()) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "run", Usage: "launch a VM. You may pass the image name as the first argument.", Flags: []cli.Flag{ cli.StringFlag{"i", "", "image_name"}, cli.StringFlag{"p", hypervisor.Default(), "hypervisor: qemu|vbox|vmw|gce"}, cli.StringFlag{"m", "1G", "memory size"}, cli.IntFlag{"c", 2, "number of CPUs"}, cli.StringFlag{"n", "nat", "networking: nat|bridge"}, cli.BoolFlag{"v", "verbose mode"}, cli.StringFlag{"b", "", "networking bridge: e.g., virbr0, vboxnet0"}, cli.StringSliceFlag{"f", new(cli.StringSlice), "port forwarding rules"}, cli.StringFlag{"gce-upload-dir", "", "Directory to upload local image to: e.g., gs://osvimg"}, }, Action: func(c *cli.Context) { config := &cmd.RunConfig{ InstanceName: c.Args().First(), ImageName: c.String("i"), Hypervisor: c.String("p"), Verbose: c.Bool("v"), Memory: c.String("m"), Cpus: c.Int("c"), Networking: c.String("n"), Bridge: c.String("b"), NatRules: nat.Parse(c.StringSlice("f")), GCEUploadDir: c.String("gce-upload-dir"), } err := cmd.Run(repo, config) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "build", Usage: "build an image", Flags: []cli.Flag{ cli.StringFlag{"p", hypervisor.Default(), "hypervisor"}, cli.BoolFlag{"v", "verbose mode"}, }, Action: func(c *cli.Context) { image := c.Args().First() if len(c.Args()) != 1 { image = repo.DefaultImage() } if image == "" { fmt.Println("usage: capstan build [image-name]") return } hypervisor := c.String("p") err := cmd.Build(repo, hypervisor, image, c.Bool("v")) if err != nil { fmt.Println(err.Error()) } }, }, { Name: "images", ShortName: "i", Usage: "list images", Action: func(c *cli.Context) { repo.ListImages() }, }, { Name: "search", Usage: "search a remote images", Action: func(c *cli.Context) { image := "" if len(c.Args()) > 0 { image = c.Args()[0] } util.ListImagesRemote(image) }, }, { Name: "instances", ShortName: "I", Usage: "list instances", Action: func(c *cli.Context) { cmd.Instances() }, }, { Name: "stop", Usage: "stop an instance", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan stop [instance_name]") return } instance := c.Args()[0] cmd.Stop(instance) }, }, { Name: "delete", Usage: "delete an instance", Action: func(c *cli.Context) { if len(c.Args()) != 1 { fmt.Println("usage: capstan delete [instance_name]") return } instance := c.Args()[0] cmd.Delete(instance) }, }, } app.Run(os.Args) }