Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var CleanCommand = cli.Command{ Name: "clean", Usage: "clean", Description: "Cleans up unused layers", Flags: []cli.Flag{ cli.Int64Flag{ Name: "threshold-bytes", Usage: "Disk usage of the store directory at which cleanup should trigger.", }, cli.StringSliceFlag{ Name: "ignore-image", Usage: "Images to ignore during cleanup", }, }, Action: func(ctx *cli.Context) error { logger := ctx.App.Metadata["logger"].(lager.Logger) logger = logger.Session("clean") configBuilder := ctx.App.Metadata["configBuilder"].(*config.Builder) configBuilder.WithIgnoreBaseImages(ctx.StringSlice("ignore-image")) configBuilder.WithCleanThresholdBytes(ctx.Int64("threshold-bytes"), ctx.IsSet("threshold-bytes")) cfg, err := configBuilder.Build() logger.Debug("clean-config", lager.Data{"currentConfig": cfg}) if err != nil { logger.Error("config-builder-failed", err) return cli.NewExitError(err.Error(), 1) } storePath := cfg.StorePath if _, err := os.Stat(storePath); os.IsNotExist(err) { err := errorspkg.Errorf("no store found at %s", storePath) logger.Error("store-path-failed", err, nil) return cli.NewExitError(err.Error(), 0) } fsDriver, err := createFileSystemDriver(cfg) if err != nil { logger.Error("failed-to-initialise-driver", err) return cli.NewExitError(err.Error(), 1) } imageCloner := imageClonerpkg.NewImageCloner(fsDriver, storePath) locksmith := locksmithpkg.NewFileSystem(storePath) dependencyManager := dependency_manager.NewDependencyManager( filepath.Join(storePath, storepkg.MetaDirName, "dependencies"), ) cacheDriver := cache_driver.NewCacheDriver(storePath) sm := garbage_collector.NewStoreMeasurer(storePath) gc := garbage_collector.NewGC(cacheDriver, fsDriver, imageCloner, dependencyManager) metricsEmitter := metrics.NewEmitter() cleaner := groot.IamCleaner(locksmith, sm, gc, metricsEmitter) noop, err := cleaner.Clean(logger, cfg.Clean.ThresholdBytes, cfg.Clean.IgnoreBaseImages, true) if err != nil { logger.Error("cleaning-up-unused-resources", err) return cli.NewExitError(err.Error(), 1) } if noop { fmt.Println("threshold not reached: skipping clean") return nil } fmt.Println("clean completed") return nil }, }
View Source
var CreateCommand = cli.Command{ Name: "create", Usage: "create [options] <image> <id>", Description: "Creates a root filesystem for the provided image.", Flags: []cli.Flag{ cli.Int64Flag{ Name: "disk-limit-size-bytes", Usage: "Inclusive disk limit (i.e: includes all layers in the filesystem)", }, cli.StringSliceFlag{ Name: "uid-mapping", Usage: "UID mapping for image translation, e.g.: <Namespace UID>:<Host UID>:<Size>", }, cli.StringSliceFlag{ Name: "gid-mapping", Usage: "GID mapping for image translation, e.g.: <Namespace GID>:<Host GID>:<Size>", }, cli.StringSliceFlag{ Name: "insecure-registry", Usage: "Whitelist a private registry", }, cli.BoolFlag{ Name: "exclude-image-from-quota", Usage: "Set disk limit to be exclusive (i.e.: excluding image layers)", }, cli.BoolFlag{ Name: "with-clean", Usage: "Clean up unused layers before creating rootfs", }, cli.BoolFlag{ Name: "without-clean", Usage: "Do NOT clean up unused layers before creating rootfs", }, cli.StringFlag{ Name: "username", Usage: "Username to authenticate in image registry", }, cli.StringFlag{ Name: "password", Usage: "Password to authenticate in image registry", }, }, Action: func(ctx *cli.Context) error { logger := ctx.App.Metadata["logger"].(lager.Logger) logger = logger.Session("create") if ctx.NArg() != 2 { logger.Error("parsing-command", errorspkg.New("invalid arguments"), lager.Data{"args": ctx.Args()}) return cli.NewExitError(fmt.Sprintf("invalid arguments - usage: %s", ctx.Command.Usage), 1) } if ctx.IsSet("with-clean") && ctx.IsSet("without-clean") { return cli.NewExitError("with-clean and without-clean cannot be used together", 1) } configBuilder := ctx.App.Metadata["configBuilder"].(*config.Builder) configBuilder.WithInsecureRegistries(ctx.StringSlice("insecure-registry")). WithUIDMappings(ctx.StringSlice("uid-mapping")). WithGIDMappings(ctx.StringSlice("gid-mapping")). WithDiskLimitSizeBytes(ctx.Int64("disk-limit-size-bytes"), ctx.IsSet("disk-limit-size-bytes")). WithExcludeImageFromQuota(ctx.Bool("exclude-image-from-quota"), ctx.IsSet("exclude-image-from-quota")). WithClean(ctx.IsSet("with-clean"), ctx.IsSet("without-clean")) cfg, err := configBuilder.Build() logger.Debug("create-config", lager.Data{"currentConfig": cfg}) if err != nil { logger.Error("config-builder-failed", err) return cli.NewExitError(err.Error(), 1) } storePath := cfg.StorePath baseImage := ctx.Args().First() id := ctx.Args().Tail()[0] uidMappings, err := parseIDMappings(cfg.Create.UIDMappings) if err != nil { err = errorspkg.Errorf("parsing uid-mapping: %s", err) logger.Error("parsing-command", err) return cli.NewExitError(err.Error(), 1) } gidMappings, err := parseIDMappings(cfg.Create.GIDMappings) if err != nil { err = errorspkg.Errorf("parsing gid-mapping: %s", err) logger.Error("parsing-command", err) return cli.NewExitError(err.Error(), 1) } storeOwnerUid, storeOwnerGid, err := findStoreOwner(uidMappings, gidMappings) if err != nil { return err } if err = store.ConfigureStore(logger, storePath, cfg.FSDriver, storeOwnerUid, storeOwnerGid); err != nil { exitErr := errorspkg.Wrapf(err, "id: %s", id) logger.Error("failed-to-setup-store", err, lager.Data{"id": id}) return cli.NewExitError(exitErr.Error(), 1) } fsDriver, err := createFileSystemDriver(cfg) if err != nil { return cli.NewExitError(err.Error(), 1) } imageCloner := image_cloner.NewImageCloner(fsDriver, storePath) runner := linux_command_runner.New() var unpacker base_image_puller.Unpacker unpackerStrategy := unpackerpkg.UnpackStrategy{ Name: cfg.FSDriver, WhiteoutDevicePath: filepath.Join(storePath, store.WhiteoutDevice), } if os.Getuid() == 0 { unpacker = unpackerpkg.NewNSSysProcUnpacker(runner, unpackerStrategy) } else { idMapper := unpackerpkg.NewIDMapper(cfg.NewuidmapBin, cfg.NewgidmapBin, runner) unpacker = unpackerpkg.NewNSIdMapperUnpacker(runner, idMapper, unpackerStrategy) } dockerSrc := remote.NewDockerSource(ctx.String("username"), ctx.String("password"), cfg.Create.InsecureRegistries) cacheDriver := cache_driver.NewCacheDriver(storePath) remoteFetcher := remote.NewRemoteFetcher(dockerSrc, cacheDriver) localFetcher := local.NewLocalFetcher() locksmith := locksmithpkg.NewFileSystem(storePath) dependencyManager := dependency_manager.NewDependencyManager( filepath.Join(storePath, storepkg.MetaDirName, "dependencies"), ) baseImagePuller := base_image_puller.NewBaseImagePuller( localFetcher, remoteFetcher, unpacker, fsDriver, dependencyManager, ) rootFSConfigurer := storepkg.NewRootFSConfigurer() metricsEmitter := metrics.NewEmitter() sm := garbage_collector.NewStoreMeasurer(storePath) gc := garbage_collector.NewGC(cacheDriver, fsDriver, imageCloner, dependencyManager) cleaner := groot.IamCleaner(locksmith, sm, gc, metricsEmitter) namespaceChecker := groot.NewNamespaceChecker(storePath) creator := groot.IamCreator( imageCloner, baseImagePuller, locksmith, rootFSConfigurer, dependencyManager, metricsEmitter, cleaner, namespaceChecker, ) createSpec := groot.CreateSpec{ ID: id, BaseImage: baseImage, DiskLimit: cfg.Create.DiskLimitSizeBytes, ExcludeBaseImageFromQuota: cfg.Create.ExcludeImageFromQuota, UIDMappings: uidMappings, GIDMappings: gidMappings, CleanOnCreate: cfg.Create.WithClean, CleanOnCreateThresholdBytes: cfg.Clean.ThresholdBytes, CleanOnCreateIgnoreImages: cfg.Clean.IgnoreBaseImages, } image, err := creator.Create(logger, createSpec) if err != nil { logger.Error("creating", err) humanizedError := tryHumanize(err, createSpec) return cli.NewExitError(humanizedError, 1) } fmt.Println(image.Path) return nil }, }
View Source
var DeleteCommand = cli.Command{ Name: "delete", Usage: "delete <id|image path>", Description: "Deletes a container image", Action: func(ctx *cli.Context) error { logger := ctx.App.Metadata["logger"].(lager.Logger) logger = logger.Session("delete") if ctx.NArg() != 1 { logger.Error("parsing-command", errorspkg.New("id was not specified")) return cli.NewExitError("id was not specified", 1) } configBuilder := ctx.App.Metadata["configBuilder"].(*config.Builder) cfg, err := configBuilder.Build() logger.Debug("delete-config", lager.Data{"currentConfig": cfg}) if err != nil { logger.Error("config-builder-failed", err) return cli.NewExitError(err.Error(), 1) } storePath := cfg.StorePath idOrPath := ctx.Args().First() id, err := idfinder.FindID(storePath, idOrPath) if err != nil { logger.Debug("id-not-found-skipping", lager.Data{"id": idOrPath, "storePath": storePath, "errorMessage": err.Error()}) fmt.Println(err) return nil } fsDriver, err := createFileSystemDriver(cfg) if err != nil { logger.Error("failed-to-initialise-driver", err) return cli.NewExitError(err.Error(), 1) } imageCloner := imageClonerpkg.NewImageCloner(fsDriver, storePath) dependencyManager := dependency_manager.NewDependencyManager( filepath.Join(storePath, store.MetaDirName, "dependencies"), ) metricsEmitter := metrics.NewEmitter() deleter := groot.IamDeleter(imageCloner, dependencyManager, metricsEmitter) err = deleter.Delete(logger, id) if err != nil { logger.Error("deleting-image-failed", err) return cli.NewExitError(err.Error(), 1) } fmt.Printf("Image %s deleted\n", id) return nil }, }
View Source
var ListCommand = cli.Command{ Name: "list", Usage: "list", Description: "Lists images in store", Action: func(ctx *cli.Context) error { logger := ctx.App.Metadata["logger"].(lager.Logger) logger = logger.Session("list") configBuilder := ctx.App.Metadata["configBuilder"].(*config.Builder) cfg, err := configBuilder.Build() logger.Debug("list-config", lager.Data{"currentConfig": cfg}) if err != nil { logger.Error("config-builder-failed", err) return cli.NewExitError(err.Error(), 1) } if _, err := os.Stat(cfg.StorePath); os.IsNotExist(err) { err := errorspkg.Errorf("no store found at %s", cfg.StorePath) logger.Error("store-path-failed", err, nil) return cli.NewExitError(err.Error(), 1) } lister := groot.IamLister() images, err := lister.List(logger, cfg.StorePath) if err != nil { logger.Error("listing-images", err, lager.Data{"storePath": cfg.StorePath}) return cli.NewExitError(fmt.Sprintf("Failed to retrieve list of images: %s", err.Error()), 1) } if len(images) == 0 { fmt.Println("Store empty") } for _, image := range images { fmt.Println(image) } return nil }, }
View Source
var StatsCommand = cli.Command{ Name: "stats", Usage: "stats [options] <id|image path>", Description: "Return filesystem stats", Action: func(ctx *cli.Context) error { logger := ctx.App.Metadata["logger"].(lager.Logger) logger = logger.Session("stats") if ctx.NArg() != 1 { logger.Error("parsing-command", errorspkg.New("invalid arguments"), lager.Data{"args": ctx.Args()}) return cli.NewExitError(fmt.Sprintf("invalid arguments - usage: %s", ctx.Command.Usage), 1) } configBuilder := ctx.App.Metadata["configBuilder"].(*config.Builder) cfg, err := configBuilder.Build() logger.Debug("stats-config", lager.Data{"currentConfig": cfg}) if err != nil { logger.Error("config-builder-failed", err) return cli.NewExitError(err.Error(), 1) } storePath := cfg.StorePath idOrPath := ctx.Args().First() id, err := idfinder.FindID(storePath, idOrPath) if err != nil { logger.Error("find-id-failed", err, lager.Data{"id": idOrPath, "storePath": storePath}) return cli.NewExitError(err.Error(), 1) } fsDriver, err := createFileSystemDriver(cfg) if err != nil { return cli.NewExitError(err.Error(), 1) } imageCloner := imageClonerpkg.NewImageCloner(fsDriver, storePath) metricsEmitter := metrics.NewEmitter() statser := groot.IamStatser(imageCloner, metricsEmitter) stats, err := statser.Stats(logger, id) if err != nil { logger.Error("fetching-stats", err) return cli.NewExitError(err.Error(), 1) } json.NewEncoder(os.Stdout).Encode(stats) return nil }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.