// getAppName returns the app name to enter // If one was supplied in the flags then it's simply returned // If the PM contains a single app, that app's name is returned // If the PM has multiple apps, the names are printed and an error is returned func getAppName(p *pod) (*types.ACName, error) { if flagAppName != "" { return types.NewACName(flagAppName) } // figure out the app name, or show a list if multiple are present b, err := ioutil.ReadFile(common.PodManifestPath(p.path())) if err != nil { return nil, errwrap.Wrap(errors.New("error reading pod manifest"), err) } m := schema.PodManifest{} if err = m.UnmarshalJSON(b); err != nil { return nil, errwrap.Wrap(errors.New("invalid pod manifest"), err) } switch len(m.Apps) { case 0: return nil, fmt.Errorf("pod contains zero apps") case 1: return &m.Apps[0].Name, nil default: } stderr.Print("pod contains multiple apps:") for _, ra := range m.Apps { stderr.Printf("\t%v", ra.Name) } return nil, fmt.Errorf("specify app using \"rkt enter --app= ...\"") }
func WritePodManifest(im *schema.PodManifest, targetFile string) { buff, err := im.MarshalJSON() if err != nil { log.Get().Panic(err) } err = ioutil.WriteFile(targetFile, []byte(buff), 0644) if err != nil { log.Get().Panic(err) } }
func removeAppFromPodManifest(pm *schema.PodManifest, appName *types.ACName) { for i, app := range pm.Apps { if app.Name == *appName { pm.Apps = append(pm.Apps[:i], pm.Apps[i+1:]...) } } }
func ParseApps(pm *schema.PodManifest, args []string) error { for len(args) > 0 { if rest, rtapp, err := parseApp(args); err != nil { return err } else { pm.Apps = append(pm.Apps, *rtapp) args = rest } } return nil }
func (h *Host) ReifyPodManifest(pm *schema.PodManifest) (*schema.PodManifest, error) { for i, rtapp := range pm.Apps { img, err := h.getRuntimeImage(rtapp.Image) if err != nil { return nil, err } pm.Apps[i].Image.ID = *img.Hash app := rtapp.App if app == nil { app = img.Manifest.App } if app == nil { if len(rtapp.Mounts) > 0 { return nil, errors.New("No app (is it valid at all?), yet mounts given") } continue } mntpnts: for _, mntpnt := range app.MountPoints { var mnt *schema.Mount for _, mntc := range rtapp.Mounts { if mntc.Path == mntpnt.Path || mntc.Path == mntpnt.Name.String() { if mnt != nil { fmt.Printf("WARNING: multiple mounts for %v:%v, using first one") } else { mnt = &mntc } } } if mnt == nil { fmt.Printf("INFO: mount for %v:%v not found, inserting mount for volume %v\n", rtapp.Name, mntpnt.Name, mntpnt.Name) mnt = &schema.Mount{Path: mntpnt.Name.String(), Volume: mntpnt.Name} pm.Apps[i].Mounts = append(pm.Apps[i].Mounts, *mnt) } for _, vol := range pm.Volumes { if vol.Name == mnt.Volume { continue mntpnts } } fmt.Printf("INFO: volume %v not found, inserting empty volume\n", mnt.Volume) _mode := "0755" _ugid := 0 pm.Volumes = append(pm.Volumes, types.Volume{Name: mnt.Volume, Kind: "empty", Mode: &_mode, UID: &_ugid, GID: &_ugid}) } } return pm, nil }
func runList(cmd *cobra.Command, args []string) int { var errors []error tabBuffer := new(bytes.Buffer) tabOut := getTabOutWithWriter(tabBuffer) if !flagNoLegend { if flagFullOutput { fmt.Fprintf(tabOut, "UUID\tAPP\tIMAGE NAME\tIMAGE ID\tSTATE\tCREATED\tSTARTED\tNETWORKS\n") } else { fmt.Fprintf(tabOut, "UUID\tAPP\tIMAGE NAME\tSTATE\tCREATED\tSTARTED\tNETWORKS\n") } } if err := walkPods(includeMostDirs, func(p *pod) { pm := schema.PodManifest{} if !p.isPreparing && !p.isAbortedPrepare && !p.isExitedDeleting { // TODO(vc): we should really hold a shared lock here to prevent gc of the pod pmf, err := p.readFile(common.PodManifestPath("")) if err != nil { errors = append(errors, newPodListReadError(p, err)) return } if err := pm.UnmarshalJSON(pmf); err != nil { errors = append(errors, newPodListLoadError(p, err, pmf)) return } if len(pm.Apps) == 0 { errors = append(errors, newPodListZeroAppsError(p)) return } } type printedApp struct { uuid string appName string imgName string imgID string state string nets string created string started string } var appsToPrint []printedApp uuid := p.uuid.String() state := p.getState() nets := fmtNets(p.nets) created, err := p.getCreationTime() if err != nil { errors = append(errors, errwrap.Wrap(fmt.Errorf("unable to get creation time for pod %q", uuid), err)) } var createdStr string if flagFullOutput { createdStr = created.Format(defaultTimeLayout) } else { createdStr = humanize.Time(created) } started, err := p.getStartTime() if err != nil { errors = append(errors, errwrap.Wrap(fmt.Errorf("unable to get start time for pod %q", uuid), err)) } var startedStr string if !started.IsZero() { if flagFullOutput { startedStr = started.Format(defaultTimeLayout) } else { startedStr = humanize.Time(started) } } if !flagFullOutput { uuid = uuid[:8] } for _, app := range pm.Apps { imageName, err := getImageName(p, app.Name) if err != nil { errors = append(errors, newPodListLoadImageManifestError(p, err)) imageName = "--" } var imageID string if flagFullOutput { imageID = app.Image.ID.String()[:19] } appsToPrint = append(appsToPrint, printedApp{ uuid: uuid, appName: app.Name.String(), imgName: imageName, imgID: imageID, state: state, nets: nets, created: createdStr, started: startedStr, }) // clear those variables so they won't be // printed for another apps in the pod as they // are actually describing a pod, not an app uuid = "" state = "" nets = "" createdStr = "" startedStr = "" } // if we reached that point, then it means that the // pod and all its apps are valid, so they can be // printed for _, app := range appsToPrint { if flagFullOutput { fmt.Fprintf(tabOut, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", app.uuid, app.appName, app.imgName, app.imgID, app.state, app.created, app.started, app.nets) } else { fmt.Fprintf(tabOut, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", app.uuid, app.appName, app.imgName, app.state, app.created, app.started, app.nets) } } }); err != nil { stderr.PrintE("failed to get pod handles", err) return 1 } if len(errors) > 0 { sep := "----------------------------------------" stderr.Printf("%d error(s) encountered when listing pods:", len(errors)) stderr.Print(sep) for _, err := range errors { stderr.Error(err) stderr.Print(sep) } stderr.Print("misc:") stderr.Printf(" rkt's appc version: %s", schema.AppContainerVersion) stderr.Print(sep) // make a visible break between errors and the listing stderr.Print("") } tabOut.Flush() stdout.Print(tabBuffer) return 0 }
func (r *Runtime) newAppcRuntimeApp(pod *api.Pod, c api.Container, pullSecrets []api.Secret, manifest *appcschema.PodManifest) error { if err, _ := r.imagePuller.PullImage(pod, &c, pullSecrets); err != nil { return nil } imgManifest, err := r.getImageManifest(c.Image) if err != nil { return err } if imgManifest.App == nil { imgManifest.App = new(appctypes.App) } imageID, err := r.getImageID(c.Image) if err != nil { return err } hash, err := appctypes.NewHash(imageID) if err != nil { return err } opts, err := r.runtimeHelper.GenerateRunContainerOptions(pod, &c) if err != nil { return err } // create the container log file and make a mount pair. mnt, err := makeContainerLogMount(opts, &c) if err != nil { return err } ctx := securitycontext.DetermineEffectiveSecurityContext(pod, &c) if err := setApp(imgManifest.App, &c, opts, ctx, pod.Spec.SecurityContext); err != nil { return err } ra := appcschema.RuntimeApp{ Name: convertToACName(c.Name), Image: appcschema.RuntimeImage{ID: *hash}, App: imgManifest.App, Annotations: []appctypes.Annotation{ { Name: *appctypes.MustACIdentifier(k8sRktContainerHashAnno), Value: strconv.FormatUint(kubecontainer.HashContainer(&c), 10), }, }, } if mnt != nil { ra.Annotations = append(ra.Annotations, appctypes.Annotation{ Name: *appctypes.MustACIdentifier(k8sRktTerminationMessagePathAnno), Value: mnt.HostPath, }) manifest.Volumes = append(manifest.Volumes, appctypes.Volume{ Name: convertToACName(mnt.Name), Kind: "host", Source: mnt.HostPath, }) } manifest.Apps = append(manifest.Apps, ra) // Set global ports. for _, port := range opts.PortMappings { manifest.Ports = append(manifest.Ports, appctypes.ExposedPort{ Name: convertToACName(port.Name), HostPort: uint(port.HostPort), }) } return nil }
// generatePodManifest creates the pod manifest from the command line input. // It returns the pod manifest as []byte on success. // This is invoked if no pod manifest is specified at the command line. func generatePodManifest(cfg PrepareConfig, dir string) ([]byte, error) { pm := schema.PodManifest{ ACKind: "PodManifest", Apps: make(schema.AppList, 0), } v, err := types.NewSemVer(version.Version) if err != nil { return nil, errwrap.Wrap(errors.New("error creating version"), err) } pm.ACVersion = *v if err := cfg.Apps.Walk(func(app *apps.App) error { img := app.ImageID am, err := cfg.Store.GetImageManifest(img.String()) if err != nil { return errwrap.Wrap(errors.New("error getting the manifest"), err) } appName, err := imageNameToAppName(am.Name) if err != nil { return errwrap.Wrap(errors.New("error converting image name to app name"), err) } if err := prepareAppImage(cfg, *appName, img, dir, cfg.UseOverlay); err != nil { return errwrap.Wrap(fmt.Errorf("error setting up image %s", img), err) } if pm.Apps.Get(*appName) != nil { return fmt.Errorf("error: multiple apps with name %s", am.Name) } if am.App == nil && app.Exec == "" { return fmt.Errorf("error: image %s has no app section and --exec argument is not provided", img) } ra := schema.RuntimeApp{ // TODO(vc): leverage RuntimeApp.Name for disambiguating the apps Name: *appName, App: am.App, Image: schema.RuntimeImage{ Name: &am.Name, ID: img, Labels: am.Labels, }, Annotations: am.Annotations, Mounts: MergeMounts(cfg.Apps.Mounts, app.Mounts), } if execOverride := app.Exec; execOverride != "" { // Create a minimal App section if not present if am.App == nil { ra.App = &types.App{ User: strconv.Itoa(os.Getuid()), Group: strconv.Itoa(os.Getgid()), } } ra.App.Exec = []string{execOverride} } if execAppends := app.Args; execAppends != nil { ra.App.Exec = append(ra.App.Exec, execAppends...) } if memoryOverride := app.MemoryLimit; memoryOverride != nil { isolator := memoryOverride.AsIsolator() ra.App.Isolators = append(ra.App.Isolators, isolator) } if cpuOverride := app.CPULimit; cpuOverride != nil { isolator := cpuOverride.AsIsolator() ra.App.Isolators = append(ra.App.Isolators, isolator) } if cfg.InheritEnv || len(cfg.ExplicitEnv) > 0 { MergeEnvs(&ra.App.Environment, cfg.InheritEnv, cfg.ExplicitEnv) } pm.Apps = append(pm.Apps, ra) return nil }); err != nil { return nil, err } // TODO(jonboulle): check that app mountpoint expectations are // satisfied here, rather than waiting for stage1 pm.Volumes = cfg.Apps.Volumes pm.Ports = cfg.Ports pmb, err := json.Marshal(pm) if err != nil { return nil, errwrap.Wrap(errors.New("error marshalling pod manifest"), err) } return pmb, nil }
func BasicPodManifest() *schema.PodManifest { im := new(schema.PodManifest) im.UnmarshalJSON([]byte(POD_MANIFEST)) return im }
// generatePodManifest creates the pod manifest from the command line input. // It returns the pod manifest as []byte on success. // This is invoked if no pod manifest is specified at the command line. func generatePodManifest(cfg PrepareConfig, dir string) ([]byte, error) { pm := schema.PodManifest{ ACKind: "PodManifest", Apps: make(schema.AppList, 0), } v, err := types.NewSemVer(version.Version) if err != nil { return nil, errwrap.Wrap(errors.New("error creating version"), err) } pm.ACVersion = *v if err := cfg.Apps.Walk(func(app *apps.App) error { img := app.ImageID am, err := cfg.Store.GetImageManifest(img.String()) if err != nil { return errwrap.Wrap(errors.New("error getting the manifest"), err) } appName, err := imageNameToAppName(am.Name) if err != nil { return errwrap.Wrap(errors.New("error converting image name to app name"), err) } if err := prepareAppImage(cfg, *appName, img, dir, cfg.UseOverlay); err != nil { return errwrap.Wrap(fmt.Errorf("error setting up image %s", img), err) } if pm.Apps.Get(*appName) != nil { return fmt.Errorf("error: multiple apps with name %s", am.Name) } if am.App == nil && app.Exec == "" { return fmt.Errorf("error: image %s has no app section and --exec argument is not provided", img) } ra := schema.RuntimeApp{ // TODO(vc): leverage RuntimeApp.Name for disambiguating the apps Name: *appName, App: am.App, Image: schema.RuntimeImage{ Name: &am.Name, ID: img, Labels: am.Labels, }, Annotations: am.Annotations, Mounts: MergeMounts(cfg.Apps.Mounts, app.Mounts), } if execOverride := app.Exec; execOverride != "" { // Create a minimal App section if not present if am.App == nil { ra.App = &types.App{ User: strconv.Itoa(os.Getuid()), Group: strconv.Itoa(os.Getgid()), } } ra.App.Exec = []string{execOverride} } if execAppends := app.Args; execAppends != nil { ra.App.Exec = append(ra.App.Exec, execAppends...) } if memoryOverride := app.MemoryLimit; memoryOverride != nil { isolator := memoryOverride.AsIsolator() ra.App.Isolators = append(ra.App.Isolators, isolator) } if cpuOverride := app.CPULimit; cpuOverride != nil { isolator := cpuOverride.AsIsolator() ra.App.Isolators = append(ra.App.Isolators, isolator) } if app.CapsRetain != nil && app.CapsRemove != nil { return fmt.Errorf("error: cannot use both --cap-retain and --cap-remove on the same image") } // Delete existing caps isolators if the user wants to override // them with either --cap-retain or --cap-remove if app.CapsRetain != nil || app.CapsRemove != nil { for i := len(ra.App.Isolators) - 1; i >= 0; i-- { isolator := ra.App.Isolators[i] if _, ok := isolator.Value().(types.LinuxCapabilitiesSet); ok { ra.App.Isolators = append(ra.App.Isolators[:i], ra.App.Isolators[i+1:]...) } } } if capsRetain := app.CapsRetain; capsRetain != nil { isolator, err := capsRetain.AsIsolator() if err != nil { return err } ra.App.Isolators = append(ra.App.Isolators, *isolator) } else if capsRemove := app.CapsRemove; capsRemove != nil { isolator, err := capsRemove.AsIsolator() if err != nil { return err } ra.App.Isolators = append(ra.App.Isolators, *isolator) } if user := app.User; user != "" { ra.App.User = user } if group := app.Group; group != "" { ra.App.Group = group } // loading the environment from the lowest priority to highest if cfg.InheritEnv { // Inherit environment does not override app image environment mergeEnvs(&ra.App.Environment, os.Environ(), false) } mergeEnvs(&ra.App.Environment, cfg.EnvFromFile, true) mergeEnvs(&ra.App.Environment, cfg.ExplicitEnv, true) pm.Apps = append(pm.Apps, ra) return nil }); err != nil { return nil, err } // TODO(jonboulle): check that app mountpoint expectations are // satisfied here, rather than waiting for stage1 pm.Volumes = cfg.Apps.Volumes pm.Ports = cfg.Ports pmb, err := json.Marshal(pm) if err != nil { return nil, errwrap.Wrap(errors.New("error marshalling pod manifest"), err) } return pmb, nil }
// generatePodManifest creates the pod manifest from the command line input. // It returns the pod manifest as []byte on success. // This is invoked if no pod manifest is specified at the command line. func generatePodManifest(cfg PrepareConfig, dir string) ([]byte, error) { pm := schema.PodManifest{ ACKind: "PodManifest", Apps: make(schema.AppList, 0), } v, err := types.NewSemVer(version.Version) if err != nil { return nil, errwrap.Wrap(errors.New("error creating version"), err) } pm.ACVersion = *v if err := cfg.Apps.Walk(func(app *apps.App) error { img := app.ImageID am, err := cfg.Store.GetImageManifest(img.String()) if err != nil { return errwrap.Wrap(errors.New("error getting the manifest"), err) } var appName *types.ACName if app.Name != "" { appName, err = types.NewACName(app.Name) if err != nil { return errwrap.Wrap(errors.New("invalid app name format"), err) } } else { appName, err = imageNameToAppName(am.Name) if err != nil { return errwrap.Wrap(errors.New("error converting image name to app name"), err) } } if _, err := prepareAppImage(cfg, *appName, img, dir, cfg.UseOverlay); err != nil { return errwrap.Wrap(fmt.Errorf("error preparing image %s", img), err) } if pm.Apps.Get(*appName) != nil { return fmt.Errorf("error: multiple apps with name %s", am.Name) } if am.App == nil && app.Exec == "" { return fmt.Errorf("error: image %s has no app section and --exec argument is not provided", img) } ra := schema.RuntimeApp{ // TODO(vc): leverage RuntimeApp.Name for disambiguating the apps Name: *appName, App: am.App, Image: schema.RuntimeImage{ Name: &am.Name, ID: img, Labels: am.Labels, }, Mounts: MergeMounts(cfg.Apps.Mounts, app.Mounts), ReadOnlyRootFS: app.ReadOnlyRootFS, } if app.Exec != "" { // Create a minimal App section if not present if am.App == nil { ra.App = &types.App{ User: strconv.Itoa(os.Getuid()), Group: strconv.Itoa(os.Getgid()), } } ra.App.Exec = []string{app.Exec} } if app.Args != nil { ra.App.Exec = append(ra.App.Exec, app.Args...) } if app.WorkingDir != "" { ra.App.WorkingDirectory = app.WorkingDir } if err := prepareIsolators(app, ra.App); err != nil { return err } if app.User != "" { ra.App.User = app.User } if app.Group != "" { ra.App.Group = app.Group } if app.SupplementaryGIDs != nil { ra.App.SupplementaryGIDs = app.SupplementaryGIDs } if app.UserAnnotations != nil { ra.App.UserAnnotations = app.UserAnnotations } if app.UserLabels != nil { ra.App.UserLabels = app.UserLabels } // loading the environment from the lowest priority to highest if cfg.InheritEnv { // Inherit environment does not override app image environment mergeEnvs(&ra.App.Environment, os.Environ(), false) } mergeEnvs(&ra.App.Environment, cfg.EnvFromFile, true) mergeEnvs(&ra.App.Environment, cfg.ExplicitEnv, true) if app.Environments != nil { envs := make([]string, 0, len(app.Environments)) for name, value := range app.Environments { envs = append(envs, fmt.Sprintf("%s=%s", name, value)) } mergeEnvs(&ra.App.Environment, envs, true) } pm.Apps = append(pm.Apps, ra) return nil }); err != nil { return nil, err } // TODO(jonboulle): check that app mountpoint expectations are // satisfied here, rather than waiting for stage1 pm.Volumes = cfg.Apps.Volumes // Check to see if ports have any errors pm.Ports = cfg.Ports if _, err := commonnet.ForwardedPorts(&pm); err != nil { return nil, err } pm.Annotations = append(pm.Annotations, types.Annotation{ Name: "coreos.com/rkt/stage1/mutable", Value: strconv.FormatBool(cfg.Mutable), }) pm.UserAnnotations = cfg.UserAnnotations pm.UserLabels = cfg.UserLabels pmb, err := json.Marshal(pm) if err != nil { return nil, errwrap.Wrap(errors.New("error marshalling pod manifest"), err) } return pmb, nil }
// generatePodManifest creates the pod manifest from the command line input. // It returns the pod manifest as []byte on success. // This is invoked if no pod manifest is specified at the command line. func generatePodManifest(cfg PrepareConfig, dir string) ([]byte, error) { pm := schema.PodManifest{ ACKind: "PodManifest", Apps: make(schema.AppList, 0), } v, err := types.NewSemVer(version.Version) if err != nil { return nil, errwrap.Wrap(errors.New("error creating version"), err) } pm.ACVersion = *v if err := cfg.Apps.Walk(func(app *apps.App) error { img := app.ImageID am, err := cfg.Store.GetImageManifest(img.String()) if err != nil { return errwrap.Wrap(errors.New("error getting the manifest"), err) } appName, err := imageNameToAppName(am.Name) if err != nil { return errwrap.Wrap(errors.New("error converting image name to app name"), err) } if err := prepareAppImage(cfg, *appName, img, dir, cfg.UseOverlay); err != nil { return errwrap.Wrap(fmt.Errorf("error setting up image %s", img), err) } if pm.Apps.Get(*appName) != nil { return fmt.Errorf("error: multiple apps with name %s", am.Name) } if am.App == nil && app.Exec == "" { return fmt.Errorf("error: image %s has no app section and --exec argument is not provided", img) } ra := schema.RuntimeApp{ // TODO(vc): leverage RuntimeApp.Name for disambiguating the apps Name: *appName, App: am.App, Image: schema.RuntimeImage{ Name: &am.Name, ID: img, Labels: am.Labels, }, Mounts: MergeMounts(cfg.Apps.Mounts, app.Mounts), } if execOverride := app.Exec; execOverride != "" { // Create a minimal App section if not present if am.App == nil { ra.App = &types.App{ User: strconv.Itoa(os.Getuid()), Group: strconv.Itoa(os.Getgid()), } } ra.App.Exec = []string{execOverride} } if execAppends := app.Args; execAppends != nil { ra.App.Exec = append(ra.App.Exec, execAppends...) } if err := prepareIsolators(app, ra.App); err != nil { return err } if user := app.User; user != "" { ra.App.User = user } if group := app.Group; group != "" { ra.App.Group = group } // loading the environment from the lowest priority to highest if cfg.InheritEnv { // Inherit environment does not override app image environment mergeEnvs(&ra.App.Environment, os.Environ(), false) } mergeEnvs(&ra.App.Environment, cfg.EnvFromFile, true) mergeEnvs(&ra.App.Environment, cfg.ExplicitEnv, true) pm.Apps = append(pm.Apps, ra) return nil }); err != nil { return nil, err } // TODO(jonboulle): check that app mountpoint expectations are // satisfied here, rather than waiting for stage1 pm.Volumes = cfg.Apps.Volumes pm.Ports = cfg.Ports // TODO(sur): add to stage1-implementors-guide and to the spec pm.Annotations = append(pm.Annotations, types.Annotation{ Name: "coreos.com/rkt/stage1/mutable", Value: strconv.FormatBool(cfg.Mutable), }) pmb, err := json.Marshal(pm) if err != nil { return nil, errwrap.Wrap(errors.New("error marshalling pod manifest"), err) } return pmb, nil }