//rktDirectory string, ociConfig string, ociRuntimeConfig string, ociDirectory string func (this *oci2rkt) makePod() (err error) { //1.covert to pod this.podManifest.ACVersion = types.SemVer{ Major: 0, Minor: 8, Patch: 0, PreRelease: "", Metadata: "", } this.podManifest.ACKind = "PodManifest" /* this.podManifest.Apps = schema.AppList{ { Name: "oci", Image: schema.RuntimeImage{ ID: types.Hash{ Val: "", }, }, }, } */ runTimeImage := schema.RuntimeImage{} hash, err := types.NewHash("sha512-ca0bee4ecb888d10cf0816ebe7e16499230ab349bd3126976ab60b9b1db2e120") if err != nil { return err } runTimeImage.ID = *hash runTimeApp := schema.RuntimeApp{ Name: "oci", } runTimeApp.Image = runTimeImage this.podManifest.Apps = append(this.podManifest.Apps, runTimeApp) this.podManifest.Volumes = nil this.podManifest.Isolators = nil this.podManifest.Annotations = nil this.podManifest.Ports = nil //2.marshal podBuf, err := json.Marshal(this.podManifest) if err != nil { return err } //3.wirte pod file pod := this.RktBundlePath + "/pod" err = ioutil.WriteFile(pod, podBuf, 0755) if err != nil { return err } return nil }
// GenerateMounts maps MountPoint paths to volumes, returning a list of Mounts. func GenerateMounts(ra *schema.RuntimeApp, volumes map[types.ACName]types.Volume) []schema.Mount { app := ra.App mnts := make(map[string]schema.Mount) for _, m := range ra.Mounts { mnts[m.Path] = m } for _, mp := range app.MountPoints { // there's already an injected mount for this target path, skip if _, ok := mnts[mp.Path]; ok { continue } vol, ok := volumes[mp.Name] // there is no volume for this mount point, creating an "empty" volume // implicitly if !ok { defaultMode := "0755" defaultUID := 0 defaultGID := 0 emptyVol := types.Volume{ Name: mp.Name, Kind: "empty", Mode: &defaultMode, UID: &defaultUID, GID: &defaultGID, } log.Printf("warning: no volume specified for mount point %q, implicitly creating an \"empty\" volume. This volume will be removed when the pod is garbage-collected.", mp.Name) volumes[mp.Name] = emptyVol ra.Mounts = append(ra.Mounts, schema.Mount{Volume: mp.Name, Path: mp.Path}) } else { ra.Mounts = append(ra.Mounts, schema.Mount{Volume: vol.Name, Path: mp.Path}) } } return ra.Mounts }
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 }
// 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 }
func AddApp(cfg AddConfig) error { // there should be only one app in the config app := cfg.Apps.Last() if app == nil { return errors.New("no image specified") } am, err := cfg.Store.GetImageManifest(cfg.Image.String()) if err != nil { return err } var appName *types.ACName if app.Name != "" { appName, err = types.NewACName(app.Name) if err != nil { return err } } else { appName, err = imageNameToAppName(am.Name) if err != nil { return err } } pod, err := pkgPod.PodFromUUIDString(cfg.DataDir, cfg.UUID.String()) if err != nil { return errwrap.Wrap(errors.New("error loading pod"), err) } defer pod.Close() debug("locking pod manifest") if err := pod.ExclusiveLockManifest(); err != nil { return errwrap.Wrap(errors.New("failed to lock pod manifest"), err) } defer pod.UnlockManifest() pm, err := pod.SandboxManifest() if err != nil { return errwrap.Wrap(errors.New("cannot add application"), err) } if pm.Apps.Get(*appName) != nil { return fmt.Errorf("error: multiple apps with name %s", *appName) } if am.App == nil && app.Exec == "" { return fmt.Errorf("error: image %s has no app section and --exec argument is not provided", cfg.Image) } appInfoDir := common.AppInfoPath(cfg.PodPath, *appName) if err := os.MkdirAll(appInfoDir, common.DefaultRegularDirPerm); err != nil { return errwrap.Wrap(errors.New("error creating apps info directory"), err) } pcfg := PrepareConfig{ CommonConfig: cfg.CommonConfig, PrivateUsers: user.NewBlankUidRange(), } if cfg.UsesOverlay { privateUsers, err := preparedWithPrivateUsers(cfg.PodPath) if err != nil { log.FatalE("error reading user namespace information", err) } if err := pcfg.PrivateUsers.Deserialize([]byte(privateUsers)); err != nil { return err } } treeStoreID, err := prepareAppImage(pcfg, *appName, cfg.Image, cfg.PodPath, cfg.UsesOverlay) if err != nil { return errwrap.Wrap(fmt.Errorf("error preparing image %s", cfg.Image), err) } rcfg := RunConfig{ CommonConfig: cfg.CommonConfig, UseOverlay: cfg.UsesOverlay, RktGid: cfg.RktGid, } if err := setupAppImage(rcfg, *appName, cfg.Image, cfg.PodPath, cfg.UsesOverlay); err != nil { return fmt.Errorf("error setting up app image: %v", err) } if cfg.UsesOverlay { imgDir := filepath.Join(cfg.PodPath, "overlay", treeStoreID) if err := os.Chown(imgDir, -1, cfg.RktGid); err != nil { return err } } ra := schema.RuntimeApp{ Name: *appName, App: am.App, Image: schema.RuntimeImage{ Name: &am.Name, ID: cfg.Image, 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 } 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)) } // Let the app level environment override the environment variables. mergeEnvs(&ra.App.Environment, envs, true) } env := ra.App.Environment env.Set("AC_APP_NAME", appName.String()) envFilePath := filepath.Join(common.Stage1RootfsPath(cfg.PodPath), "rkt", "env", appName.String()) if err := common.WriteEnvFile(env, pcfg.PrivateUsers, envFilePath); err != nil { return err } debug("adding app to sandbox") pm.Apps = append(pm.Apps, ra) if err := pod.UpdateManifest(pm, cfg.PodPath); err != nil { return err } args := []string{ fmt.Sprintf("--debug=%t", cfg.Debug), fmt.Sprintf("--uuid=%s", cfg.UUID), fmt.Sprintf("--app=%s", appName), } if _, err := os.Create(common.AppCreatedPath(pod.Path(), appName.String())); err != nil { return err } ce := CrossingEntrypoint{ PodPath: cfg.PodPath, PodPID: cfg.PodPID, AppName: appName.String(), EntrypointName: appAddEntrypoint, EntrypointArgs: args, Interactive: false, } if err := ce.Run(); err != nil { return err } 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) } 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 }