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  }