github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/cmd/build.go (about) 1 package cmd 2 3 import ( 4 "io/ioutil" 5 "os" 6 7 "github.com/sirupsen/logrus" 8 "github.com/spf13/cobra" 9 10 "github.com/emc-advanced-dev/pkg/errors" 11 "github.com/solo-io/unik/pkg/client" 12 unikos "github.com/solo-io/unik/pkg/os" 13 ) 14 15 var name, sourcePath, base, lang, provider, runArgs string 16 var mountPoints []string 17 var force, noCleanup bool 18 19 var buildCmd = &cobra.Command{ 20 Use: "build", 21 Short: "Build a unikernel image from source code files", 22 Long: `Compiles source files into a runnable unikernel image. 23 24 Images must be compiled using a specific compiler. Compilers are composed of 3 elements: 25 **Base**: The Unikernel Base to build the image on. These include different unikernel implementations, such as [rumprun](https://github.com/rumpkernel/rumprun), [IncludeOS](https://gitter.im/hioa-cs/IncludeOS), etc. 26 **Language**: The language/runtime the image should be built with. E.g. for a golang project, specify '-language go'. Languages supported depend on the unikernel base. 27 **Provider**: The (cloud/hypervisor) provider the image should be built for. Supported providers depend on the unikernel base. 28 29 In order to see a list of all supported base/language/provider combinations, run 'unik compilers' 30 31 Images must be compiled for a specific provider, specified with the '--provider' flag 32 To see a list of available providers, run 'unik providers' 33 34 A unikernel base that is compatible with the provider must be specified with the '--base' flag. 35 A language runtime that is compatible with the base must be specified with the '--language' flag. 36 To see a table of all compatible base-language-provider combinations, run 'unik compilers' 37 38 If you wish to attach volumes to instances of an image, the image must be compiled in advance 39 with a list of the expected mount points. e.g. for an application that reads from a '/data' folder, 40 the unikernel should be compiled with the flag '--mount /data' 41 42 Runtime arguments to be passed to your unikernel must also be specified at compile time. 43 You can specify arguments as a single string passed to the '--args' flag 44 45 Image names must be unique. If an image exists with the same name, you can force overwriting with the --force flag 46 47 Example usage: 48 unik build --name myUnikernel --path ./myApp/src --base rump --language go --provider aws --mountpoint /foo --mountpoint /bar --args 'arg1 arg2 arg3' --force 49 50 * will create a Go unikernel named myUnikernel using the sources found in ./myApp/src, 51 * compiled using rumprun targeting AWS infrastructure, 52 * expecting a volume to be mounted at /foo at runtime, 53 * expecting another volume to be mounted at /bar at runtime, 54 * passing 'arg1 arg2 arg3' as arguments to the application when it is run, 55 * and deleting any previous existing instances and image for the name myUnikernel before compiling 56 57 Another example (using only the required parameters): 58 unik build -name anotherUnikernel -path ./anotherApp/src --base includeos --language cpp --provider virtualbox 59 `, 60 Run: func(cmd *cobra.Command, args []string) { 61 if err := func() error { 62 if name == "" { 63 return errors.New("--name must be set", nil) 64 } 65 if sourcePath == "" { 66 return errors.New("--path must be set", nil) 67 } 68 if base == "" { 69 return errors.New("--base must be set", nil) 70 } 71 if lang == "" { 72 return errors.New("--language must be set", nil) 73 } 74 if provider == "" { 75 return errors.New("--provider must be set", nil) 76 } 77 if err := readClientConfig(); err != nil { 78 return err 79 } 80 if host == "" { 81 host = clientConfig.Host 82 } 83 logrus.WithFields(logrus.Fields{ 84 "name": name, 85 "path": sourcePath, 86 "base": base, 87 "language": lang, 88 "provider": provider, 89 "args": runArgs, 90 "mountPoints": mountPoints, 91 "force": force, 92 "host": host, 93 }).Infof("running unik build") 94 sourceTar, err := ioutil.TempFile("", "sources.tar.gz.") 95 if err != nil { 96 logrus.WithError(err).Error("failed to create tmp tar file") 97 } 98 defer os.Remove(sourceTar.Name()) 99 if err := unikos.Compress(sourcePath, sourceTar.Name()); err != nil { 100 return errors.New("failed to tar sources", err) 101 } 102 logrus.Infof("App packaged as tarball: %s\n", sourceTar.Name()) 103 image, err := client.UnikClient(host).Images().Build(name, sourceTar.Name(), base, lang, provider, runArgs, mountPoints, force, noCleanup) 104 if err != nil { 105 return errors.New("building image failed", err) 106 } 107 printImages(image) 108 return nil 109 }(); err != nil { 110 logrus.Errorf("build failed: %v", err) 111 os.Exit(-1) 112 } 113 }, 114 } 115 116 func init() { 117 RootCmd.AddCommand(buildCmd) 118 buildCmd.Flags().StringVar(&name, "name", "", "<string,required> name to give the unikernel. must be unique") 119 buildCmd.Flags().StringVar(&sourcePath, "path", "", "<string,required> path to root application sources folder") 120 buildCmd.Flags().StringVar(&base, "base", "", "<string,required> name of the unikernel base to use") 121 buildCmd.Flags().StringVar(&lang, "language", "", "<string,required> language the unikernel source is written in") 122 buildCmd.Flags().StringVar(&provider, "provider", "", "<string,required> name of the target infrastructure to compile for") 123 buildCmd.Flags().StringVar(&runArgs, "args", "", "<string,optional> to be passed to the unikernel at runtime") 124 buildCmd.Flags().StringSliceVar(&mountPoints, "mountpoint", []string{}, "<string,repeated> specify up to 8 mount points for volumes") 125 buildCmd.Flags().BoolVar(&force, "force", false, "<bool, optional> force overwriting a previously existing") 126 buildCmd.Flags().BoolVar(&noCleanup, "no-cleanup", false, "<bool, optional> for debugging; do not clean up artifacts for images that fail to build") 127 }