func init() { v, err := types.NewSemVer(version) if err != nil { panic(err) } AppContainerVersion = *v }
func parseVersion(input string) (rktVersion, error) { nsv, err := appctypes.NewSemVer(input) if err != nil { return nil, err } return rktVersion{int(nsv.Major), int(nsv.Minor), int(nsv.Patch)}, nil }
func (p *Pod) writePodManifest(apps []schema.RuntimeApp) error { m := p.manifest.Pod ver, _ := types.NewSemVer("0.6.1") manifest := schema.PodManifest{ ACKind: "PodManifest", ACVersion: *ver, Apps: apps, Volumes: m.Volumes, Isolators: m.Isolators, Annotations: m.Annotations, Ports: m.Ports} return WritePodManifest(&manifest, p.target+pathPodManifestJson) }
func (p *Pod) writePodManifest(apps []schema.RuntimeApp) { m := p.manifest.Pod ver, _ := types.NewSemVer("0.6.1") manifest := schema.PodManifest{ ACKind: "PodManifest", ACVersion: *ver, Apps: apps, Volumes: m.Volumes, Isolators: m.Isolators, Annotations: m.Annotations, Ports: m.Ports} utils.WritePodManifest(&manifest, p.target+POD_TARGET_MANIFEST) }
// 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 GenerateManifest(layerData types.DockerImageData, dockerURL *types.ParsedDockerURL) (*schema.ImageManifest, error) { dockerConfig := layerData.Config genManifest := &schema.ImageManifest{} appURL := "" // omit docker hub index URL in app name if dockerURL.IndexURL != defaultIndex { appURL = dockerURL.IndexURL + "/" } appURL += dockerURL.ImageName + "-" + layerData.ID appURL, err := appctypes.SanitizeACIdentifier(appURL) if err != nil { return nil, err } name := appctypes.MustACIdentifier(appURL) genManifest.Name = *name acVersion, err := appctypes.NewSemVer(schemaVersion) if err != nil { panic("invalid appc spec version") } genManifest.ACVersion = *acVersion genManifest.ACKind = appctypes.ACKind(schema.ImageManifestKind) var ( labels appctypes.Labels parentLabels appctypes.Labels annotations appctypes.Annotations ) layer := appctypes.MustACIdentifier("layer") labels = append(labels, appctypes.Label{Name: *layer, Value: layerData.ID}) tag := dockerURL.Tag version := appctypes.MustACIdentifier("version") labels = append(labels, appctypes.Label{Name: *version, Value: tag}) if layerData.OS != "" { os := appctypes.MustACIdentifier("os") labels = append(labels, appctypes.Label{Name: *os, Value: layerData.OS}) parentLabels = append(parentLabels, appctypes.Label{Name: *os, Value: layerData.OS}) if layerData.Architecture != "" { arch := appctypes.MustACIdentifier("arch") labels = append(labels, appctypes.Label{Name: *arch, Value: layerData.Architecture}) parentLabels = append(parentLabels, appctypes.Label{Name: *arch, Value: layerData.Architecture}) } } if layerData.Author != "" { authorsKey := appctypes.MustACIdentifier("authors") annotations = append(annotations, appctypes.Annotation{Name: *authorsKey, Value: layerData.Author}) } epoch := time.Unix(0, 0) if !layerData.Created.Equal(epoch) { createdKey := appctypes.MustACIdentifier("created") annotations = append(annotations, appctypes.Annotation{Name: *createdKey, Value: layerData.Created.Format(time.RFC3339)}) } if layerData.Comment != "" { commentKey := appctypes.MustACIdentifier("docker-comment") annotations = append(annotations, appctypes.Annotation{Name: *commentKey, Value: layerData.Comment}) } annotations = append(annotations, appctypes.Annotation{Name: *appctypes.MustACIdentifier(appcDockerV1RegistryURL), Value: dockerURL.IndexURL}) annotations = append(annotations, appctypes.Annotation{Name: *appctypes.MustACIdentifier(appcDockerV1Repository), Value: dockerURL.ImageName}) annotations = append(annotations, appctypes.Annotation{Name: *appctypes.MustACIdentifier(appcDockerV1ImageID), Value: layerData.ID}) annotations = append(annotations, appctypes.Annotation{Name: *appctypes.MustACIdentifier(appcDockerV1ParentImageID), Value: layerData.Parent}) genManifest.Labels = labels genManifest.Annotations = annotations if dockerConfig != nil { exec := getExecCommand(dockerConfig.Entrypoint, dockerConfig.Cmd) if exec != nil { user, group := parseDockerUser(dockerConfig.User) var env appctypes.Environment for _, v := range dockerConfig.Env { parts := strings.SplitN(v, "=", 2) env.Set(parts[0], parts[1]) } app := &appctypes.App{ Exec: exec, User: user, Group: group, Environment: env, WorkingDirectory: dockerConfig.WorkingDir, } app.MountPoints, err = convertVolumesToMPs(dockerConfig.Volumes) if err != nil { return nil, err } app.Ports, err = convertPorts(dockerConfig.ExposedPorts, dockerConfig.PortSpecs) if err != nil { return nil, err } genManifest.App = app } } if layerData.Parent != "" { indexPrefix := "" // omit docker hub index URL in app name if dockerURL.IndexURL != defaultIndex { indexPrefix = dockerURL.IndexURL + "/" } parentImageNameString := indexPrefix + dockerURL.ImageName + "-" + layerData.Parent parentImageNameString, err := appctypes.SanitizeACIdentifier(parentImageNameString) if err != nil { return nil, err } parentImageName := appctypes.MustACIdentifier(parentImageNameString) genManifest.Dependencies = append(genManifest.Dependencies, appctypes.Dependency{ImageName: *parentImageName, Labels: parentLabels}) annotations = append(annotations, appctypes.Annotation{Name: *appctypes.MustACIdentifier(appcDockerV1Tag), Value: dockerURL.Tag}) } return genManifest, 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 }
// GenerateManifest converts the docker manifest format to an appc // ImageManifest. func GenerateManifest(layerData types.DockerImageData, dockerURL *types.ParsedDockerURL) (*schema.ImageManifest, error) { dockerConfig := layerData.Config genManifest := &schema.ImageManifest{} appURL := "" appURL = dockerURL.IndexURL + "/" appURL += dockerURL.ImageName + "-" + layerData.ID appURL, err := appctypes.SanitizeACIdentifier(appURL) if err != nil { return nil, err } name := appctypes.MustACIdentifier(appURL) genManifest.Name = *name acVersion, err := appctypes.NewSemVer(schema.AppContainerVersion.String()) if err != nil { panic("invalid appc spec version") } genManifest.ACVersion = *acVersion genManifest.ACKind = appctypes.ACKind(schema.ImageManifestKind) var annotations appctypes.Annotations labels := make(map[appctypes.ACIdentifier]string) parentLabels := make(map[appctypes.ACIdentifier]string) addLabel := func(key, val string) { if key != "" && val != "" { labels[*appctypes.MustACIdentifier(key)] = val } } addParentLabel := func(key, val string) { if key != "" && val != "" { parentLabels[*appctypes.MustACIdentifier(key)] = val } } addAnno := func(key, val string) { if key != "" && val != "" { annotations.Set(*appctypes.MustACIdentifier(key), val) } } addLabel("layer", layerData.ID) addLabel("version", dockerURL.Tag) addLabel("os", layerData.OS) addParentLabel("os", layerData.OS) addLabel("arch", layerData.Architecture) addParentLabel("arch", layerData.OS) addAnno("authors", layerData.Author) epoch := time.Unix(0, 0) if !layerData.Created.Equal(epoch) { addAnno("created", layerData.Created.Format(time.RFC3339)) } addAnno("docker-comment", layerData.Comment) addAnno(common.AppcDockerRegistryURL, dockerURL.IndexURL) addAnno(common.AppcDockerRepository, dockerURL.ImageName) addAnno(common.AppcDockerImageID, layerData.ID) addAnno(common.AppcDockerParentImageID, layerData.Parent) if dockerConfig != nil { exec := getExecCommand(dockerConfig.Entrypoint, dockerConfig.Cmd) if exec != nil { user, group := parseDockerUser(dockerConfig.User) var env appctypes.Environment for _, v := range dockerConfig.Env { parts := strings.SplitN(v, "=", 2) env.Set(parts[0], parts[1]) } app := &appctypes.App{ Exec: exec, User: user, Group: group, Environment: env, WorkingDirectory: dockerConfig.WorkingDir, } app.MountPoints, err = convertVolumesToMPs(dockerConfig.Volumes) if err != nil { return nil, err } app.Ports, err = convertPorts(dockerConfig.ExposedPorts, dockerConfig.PortSpecs) if err != nil { return nil, err } ep, cmd, err := generateEPCmdAnnotation(dockerConfig.Entrypoint, dockerConfig.Cmd) if err != nil { return nil, err } if len(ep) > 0 { addAnno(common.AppcDockerEntrypoint, ep) } if len(cmd) > 0 { addAnno(common.AppcDockerCmd, cmd) } genManifest.App = app } } if layerData.Parent != "" { indexPrefix := "" // omit docker hub index URL in app name indexPrefix = dockerURL.IndexURL + "/" parentImageNameString := indexPrefix + dockerURL.ImageName + "-" + layerData.Parent parentImageNameString, err := appctypes.SanitizeACIdentifier(parentImageNameString) if err != nil { return nil, err } parentImageName := appctypes.MustACIdentifier(parentImageNameString) plbl, err := appctypes.LabelsFromMap(labels) if err != nil { return nil, err } genManifest.Dependencies = append(genManifest.Dependencies, appctypes.Dependency{ImageName: *parentImageName, Labels: plbl}) addAnno(common.AppcDockerTag, dockerURL.Tag) } genManifest.Labels, err = appctypes.LabelsFromMap(labels) if err != nil { return nil, err } genManifest.Annotations = annotations return genManifest, 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 }