func runCatManifest(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } pod, err := getPodFromUUIDString(args[0]) if err != nil { stderr("cat-manifest: problem retrieving pod: %v", err) return 1 } defer pod.Close() manifest, err := pod.getManifest() if err != nil { return 1 } var b []byte if flagPMPrettyPrint { b, err = json.MarshalIndent(manifest, "", "\t") } else { b, err = json.Marshal(manifest) } if err != nil { stderr("cat-manifest: cannot read the pod manifest: %v", err) return 1 } stdout(string(b)) return 0 }
func runStatus(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } p, err := getPodFromUUIDString(args[0]) if err != nil { stderr("Problem retrieving pod: %v", err) return 1 } defer p.Close() if flagWait { if err := p.waitExited(); err != nil { stderr("Unable to wait for pod: %v", err) return 1 } } if err = printStatus(p); err != nil { stderr("Unable to print status: %v", err) return 1 } return 0 }
func runTrust(cmd *cobra.Command, args []string) (exit int) { if flagPrefix == "" && !flagRoot { if len(args) != 0 { stderr("--root required for non-prefixed (root) keys") } else { cmd.Usage() } return 1 } if flagPrefix != "" && flagRoot { stderr("--root and --prefix usage mutually exclusive") return 1 } // if the user included a scheme with the prefix, error on it u, err := url.Parse(flagPrefix) if err == nil && u.Scheme != "" { stderr("--prefix must not contain a URL scheme, omit %s://", u.Scheme) return 1 } pkls, err := getPubKeyLocations(flagPrefix, args) if err != nil { stderr("Error determining key location: %v", err) return 1 } if err := addKeys(pkls, flagPrefix); err != nil { stderr("Error adding keys: %v", err) return 1 } return 0 }
func runRm(cmd *cobra.Command, args []string) (exit int) { var podUUID *types.UUID var err error switch { case len(args) == 0 && flagUUIDFile != "": podUUID, err = readUUIDFromFile(flagUUIDFile) if err != nil { stderr("Unable to read UUID from file: %v", err) return 1 } case len(args) == 1 && flagUUIDFile == "": podUUID, err = resolveUUID(args[0]) if err != nil { stderr("Unable to resolve UUID: %v", err) return 1 } default: cmd.Usage() return 1 } p, err := getPod(podUUID) if err != nil { stderr("Cannot get pod: %v", err) return 1 } return removePod(p) }
func runStatus(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } podUUID, err := resolveUUID(args[0]) if err != nil { stderr("Unable to resolve UUID: %v", err) return 1 } p, err := getPod(podUUID) if err != nil { stderr("Unable to get pod: %v", err) return 1 } defer p.Close() if flagWait { if err := p.waitExited(); err != nil { stderr("Unable to wait for pod: %v", err) return 1 } } if err = printStatus(p); err != nil { stderr("Unable to print status: %v", err) return 1 } return 0 }
func runTrust(cmd *cobra.Command, args []string) (exit int) { if globalFlags.InsecureSkipVerify { // --insecure-skip-verify disable the keystore but we need it for rkt trust stderr("--insecure-skip-verify cannot be used with rkt trust") return 1 } if flagPrefix == "" && !flagRoot { if len(args) != 0 { stderr("--root required for non-prefixed (root) keys") } else { cmd.Usage() } return 1 } if flagPrefix != "" && flagRoot { stderr("--root and --prefix usage mutually exclusive") return 1 } ks := getKeystore() if ks == nil { stderr("could not get the keystore") return 1 } // if the user included a scheme with the prefix, error on it u, err := url.Parse(flagPrefix) if err == nil && u.Scheme != "" { stderr("--prefix must not contain a URL scheme, omit %s://", u.Scheme) return 1 } pkls := args m := &pubkey.Manager{ InsecureAllowHttp: flagAllowHTTP, TrustKeysFromHttps: globalFlags.TrustKeysFromHttps, Ks: ks, Debug: globalFlags.Debug, } if len(pkls) == 0 { pkls, err = m.GetPubKeyLocations(flagPrefix) if err != nil { stderr("Error determining key location: %v", err) return 1 } } acceptOpt := pubkey.AcceptAsk if globalFlags.InsecureSkipVerify { acceptOpt = pubkey.AcceptForce } if err := m.AddKeys(pkls, flagPrefix, acceptOpt, pubkey.OverrideDeny); err != nil { stderr("Error adding keys: %v", err) return 1 } return 0 }
func runImageImport(cmd *cobra.Command, args []string) (exit int) { if len(args) != 2 { cmd.Usage() return 1 } outFile := args[1] ext := filepath.Ext(outFile) if ext != schema.ACIExtension { stderr("rkt: Extension must be %s (given %s)", schema.ACIExtension, ext) return 1 } aciImgPath, err := oci2aciImage(args[0]) if err != nil { stderr("rkt: oci2aci failed: %s", err) return 1 } if err = run(exec.Command("mv", aciImgPath, args[1])); err != nil { return 1 } return 0 }
func runImageImport(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } //convert oci bundle to aci image aciImage, err := oci2aci.Oci2aciImage(args[0]) if err != nil { fmt.Printf("oci2aci failed: %v", err) return 1 } //save aci to rkt store s, err := store.NewStore(globalFlags.Dir) if err != nil { fmt.Printf("cannot open store: %v", err) return 1 } aciFile, err := os.Open(aciImage) if err != nil { fmt.Printf("opening ACI file %s failed: %v", aciImage, err) return 1 } key, err := s.WriteACI(aciFile, true) if err != nil { fmt.Printf("write ACI file failed: %v", err) return 1 } fmt.Println(key) return 0 }
func runFetch(cmd *cobra.Command, args []string) (exit int) { if err := parseApps(&rktApps, args, cmd.Flags(), false); err != nil { stderr("fetch: unable to parse arguments: %v", err) return 1 } if rktApps.Count() < 1 { stderr("fetch: must provide at least one image") return 1 } if flagStoreOnly && flagNoStore { stderr("both --store-only and --no-store specified") return 1 } s, err := store.NewStore(getDataDir()) if err != nil { stderr("fetch: cannot open store: %v", err) return 1 } ks := getKeystore() config, err := getConfig() if err != nil { stderr("fetch: cannot get configuration: %v", err) return 1 } ft := &image.Fetcher{ S: s, Ks: ks, Headers: config.AuthPerHost, DockerAuth: config.DockerCredentialsPerRegistry, InsecureFlags: globalFlags.InsecureFlags, Debug: globalFlags.Debug, TrustKeysFromHTTPS: globalFlags.TrustKeysFromHTTPS, StoreOnly: flagStoreOnly, NoStore: flagNoStore, WithDeps: true, } err = rktApps.Walk(func(app *apps.App) error { hash, err := ft.FetchImage(app.Image, app.Asc, app.ImType) if err != nil { return err } if !flagFullHash { hash = types.ShortHash(hash) } stdout(hash) return nil }) if err != nil { stderr("%v", err) return 1 } return }
func getSubCommands(cmd *cobra.Command) []*cobra.Command { subCommands := []*cobra.Command{} for _, subCmd := range cmd.Commands() { subCommands = append(subCommands, subCmd) subCommands = append(subCommands, getSubCommands(subCmd)...) } return subCommands }
func runImageCatManifest(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("image cat-manifest: cannot open store: %v", err) return 1 } var key string if _, err := types.NewHash(args[0]); err == nil { key, err = s.ResolveKey(args[0]) if err != nil { stderr("image cat-manifest: cannot resolve key: %v", err) return 1 } } else { app, err := discovery.NewAppFromString(args[0]) if err != nil { stderr("image cat-manifest: cannot parse the image name: %v", err) return 1 } labels, err := types.LabelsFromMap(app.Labels) if err != nil { stderr("image cat-manifest: invalid labels in the name: %v", err) return 1 } key, err = s.GetACI(app.Name, labels) if err != nil { stderr("image cat-manifest: cannot find image: %v", err) return 1 } } manifest, err := s.GetImageManifest(key) if err != nil { stderr("image cat-manifest: cannot get image manifest: %v", err) return 1 } var b []byte if flagPrettyPrint { b, err = json.MarshalIndent(manifest, "", "\t") } else { b, err = json.Marshal(manifest) } if err != nil { stderr("image cat-manifest: cannot read the image manifest: %v", err) return 1 } stdout(string(b)) return 0 }
func runFetch(cmd *cobra.Command, args []string) (exit int) { if err := parseApps(&rktApps, args, cmd.Flags(), false); err != nil { stderr("fetch: unable to parse arguments: %v", err) return 1 } if rktApps.Count() < 1 { stderr("fetch: must provide at least one image") return 1 } if flagStoreOnly && flagNoStore { stderr("both --store-only and --no-store specified") return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("fetch: cannot open store: %v", err) return 1 } ks := getKeystore() config, err := getConfig() if err != nil { stderr("fetch: cannot get configuration: %v", err) return 1 } ft := &fetcher{ imageActionData: imageActionData{ s: s, ks: ks, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, storeOnly: flagStoreOnly, noStore: flagNoStore, withDeps: true, } err = rktApps.Walk(func(app *apps.App) error { hash, err := ft.fetchImage(app.Image, app.Asc) if err != nil { return err } shortHash := types.ShortHash(hash) stdout(shortHash) return nil }) if err != nil { stderr("%v", err) return 1 } return }
func runEnter(cmd *cobra.Command, args []string) (exit int) { if len(args) < 1 { cmd.Usage() return 1 } p, err := getPodFromUUIDString(args[0]) if err != nil { stderr("Problem problem retrieving pod: %v", err) return 1 } defer p.Close() if !p.isRunning() { stderr("Pod %q isn't currently running", p.uuid) return 1 } podPID, err := p.getContainerPID1() if err != nil { stderr("Unable to determine the pid for pod %q: %v", p.uuid, err) return 1 } appName, err := getAppName(p) if err != nil { stderr("Unable to determine app name: %v", err) return 1 } argv, err := getEnterArgv(p, args) if err != nil { stderr("Enter failed: %v", err) return 1 } s, err := store.NewStore(getDataDir()) if err != nil { stderr("Cannot open store: %v", err) return 1 } stage1TreeStoreID, err := p.getStage1TreeStoreID() if err != nil { stderr("Error getting stage1 treeStoreID: %v", err) return 1 } stage1RootFS := s.GetTreeStoreRootFS(stage1TreeStoreID) if err = stage0.Enter(p.path(), podPID, *appName, stage1RootFS, argv); err != nil { stderr("Enter failed: %v", err) return 1 } // not reached when stage0.Enter execs /enter return 0 }
func runImageExport(cmd *cobra.Command, args []string) (exit int) { if len(args) != 2 { cmd.Usage() return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("image export: cannot open store: %v", err) return 1 } key, err := getKeyFromAppOrHash(s, args[0]) if err != nil { stderr("image export: %v", err) return 1 } aci, err := s.ReadStream(key) if err != nil { stderr("image export: error reading image: %v", err) return 1 } defer aci.Close() mode := os.O_CREATE | os.O_WRONLY if flagOverwriteACI { mode |= os.O_TRUNC } else { mode |= os.O_EXCL } f, err := os.OpenFile(args[1], mode, 0644) if err != nil { if os.IsExist(err) { stderr("image export: output ACI file exists (try --overwrite)") } else { stderr("image export: unable to open output ACI file %s: %v", args[1], err) } return 1 } defer func() { err := f.Close() if err != nil { stderr("image export: error closing output ACI file: %v", err) exit = 1 } }() _, err = io.Copy(f, aci) if err != nil { stderr("image export: error writing to output ACI file: %v", err) return 1 } return 0 }
func runRm(cmd *cobra.Command, args []string) (exit int) { var podUUID *types.UUID var podUUIDs []*types.UUID var err error switch { case len(args) == 0 && flagUUIDFile != "": podUUID, err = readUUIDFromFile(flagUUIDFile) if err != nil { stderr("Unable to read UUID from file: %v", err) return 1 } podUUIDs = append(podUUIDs, podUUID) case len(args) > 0 && flagUUIDFile == "": for _, uuid := range args { podUUID, err := resolveUUID(uuid) if err != nil { stderr("Unable to resolve UUID: %v", err) } else { podUUIDs = append(podUUIDs, podUUID) } } default: cmd.Usage() return 1 } ret := 0 for _, podUUID = range podUUIDs { p, err := getPod(podUUID) if err != nil { ret = 1 stderr("Cannot get pod: %v", err) } if removePod(p) { stdout("%q", p.uuid) } else { ret = 1 } } if ret == 1 { stderr("Failed to remove one or more pods") } return ret }
func runTrust(cmd *cobra.Command, args []string) (exit int) { if globalFlags.InsecureSkipVerify { // --insecure-skip-verify disable the keystore but we need it for rkt trust stderr("--insecure-skip-verify cannot be used with rkt trust") return 1 } if flagPrefix == "" && !flagRoot { if len(args) != 0 { stderr("--root required for non-prefixed (root) keys") } else { cmd.Usage() } return 1 } if flagPrefix != "" && flagRoot { stderr("--root and --prefix usage mutually exclusive") return 1 } // if the user included a scheme with the prefix, error on it u, err := url.Parse(flagPrefix) if err == nil && u.Scheme != "" { stderr("--prefix must not contain a URL scheme, omit %s://", u.Scheme) return 1 } pkls := args if len(pkls) == 0 { pkls, err = getPubKeyLocations(flagPrefix, flagAllowHTTP, globalFlags.Debug) if err != nil { stderr("Error determining key location: %v", err) return 1 } } // allow override if err := addKeys(pkls, flagPrefix, flagAllowHTTP, globalFlags.InsecureSkipVerify, true); err != nil { stderr("Error adding keys: %v", err) return 1 } return 0 }
func usageFunc(cmd *cobra.Command) error { subCommands := getSubCommands(cmd) commandUsageTemplate.Execute(tabOut, struct { Executable string Cmd *cobra.Command CmdFlags *pflag.FlagSet SubCommands []*cobra.Command Version string }{ cliName, cmd, cmd.Flags(), subCommands, version.Version, }) tabOut.Flush() return nil }
func usageFunc(cmd *cobra.Command) error { subCommands := getSubCommands(cmd) tabOut := getTabOutWithWriter(os.Stdout) commandUsageTemplate.Execute(tabOut, struct { Cmd *cobra.Command LocalFlags string GlobalFlags string SubCommands []*cobra.Command Version string }{ cmd, rktFlagUsages(cmd.LocalFlags()), rktFlagUsages(cmd.InheritedFlags()), subCommands, version.Version, }) tabOut.Flush() return nil }
// getStage1Hash will try to fetch stage1 from store if it is a // default one. If that fails it will try to get via usual fetching // from disk or network. // // As a special case, if stage1 image path is a default and not // overriden by --stage1-image flag and it is has no scheme, it will // try to fetch it from two places on disk - from the path directly if // it is absolute and then from the same directory where rkt binary // resides. // // The passed command must have "stage1-image" string flag registered. func getStage1Hash(s *store.Store, cmd *cobra.Command) (*types.Hash, error) { fn := &finder{ imageActionData: imageActionData{ s: s, }, storeOnly: false, noStore: false, withDeps: false, } imageFlag := cmd.Flags().Lookup(stage1ImageFlagName) if imageFlag == nil { panic(fmt.Sprintf("Expected flag --%s to be registered in command %s", stage1ImageFlagName, cmd.Name())) } path := imageFlag.Value.String() if path == defaultStage1Image { return getDefaultStage1Hash(fn, imageFlag.Changed) } return getCustomStage1Hash(fn, path) }
// getStage1Hash will try to fetch stage1 from store if it is a // default one. If that fails it will try to get via usual fetching // from disk or network. // // As a special case, if stage1 image path is a default and not // overriden by --stage1-image flag and it is has no scheme, it will // try to fetch it from two places on disk - from the path directly if // it is absolute and then from the same directory where rkt binary // resides. // // The passed command must have "stage1-image" string flag registered. func getStage1Hash(s *store.Store, cmd *cobra.Command) (*types.Hash, error) { fn := &image.Finder{ S: s, InsecureFlags: globalFlags.InsecureFlags, TrustKeysFromHttps: globalFlags.TrustKeysFromHttps, StoreOnly: false, NoStore: false, WithDeps: false, } imageFlag := cmd.Flags().Lookup(stage1ImageFlagName) if imageFlag == nil { panic(fmt.Sprintf("Expected flag --%s to be registered in command %s", stage1ImageFlagName, cmd.Name())) } path := imageFlag.Value.String() if path == defaultStage1Image { return getDefaultStage1Hash(fn, imageFlag.Changed) } return getCustomStage1Hash(fn, path) }
func runImageCatManifest(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("image cat-manifest: cannot open store: %v", err) return 1 } key, err := getKeyFromAppOrHash(s, args[0]) if err != nil { stderr("image cat-manifest: %v", err) return 1 } manifest, err := s.GetImageManifest(key) if err != nil { stderr("image cat-manifest: cannot get image manifest: %v", err) return 1 } var b []byte if flagPrettyPrint { b, err = json.MarshalIndent(manifest, "", "\t") } else { b, err = json.Marshal(manifest) } if err != nil { stderr("image cat-manifest: cannot read the image manifest: %v", err) return 1 } stdout(string(b)) return 0 }
func runEnter(cmd *cobra.Command, args []string) (exit int) { if len(args) < 1 { cmd.Usage() return 1 } podUUID, err := resolveUUID(args[0]) if err != nil { stderr("Unable to resolve UUID: %v", err) return 1 } p, err := getPod(podUUID) if err != nil { stderr("Failed to open pod %q: %v", podUUID, err) return 1 } defer p.Close() if !p.isRunning() { stderr("Pod %q isn't currently running", podUUID) return 1 } podPID, err := p.getPID() if err != nil { stderr("Unable to determine the pid for pod %q: %v", podUUID, err) return 1 } appName, err := getAppName(p) if err != nil { stderr("Unable to determine app name: %v", err) return 1 } argv, err := getEnterArgv(p, args) if err != nil { stderr("Enter failed: %v", err) return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("Cannot open store: %v", err) return 1 } stage1ID, err := p.getStage1Hash() if err != nil { stderr("Error getting stage1 hash") return 1 } stage1RootFS := s.GetTreeStoreRootFS(stage1ID.String()) if err = stage0.Enter(p.path(), podPID, *appName, stage1RootFS, argv); err != nil { stderr("Enter failed: %v", err) return 1 } // not reached when stage0.Enter execs /enter return 0 }
func runRun(cmd *cobra.Command, args []string) (exit int) { err := parseApps(&rktApps, args, cmd.Flags(), true) if err != nil { stderr("run: error parsing app image arguments: %v", err) return 1 } if len(flagPorts) > 0 && !flagPrivateNet.Any() { stderr("--port flag requires --private-net") return 1 } if len(flagPodManifest) > 0 && (len(flagVolumes) > 0 || len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || rktApps.Count() > 0 || flagLocal) { stderr("conflicting flags set with --pod-manifest (see --help)") return 1 } if globalFlags.Dir == "" { log.Printf("dir unset - using temporary directory") var err error globalFlags.Dir, err = ioutil.TempDir("", "rkt") if err != nil { stderr("error creating temporary directory: %v", err) return 1 } } if flagInteractive && rktApps.Count() > 1 { stderr("run: interactive option only supports one image") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("run: must provide at least one image or specify the pod manifest") return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("run: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("run: cannot get configuration: %v", err) return 1 } fn := &finder{ imageActionData: imageActionData{ s: s, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, local: flagLocal, withDeps: false, } s1img, err := fn.findImage(flagStage1Image, "", false) if err != nil { stderr("Error finding stage1 image %q: %v", flagStage1Image, err) return 1 } fn.ks = getKeystore() fn.withDeps = true if err := fn.findImages(&rktApps); err != nil { stderr("%v", err) return 1 } p, err := newPod() if err != nil { stderr("Error creating new pod: %v", err) return 1 } processLabel, mountLabel, err := label.InitLabels(nil) if err != nil { stderr("Error initialising SELinux: %v", err) return 1 } cfg := stage0.CommonConfig{ MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Volumes = []types.Volume(flagVolumes) pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } err = stage0.Prepare(pcfg, p.path(), p.uuid) if err != nil { stderr("run: error setting up stage0: %v", err) return 1 } // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr("Error getting pod lock fd: %v", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.xToRun(); err != nil { stderr("run: unable to transition to run: %v", err) return 1 } rcfg := stage0.RunConfig{ CommonConfig: cfg, PrivateNet: flagPrivateNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, LocalConfig: globalFlags.LocalConfigDir, } imgs, err := p.getApps() if err != nil { stderr("run: cannot get the image hashes in the pod manifest: %v", err) return 1 } rcfg.Images = imgs stage0.Run(rcfg, p.path()) // execs, never returns return 1 }
func runRun(cmd *cobra.Command, args []string) (exit int) { privateUsers := uid.NewBlankUidRange() err := parseApps(&rktApps, args, cmd.Flags(), true) if err != nil { stderr("run: error parsing app image arguments: %v", err) return 1 } if flagStoreOnly && flagNoStore { stderr("both --store-only and --no-store specified") return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr("run: --private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(uid.DefaultRangeCount) } if len(flagPorts) > 0 && flagNet.None() { stderr("--port flag does not work with 'none' networking") return 1 } if len(flagPorts) > 0 && flagNet.Host() { stderr("--port flag does not work with 'host' networking") return 1 } if flagMDSRegister && flagNet.None() { stderr("--mds-register flag does not work with --net=none. Please use 'host', 'default' or an equivalent network") return 1 } if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || rktApps.Count() > 0 || flagStoreOnly || flagNoStore) { stderr("conflicting flags set with --pod-manifest (see --help)") return 1 } if flagInteractive && rktApps.Count() > 1 { stderr("run: interactive option only supports one image") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("run: must provide at least one image or specify the pod manifest") return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("run: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("run: cannot get configuration: %v", err) return 1 } fn := &finder{ imageActionData: imageActionData{ s: s, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, storeOnly: flagStoreOnly, noStore: flagNoStore, withDeps: false, } s1img, err := getStage1Hash(s, cmd) if err != nil { stderr("%v", err) return 1 } fn.ks = getKeystore() fn.withDeps = true if err := fn.findImages(&rktApps); err != nil { stderr("%v", err) return 1 } p, err := newPod() if err != nil { stderr("Error creating new pod: %v", err) return 1 } // if requested, write out pod UUID early so "rkt rm" can // clean it up even if something goes wrong if flagUUIDFileSave != "" { if err := writeUUIDToFile(p.uuid, flagUUIDFileSave); err != nil { stderr("Error saving pod UUID to file: %v", err) return 1 } } processLabel, mountLabel, err := label.InitLabels(nil) if err != nil { stderr("Error initialising SELinux: %v", err) return 1 } cfg := stage0.CommonConfig{ MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), PrivateUsers: privateUsers, } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr("rkt: cannot get shared prepare lock: %v", err) return 1 } err = stage0.Prepare(pcfg, p.path(), p.uuid) if err != nil { stderr("run: error setting up stage0: %v", err) keyLock.Close() return 1 } keyLock.Close() // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr("Error getting pod lock fd: %v", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.xToRun(); err != nil { stderr("run: unable to transition to run: %v", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr("run: group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } rcfg := stage0.RunConfig{ CommonConfig: cfg, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, LocalConfig: globalFlags.LocalConfigDir, RktGid: rktgid, } apps, err := p.getApps() if err != nil { stderr("run: cannot get the appList in the pod manifest: %v", err) return 1 } rcfg.Apps = apps stage0.Run(rcfg, p.path(), globalFlags.Dir) // execs, never returns return 1 }
func runPrepare(cmd *cobra.Command, args []string) (exit int) { var err error origStdout := os.Stdout if flagQuiet { if os.Stdout, err = os.Open("/dev/null"); err != nil { stderr("prepare: unable to open /dev/null") return 1 } } if err = parseApps(&rktApps, args, cmd.Flags(), true); err != nil { stderr("prepare: error parsing app image arguments: %v", err) return 1 } if len(flagPodManifest) > 0 && (len(flagVolumes) > 0 || len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || flagLocal) { stderr("prepare: conflicting flags set with --pod-manifest (see --help)") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("prepare: must provide at least one image or specify the pod manifest") return 1 } if globalFlags.Dir == "" { log.Printf("dir unset - using temporary directory") globalFlags.Dir, err = ioutil.TempDir("", "rkt") if err != nil { stderr("prepare: error creating temporary directory: %v", err) return 1 } } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("prepare: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("prepare: cannot get configuration: %v", err) return 1 } fn := &finder{ imageActionData: imageActionData{ s: s, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, local: flagLocal, withDeps: false, } s1img, err := getStage1Hash(s, flagStage1Image) if err != nil { stderr("prepare: %v", err) return 1 } fn.ks = getKeystore() fn.withDeps = true if err := fn.findImages(&rktApps); err != nil { stderr("%v", err) return 1 } p, err := newPod() if err != nil { stderr("prepare: error creating new pod: %v", err) return 1 } cfg := stage0.CommonConfig{ Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Volumes = []types.Volume(flagVolumes) pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } if err = stage0.Prepare(pcfg, p.path(), p.uuid); err != nil { stderr("prepare: error setting up stage0: %v", err) return 1 } if err := p.sync(); err != nil { stderr("prepare: error syncing pod data: %v", err) return 1 } if err := p.xToPrepared(); err != nil { stderr("prepare: error transitioning to prepared: %v", err) return 1 } os.Stdout = origStdout // restore output in case of --quiet stdout("%s", p.uuid.String()) return 0 }
func runRunPrepared(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } p, err := getPodFromUUIDString(args[0]) if err != nil { stderr("prepared-run: problem retrieving pod: %v", err) return 1 } defer p.Close() s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("prepared-run: cannot open store: %v", err) return 1 } if !p.isPrepared { stderr("prepared-run: pod %q is not prepared", p.uuid) return 1 } if flagInteractive { ac, err := p.getAppCount() if err != nil { stderr("prepared-run: cannot get pod's app count: %v", err) return 1 } if ac > 1 { stderr("prepared-run: interactive option only supports pods with one app") return 1 } } // Make sure we have a metadata service available before we move to // run state so that the user can rerun the command without needing // to prepare the image again. if flagMDSRegister { if err := stage0.CheckMdsAvailability(); err != nil { stderr("prepare-run: %v", err) return 1 } } if err := p.xToRun(); err != nil { stderr("prepared-run: cannot transition to run: %v", err) return 1 } lfd, err := p.Fd() if err != nil { stderr("prepared-run: unable to get lock fd: %v", err) return 1 } apps, err := p.getApps() if err != nil { stderr("prepared-run: unable to get app list: %v", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr("prepared-run: group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } rcfg := stage0.RunConfig{ CommonConfig: stage0.CommonConfig{ Store: s, UUID: p.uuid, Debug: globalFlags.Debug, }, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, Apps: apps, RktGid: rktgid, } if globalFlags.Debug { stage0.InitDebug() } stage0.Run(rcfg, p.path(), globalFlags.Dir) // execs, never returns return 1 }
func runImageRender(cmd *cobra.Command, args []string) (exit int) { if len(args) != 2 { cmd.Usage() return 1 } outputDir := args[1] s, err := store.NewStore(getDataDir()) if err != nil { stderr("image render: cannot open store: %v", err) return 1 } key, err := getStoreKeyFromAppOrHash(s, args[0]) if err != nil { stderr("image render: %v", err) return 1 } id, _, err := s.RenderTreeStore(key, false) if err != nil { stderr("image render: error rendering ACI: %v", err) return 1 } if _, err := s.CheckTreeStore(id); err != nil { stderr("image render: warning: tree cache is in a bad state. Rebuilding...") var err error if id, _, err = s.RenderTreeStore(key, true); err != nil { stderr("image render: error rendering ACI: %v", err) return 1 } } if _, err := os.Stat(outputDir); err == nil { if !flagRenderOverwrite { stderr("image render: output directory exists (try --overwrite)") return 1 } // don't allow the user to delete the root filesystem by mistake if outputDir == "/" { stderr("image extract: this would delete your root filesystem. Refusing.") return 1 } if err := os.RemoveAll(outputDir); err != nil { stderr("image render: error removing existing output dir: %v", err) return 1 } } rootfsOutDir := outputDir if !flagRenderRootfsOnly { if err := os.MkdirAll(outputDir, 0755); err != nil { stderr("image render: error creating output directory: %v", err) return 1 } rootfsOutDir = filepath.Join(rootfsOutDir, "rootfs") manifest, err := s.GetImageManifest(key) if err != nil { stderr("image render: error getting manifest: %v", err) return 1 } mb, err := json.Marshal(manifest) if err != nil { stderr("image render: error marshalling image manifest: %v", err) return 1 } if err := ioutil.WriteFile(filepath.Join(outputDir, "manifest"), mb, 0700); err != nil { stderr("image render: error writing image manifest: %v", err) return 1 } } cachedTreePath := s.GetTreeStoreRootFS(id) if err := fileutil.CopyTree(cachedTreePath, rootfsOutDir, uid.NewBlankUidRange()); err != nil { stderr("image render: error copying ACI rootfs: %v", err) return 1 } return 0 }
func runImageExtract(cmd *cobra.Command, args []string) (exit int) { if len(args) != 2 { cmd.Usage() return 1 } outputDir := args[1] s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("image extract: cannot open store: %v", err) return 1 } key, err := getStoreKeyFromAppOrHash(s, args[0]) if err != nil { stderr("image extract: %v", err) return 1 } aci, err := s.ReadStream(key) if err != nil { stderr("image extract: error reading ACI from the store: %v", err) return 1 } // ExtractTar needs an absolute path absOutputDir, err := filepath.Abs(outputDir) if err != nil { stderr("image extract: error converting output to an absolute path: %v", err) return 1 } if _, err := os.Stat(absOutputDir); err == nil { if !flagExtractOverwrite { stderr("image extract: output directory exists (try --overwrite)") return 1 } // don't allow the user to delete the root filesystem by mistake if absOutputDir == "/" { stderr("image extract: this would delete your root filesystem. Refusing.") return 1 } if err := os.RemoveAll(absOutputDir); err != nil { stderr("image extract: error removing existing output dir: %v", err) return 1 } } // if the user only asks for the rootfs we extract the image to a temporary // directory and then move/copy the rootfs to the output directory, if not // we just extract the image to the output directory extractDir := absOutputDir if flagExtractRootfsOnly { rktTmpDir, err := s.TmpDir() if err != nil { stderr("image extract: error creating rkt temporary directory: %v", err) return 1 } tmpDir, err := ioutil.TempDir(rktTmpDir, "rkt-image-extract-") if err != nil { stderr("image extract: error creating temporary directory: %v", err) return 1 } defer os.RemoveAll(tmpDir) extractDir = tmpDir } else { if err := os.MkdirAll(absOutputDir, 0755); err != nil { stderr("image extract: error creating output directory: %v", err) return 1 } } if err := tar.ExtractTar(aci, extractDir, false, uid.NewBlankUidRange(), nil); err != nil { stderr("image extract: error extracting ACI: %v", err) return 1 } if flagExtractRootfsOnly { rootfsDir := filepath.Join(extractDir, "rootfs") if err := os.Rename(rootfsDir, absOutputDir); err != nil { if e, ok := err.(*os.LinkError); ok && e.Err == syscall.EXDEV { // it's on a different device, fall back to copying if err := fileutil.CopyTree(rootfsDir, absOutputDir, uid.NewBlankUidRange()); err != nil { stderr("image extract: error copying ACI rootfs: %v", err) return 1 } } else { stderr("image extract: error moving ACI rootfs: %v", err) return 1 } } } return 0 }
func runRunPrepared(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } podUUID, err := resolveUUID(args[0]) if err != nil { stderr("Unable to resolve UUID: %v", err) return 1 } if globalFlags.Dir == "" { log.Printf("dir unset - using temporary directory") var err error globalFlags.Dir, err = ioutil.TempDir("", "rkt") if err != nil { stderr("error creating temporary directory: %v", err) return 1 } } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("prepared-run: cannot open store: %v", err) return 1 } p, err := getPod(podUUID.String()) if err != nil { stderr("prepared-run: cannot get pod: %v", err) return 1 } if !p.isPrepared { stderr("prepared-run: pod %q is not prepared", podUUID.String()) return 1 } if flagInteractive { ac, err := p.getAppCount() if err != nil { stderr("prepared-run: cannot get pod's app count: %v", err) return 1 } if ac > 1 { stderr("prepared-run: interactive option only supports pods with one app") return 1 } } if err := p.xToRun(); err != nil { stderr("prepared-run: cannot transition to run: %v", err) return 1 } lfd, err := p.Fd() if err != nil { stderr("prepared-run: unable to get lock fd: %v", err) return 1 } s1img, err := p.getStage1Hash() if err != nil { stderr("prepared-run: unable to get stage1 Hash: %v", err) return 1 } apps, err := p.getApps() if err != nil { stderr("prepared-run: unable to get app list: %v", err) return 1 } rcfg := stage0.RunConfig{ CommonConfig: stage0.CommonConfig{ Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, }, PrivateNet: flagPrivateNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, Apps: apps, } stage0.Run(rcfg, p.path()) // execs, never returns return 1 }
func runPrepare(cmd *cobra.Command, args []string) (exit int) { var err error origStdout := os.Stdout privateUsers := uid.NewBlankUidRange() if flagQuiet { if os.Stdout, err = os.Open("/dev/null"); err != nil { stderr("prepare: unable to open /dev/null: %v", err) return 1 } } if flagStoreOnly && flagNoStore { stderr("both --store-only and --no-store specified") return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr("prepare: --private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(uid.DefaultRangeCount) } if err = parseApps(&rktApps, args, cmd.Flags(), true); err != nil { stderr("prepare: error parsing app image arguments: %v", err) return 1 } if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || flagStoreOnly || flagNoStore) { stderr("prepare: conflicting flags set with --pod-manifest (see --help)") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("prepare: must provide at least one image or specify the pod manifest") return 1 } s, err := store.NewStore(getDataDir()) if err != nil { stderr("prepare: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("prepare: cannot get configuration: %v", err) return 1 } s1img, err := getStage1Hash(s, cmd) if err != nil { stderr("prepare: %v", err) return 1 } fn := &image.Finder{ S: s, Ks: getKeystore(), Headers: config.AuthPerHost, DockerAuth: config.DockerCredentialsPerRegistry, InsecureFlags: globalFlags.InsecureFlags, Debug: globalFlags.Debug, TrustKeysFromHttps: globalFlags.TrustKeysFromHttps, StoreOnly: flagStoreOnly, NoStore: flagNoStore, WithDeps: true, } if err := fn.FindImages(&rktApps); err != nil { stderr("prepare: %v", err) return 1 } p, err := newPod() if err != nil { stderr("prepare: error creating new pod: %v", err) return 1 } cfg := stage0.CommonConfig{ Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: &cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), PrivateUsers: privateUsers, } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr("rkt: cannot get shared prepare lock: %v", err) return 1 } if err = stage0.Prepare(pcfg, p.path(), p.uuid); err != nil { stderr("prepare: error setting up stage0: %v", err) keyLock.Close() return 1 } keyLock.Close() if err := p.sync(); err != nil { stderr("prepare: error syncing pod data: %v", err) return 1 } if err := p.xToPrepared(); err != nil { stderr("prepare: error transitioning to prepared: %v", err) return 1 } os.Stdout = origStdout // restore output in case of --quiet stdout("%s", p.uuid.String()) return 0 }