// mergeEnv merges the optEnv with the image's environments. // The environments defined in the image will be overridden by // the ones with the same name in optEnv. func mergeEnv(app *appctypes.App, optEnv []kubecontainer.EnvVar) { envMap := make(map[string]string) for _, e := range app.Environment { envMap[e.Name] = e.Value } for _, e := range optEnv { envMap[e.Name] = e.Value } app.Environment = nil for name, value := range envMap { app.Environment = append(app.Environment, appctypes.EnvironmentVariable{ Name: name, Value: value, }) } }
// setApp overrides the app's fields if any of them are specified in the // container's spec. func setApp(app *appctypes.App, c *api.Container, opts *kubecontainer.RunContainerOptions) error { // Override the exec. // TOOD(yifan): Revisit this for the overriding rule. if len(c.Command) > 0 || len(c.Args) > 0 { app.Exec = append(c.Command, c.Args...) } // TODO(yifan): Use non-root user in the future, see: // https://github.com/coreos/rkt/issues/820 app.User, app.Group = "0", "0" // Override the working directory. if len(c.WorkingDir) > 0 { app.WorkingDirectory = c.WorkingDir } // Override the environment. if len(opts.Envs) > 0 { app.Environment = []appctypes.EnvironmentVariable{} } for _, env := range c.Env { app.Environment = append(app.Environment, appctypes.EnvironmentVariable{ Name: env.Name, Value: env.Value, }) } // Override the mount points. if len(opts.Mounts) > 0 { app.MountPoints = []appctypes.MountPoint{} } for _, m := range opts.Mounts { mountPointName, err := appctypes.NewACName(m.Name) if err != nil { return err } app.MountPoints = append(app.MountPoints, appctypes.MountPoint{ Name: *mountPointName, Path: m.ContainerPath, ReadOnly: m.ReadOnly, }) } // Override the ports. if len(opts.PortMappings) > 0 { app.Ports = []appctypes.Port{} } for _, p := range opts.PortMappings { name, err := appctypes.SanitizeACName(p.Name) if err != nil { return err } portName := appctypes.MustACName(name) app.Ports = append(app.Ports, appctypes.Port{ Name: *portName, Protocol: string(p.Protocol), Port: uint(p.ContainerPort), }) } // Override isolators. return setIsolators(app, c) }
// setApp overrides the app's fields if any of them are specified in the // container's spec. func setApp(app *appctypes.App, c *api.Container, opts *kubecontainer.RunContainerOptions) error { // Override the exec. if len(c.Command) > 0 { app.Exec = c.Command } if len(c.Args) > 0 { app.Exec = append(app.Exec, c.Args...) } // TODO(yifan): Use non-root user in the future, see: // https://github.com/coreos/rkt/issues/820 app.User, app.Group = "0", "0" // Override the working directory. if len(c.WorkingDir) > 0 { app.WorkingDirectory = c.WorkingDir } // Merge the environment. Override the image with the ones defined in the spec if necessary. for _, env := range opts.Envs { if ix := findEnvInList(app.Environment, env); ix >= 0 { app.Environment[ix].Value = env.Value continue } app.Environment = append(app.Environment, appctypes.EnvironmentVariable{ Name: env.Name, Value: env.Value, }) } // Override the mount points. if len(opts.Mounts) > 0 { app.MountPoints = []appctypes.MountPoint{} } for _, m := range opts.Mounts { mountPointName, err := appctypes.NewACName(m.Name) if err != nil { return err } app.MountPoints = append(app.MountPoints, appctypes.MountPoint{ Name: *mountPointName, Path: m.ContainerPath, ReadOnly: m.ReadOnly, }) } // Override the ports. if len(opts.PortMappings) > 0 { app.Ports = []appctypes.Port{} } for _, p := range opts.PortMappings { name, err := appctypes.SanitizeACName(p.Name) if err != nil { return err } portName := appctypes.MustACName(name) app.Ports = append(app.Ports, appctypes.Port{ Name: *portName, Protocol: string(p.Protocol), Port: uint(p.ContainerPort), }) } // Override isolators. return setIsolators(app, c) }
func genManifest(path string) *schema.ImageManifest { // Get runtime.json and config.json runtimePath := path + "/runtime.json" configPath := path + "/config.json" runtime, err := ioutil.ReadFile(runtimePath) if err != nil { if debugEnabled { log.Printf("Open file runtime.json failed: %v", err) } return nil } config, err := ioutil.ReadFile(configPath) if err != nil { if debugEnabled { log.Printf("Open file config.json failed: %v", err) } return nil } var spec specs.LinuxSpec err = json.Unmarshal(config, &spec) if err != nil { if debugEnabled { log.Printf("Unmarshal config.json failed: %v", err) } return nil } var runSpec specs.LinuxRuntimeSpec err = json.Unmarshal(runtime, &runSpec) if err != nil { if debugEnabled { log.Printf("Unmarshal runtime.json failed: %v", err) } return nil } // Begin to convert runtime.json/config.json to manifest m := new(schema.ImageManifest) // 1. Assemble "acKind" field m.ACKind = schema.ImageManifestKind // 2. Assemble "acVersion" field m.ACVersion = schema.AppContainerVersion // 3. Assemble "name" field m.Name = types.ACIdentifier(manifestName) // 4. Assemble "labels" field // 4.1 "version" label := new(types.Label) label.Name = types.ACIdentifier("version") label.Value = spec.Version m.Labels = append(m.Labels, *label) // 4.2 "os" label = new(types.Label) label.Name = types.ACIdentifier("os") label.Value = spec.Platform.OS m.Labels = append(m.Labels, *label) // 4.3 "arch" label = new(types.Label) label.Name = types.ACIdentifier("arch") label.Value = spec.Platform.Arch m.Labels = append(m.Labels, *label) // 5. Assemble "app" field app := new(types.App) // 5.1 "exec" app.Exec = spec.Process.Args prefixDir := "" //var exeStr string if app.Exec == nil { app.Exec = append(app.Exec, "/bin/sh") } else { if !filepath.IsAbs(app.Exec[0]) { if spec.Process.Cwd == "" { prefixDir = "/" } else { prefixDir = spec.Process.Cwd } } app.Exec[0] = prefixDir + app.Exec[0] } // 5.2 "user" app.User = fmt.Sprintf("%d", spec.Process.User.UID) // 5.3 "group" app.Group = fmt.Sprintf("%d", spec.Process.User.GID) // 5.4 "eventHandlers" event := new(types.EventHandler) event.Name = "pre-start" for index := range runSpec.Hooks.Prestart { event.Exec = append(event.Exec, runSpec.Hooks.Prestart[index].Path) event.Exec = append(event.Exec, runSpec.Hooks.Prestart[index].Args...) event.Exec = append(event.Exec, runSpec.Hooks.Prestart[index].Env...) } if len(event.Exec) == 0 { event.Exec = append(event.Exec, "/bin/echo") event.Exec = append(event.Exec, "-n") } app.EventHandlers = append(app.EventHandlers, *event) event = new(types.EventHandler) event.Name = "post-stop" for index := range runSpec.Hooks.Poststop { event.Exec = append(event.Exec, runSpec.Hooks.Poststop[index].Path) event.Exec = append(event.Exec, runSpec.Hooks.Poststop[index].Args...) event.Exec = append(event.Exec, runSpec.Hooks.Poststop[index].Env...) } if len(event.Exec) == 0 { event.Exec = append(event.Exec, "/bin/echo") event.Exec = append(event.Exec, "-n") } app.EventHandlers = append(app.EventHandlers, *event) // 5.5 "workingDirectory" app.WorkingDirectory = spec.Process.Cwd // 5.6 "environment" env := new(types.EnvironmentVariable) for index := range spec.Process.Env { s := strings.Split(spec.Process.Env[index], "=") env.Name = s[0] env.Value = s[1] app.Environment = append(app.Environment, *env) } // 5.7 "mountPoints" for index := range spec.Mounts { mount := new(types.MountPoint) mount.Name = types.ACName(spec.Mounts[index].Name) mount.Path = spec.Mounts[index].Path mount.ReadOnly = false app.MountPoints = append(app.MountPoints, *mount) } // 5.8 "ports" // 5.9 "isolators" if runSpec.Linux.Resources != nil { if runSpec.Linux.Resources.CPU.Quota != 0 { cpuLimt := new(ResourceCPU) cpuLimt.Limit = fmt.Sprintf("%dm", runSpec.Linux.Resources.CPU.Quota) isolator := new(types.Isolator) isolator.Name = types.ACIdentifier("resource/cpu") bytes, _ := json.Marshal(cpuLimt) valueRaw := json.RawMessage(bytes) isolator.ValueRaw = &valueRaw app.Isolators = append(app.Isolators, *isolator) } if runSpec.Linux.Resources.Memory.Limit != 0 { memLimt := new(ResourceMem) memLimt.Limit = fmt.Sprintf("%dG", runSpec.Linux.Resources.Memory.Limit/(1024*1024*1024)) isolator := new(types.Isolator) isolator.Name = types.ACIdentifier("resource/memory") bytes, _ := json.Marshal(memLimt) valueRaw := json.RawMessage(bytes) isolator.ValueRaw = &valueRaw app.Isolators = append(app.Isolators, *isolator) } } if len(spec.Linux.Capabilities) != 0 { isolatorCapSet := new(IsolatorCapSet) isolatorCapSet.Sets = append(isolatorCapSet.Sets, spec.Linux.Capabilities...) isolator := new(types.Isolator) isolator.Name = types.ACIdentifier(types.LinuxCapabilitiesRetainSetName) bytes, _ := json.Marshal(isolatorCapSet) valueRaw := json.RawMessage(bytes) isolator.ValueRaw = &valueRaw app.Isolators = append(app.Isolators, *isolator) } // 6. "annotations" // 7. "dependencies" // 8. "pathWhitelist" m.App = app return m }