// writeEnvFile creates an environment file for given app name, the minimum // required environment variables by the appc spec will be set to sensible // defaults here if they're not provided by env. func writeEnvFile(p *stage1commontypes.Pod, env types.Environment, appName types.ACName, privateUsers string) error { ef := bytes.Buffer{} for dk, dv := range defaultEnv { if _, exists := env.Get(dk); !exists { fmt.Fprintf(&ef, "%s=%s\000", dk, dv) } } for _, e := range env { fmt.Fprintf(&ef, "%s=%s\000", e.Name, e.Value) } uidRange := uid.NewBlankUidRange() if err := uidRange.Deserialize([]byte(privateUsers)); err != nil { return err } envFilePath := EnvFilePath(p.Root, appName) if err := ioutil.WriteFile(envFilePath, ef.Bytes(), 0644); err != nil { return err } if uidRange.Shift != 0 && uidRange.Count != 0 { if err := os.Chown(envFilePath, int(uidRange.Shift), int(uidRange.Shift)); err != nil { return err } } return nil }
// writeEnvFile creates an environment file for given app name, the minimum // required environment variables by the appc spec will be set to sensible // defaults here if they're not provided by env. func writeEnvFile(p *stage1commontypes.Pod, env types.Environment, appName types.ACName, uidRange *user.UidRange, separator byte, envFilePath string) error { ef := bytes.Buffer{} for dk, dv := range defaultEnv { if _, exists := env.Get(dk); !exists { fmt.Fprintf(&ef, "%s=%s%c", dk, dv, separator) } } for _, e := range env { fmt.Fprintf(&ef, "%s=%s%c", e.Name, e.Value, separator) } if err := ioutil.WriteFile(envFilePath, ef.Bytes(), 0644); err != nil { return err } if uidRange.Shift != 0 && uidRange.Count != 0 { if err := os.Chown(envFilePath, int(uidRange.Shift), int(uidRange.Shift)); err != nil { return err } } return nil }
// mergeEnvs merges environment variables from env into the current appEnv // if override is set to true, then variables with the same name will be set to the value in env // env is expected to be in the os.Environ() key=value format func mergeEnvs(appEnv *types.Environment, env []string, override bool) { for _, ev := range env { pair := strings.SplitN(ev, "=", 2) if _, exists := appEnv.Get(pair[0]); override || !exists { appEnv.Set(pair[0], pair[1]) } } }
// WriteEnvFile creates an environment file for given app name, the minimum // required environment variables by the appc spec will be set to sensible // defaults here if they're not provided by env. func WriteEnvFile(env types.Environment, uidRange *user.UidRange, envFilePath string) error { ef := bytes.Buffer{} for dk, dv := range defaultEnv { if _, exists := env.Get(dk); !exists { fmt.Fprintf(&ef, "%s=%s\n", dk, dv) } } for _, e := range env { fmt.Fprintf(&ef, "%s=%s\n", e.Name, e.Value) } if err := ioutil.WriteFile(envFilePath, ef.Bytes(), 0644); err != nil { return err } if err := user.ShiftFiles([]string{envFilePath}, uidRange); err != nil { return err } return nil }
// MergeEnvs amends appEnv setting variables in setEnv before setting anything new from os.Environ if inheritEnv = true // setEnv is expected to be in the os.Environ() key=value format func MergeEnvs(appEnv *types.Environment, inheritEnv bool, setEnv []string) { for _, ev := range setEnv { pair := strings.SplitN(ev, "=", 2) appEnv.Set(pair[0], pair[1]) } if inheritEnv { for _, ev := range os.Environ() { pair := strings.SplitN(ev, "=", 2) if _, exists := appEnv.Get(pair[0]); !exists { appEnv.Set(pair[0], pair[1]) } } } }
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 }
func GenerateManifestV22(name string, dockerURL *types.ParsedDockerURL, config *typesV2.ImageConfig, imageDigest string, lowerLayers []*schema.ImageManifest) (*schema.ImageManifest, error) { manifest, err := GenerateEmptyManifest(name) if err != nil { return nil, err } labels := manifest.Labels.ToMap() annotations := manifest.Annotations addLabel := func(key, val string) { if key != "" && val != "" { labels[*appctypes.MustACIdentifier(key)] = val } } addAnno := func(key, val string) { if key != "" && val != "" { annotations.Set(*appctypes.MustACIdentifier(key), val) } } addLabel("version", dockerURL.Tag) addLabel("os", config.OS) addLabel("arch", config.Architecture) addAnno("author", config.Author) addAnno("created", config.Created) addAnno(common.AppcDockerRegistryURL, dockerURL.IndexURL) addAnno(common.AppcDockerRepository, dockerURL.ImageName) addAnno(common.AppcDockerImageID, imageDigest) addAnno("created", config.Created) if config.Config != nil { innerCfg := config.Config exec := getExecCommand(innerCfg.Entrypoint, innerCfg.Cmd) user, group := parseDockerUser(innerCfg.User) var env appctypes.Environment for _, v := range innerCfg.Env { parts := strings.SplitN(v, "=", 2) env.Set(parts[0], parts[1]) } manifest.App = &appctypes.App{ Exec: exec, User: user, Group: group, Environment: env, WorkingDirectory: innerCfg.WorkingDir, } manifest.App.MountPoints, err = convertVolumesToMPs(innerCfg.Volumes) if err != nil { return nil, err } manifest.App.Ports, err = convertPorts(innerCfg.ExposedPorts, nil) if err != nil { return nil, err } ep, cmd, err := generateEPCmdAnnotation(innerCfg.Entrypoint, innerCfg.Cmd) if err != nil { return nil, err } if len(ep) > 0 { addAnno(common.AppcDockerEntrypoint, ep) } if len(cmd) > 0 { addAnno(common.AppcDockerCmd, cmd) } } for _, lowerLayer := range lowerLayers { manifest.Dependencies = append(manifest.Dependencies, appctypes.Dependency{ ImageName: lowerLayer.Name, Labels: lowerLayer.Labels, }) } manifest.Labels, err = appctypes.LabelsFromMap(labels) if err != nil { return nil, err } manifest.Annotations = annotations return manifest, 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 }