package main import ( "os" "reflect" "regexp" "strings" is "github.com/containers/image/storage" "github.com/containers/storage" "github.com/fatih/camelcase" "github.com/projectatomic/libpod/libkpod" "github.com/projectatomic/libpod/libpod" "github.com/pkg/errors" "github.com/urfave/cli" ) var ( stores = make(map[storage.Store]struct{}) ) const CrioConfigPath = "/etc/crio/crio.conf" func getStore(c *libkpod.Config) (storage.Store, error) { options := storage.DefaultStoreOptions options.GraphRoot = c.Root options.RunRoot = c.RunRoot options.GraphDriverName = c.Storage options.GraphDriverOptions = c.StorageOptions store, err := storage.GetStore(options) if err != nil { return nil, err } is.Transport.SetStore(store) stores[store] = struct{}{} return store, nil } func getRuntime(c *cli.Context) (*libpod.Runtime, error) { config, err := getConfig(c) if err != nil { return nil, errors.Wrapf(err, "could not get config") } options := storage.DefaultStoreOptions options.GraphRoot = config.Root options.RunRoot = config.RunRoot options.GraphDriverName = config.Storage options.GraphDriverOptions = config.StorageOptions return libpod.NewRuntime(libpod.WithStorageConfig(options)) } func shutdownStores() { for store := range stores { if _, err := store.Shutdown(false); err != nil { break } } } func getConfig(c *cli.Context) (*libkpod.Config, error) { config := libkpod.DefaultConfig() var configFile string if c.GlobalIsSet("config") { configFile = c.GlobalString("config") } else if _, err := os.Stat(CrioConfigPath); err == nil { configFile = CrioConfigPath } // load and merge the configfile from the commandline or use // the default crio config file if configFile != "" { err := config.UpdateFromFile(configFile) if err != nil { return config, err } } if c.GlobalIsSet("root") { config.Root = c.GlobalString("root") } if c.GlobalIsSet("runroot") { config.RunRoot = c.GlobalString("runroot") } if c.GlobalIsSet("storage-driver") { config.Storage = c.GlobalString("storage-driver") } if c.GlobalIsSet("storage-opt") { opts := c.GlobalStringSlice("storage-opt") if len(opts) > 0 { config.StorageOptions = opts } } if c.GlobalIsSet("runtime") { config.Runtime = c.GlobalString("runtime") } return config, nil } func splitCamelCase(src string) string { entries := camelcase.Split(src) return strings.Join(entries, " ") } // validateFlags searches for StringFlags or StringSlice flags that never had // a value set. This commonly occurs when the CLI mistakenly takes the next // option and uses it as a value. func validateFlags(c *cli.Context, flags []cli.Flag) error { for _, flag := range flags { switch reflect.TypeOf(flag).String() { case "cli.StringSliceFlag": { f := flag.(cli.StringSliceFlag) name := strings.Split(f.Name, ",") val := c.StringSlice(name[0]) for _, v := range val { if ok, _ := regexp.MatchString("^-.+", v); ok { return errors.Errorf("option --%s requires a value", name[0]) } } } case "cli.StringFlag": { f := flag.(cli.StringFlag) name := strings.Split(f.Name, ",") val := c.String(name[0]) if ok, _ := regexp.MatchString("^-.+", val); ok { return errors.Errorf("option --%s requires a value", name[0]) } } } } return nil }