// mergePortMappings merges the optPortMappings with the image's port mappings. // The port mappings defined in the image will be overridden by the ones // with the same name in optPortMappings. func mergePortMappings(app *appctypes.App, optPortMappings []kubecontainer.PortMapping) { portMap := make(map[appctypes.ACName]appctypes.Port) for _, p := range app.Ports { portMap[p.Name] = p } for _, p := range optPortMappings { pName := convertToACName(p.Name) portMap[pName] = appctypes.Port{ Name: pName, Protocol: string(p.Protocol), Port: uint(p.ContainerPort), } } app.Ports = nil for _, port := range portMap { app.Ports = append(app.Ports, port) } }
// 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 patchManifest(im *schema.ImageManifest) error { if patchName != "" { name, err := types.NewACIdentifier(patchName) if err != nil { return err } im.Name = *name } var app *types.App = im.App if patchExec != "" { if app == nil { // if the original manifest was missing an app and // patchExec is set let's assume the user is trying to // inject one... im.App = &types.App{} app = im.App } app.Exec = strings.Split(patchExec, " ") } if patchUser != "" || patchGroup != "" || patchSupplementaryGIDs != "" || patchCaps != "" || patchRevokeCaps != "" || patchMounts != "" || patchPorts != "" || patchIsolators != "" { // ...but if we still don't have an app and the user is trying // to patch one of its other parameters, it's an error if app == nil { return fmt.Errorf("no app in the supplied manifest and no exec command provided") } } if patchUser != "" { app.User = patchUser } if patchGroup != "" { app.Group = patchGroup } if patchSupplementaryGIDs != "" { app.SupplementaryGIDs = []int{} gids := strings.Split(patchSupplementaryGIDs, ",") for _, g := range gids { gid, err := strconv.Atoi(g) if err != nil { return fmt.Errorf("invalid supplementary group %q: %v", g, err) } app.SupplementaryGIDs = append(app.SupplementaryGIDs, gid) } } if patchCaps != "" { isolator := app.Isolators.GetByName(types.LinuxCapabilitiesRetainSetName) if isolator != nil { return fmt.Errorf("isolator already exists (os/linux/capabilities-retain-set)") } // Instantiate a Isolator with the content specified by the --capability // parameter. caps, err := types.NewLinuxCapabilitiesRetainSet(strings.Split(patchCaps, ",")...) if err != nil { return fmt.Errorf("cannot parse capability %q: %v", patchCaps, err) } app.Isolators = append(app.Isolators, caps.AsIsolator()) } if patchRevokeCaps != "" { isolator := app.Isolators.GetByName(types.LinuxCapabilitiesRevokeSetName) if isolator != nil { return fmt.Errorf("isolator already exists (os/linux/capabilities-remove-set)") } // Instantiate a Isolator with the content specified by the --revoke-capability // parameter. caps, err := types.NewLinuxCapabilitiesRevokeSet(strings.Split(patchRevokeCaps, ",")...) if err != nil { return fmt.Errorf("cannot parse capability %q: %v", patchRevokeCaps, err) } app.Isolators = append(app.Isolators, caps.AsIsolator()) } if patchMounts != "" { mounts := strings.Split(patchMounts, ":") for _, m := range mounts { mountPoint, err := types.MountPointFromString(m) if err != nil { return fmt.Errorf("cannot parse mount point %q: %v", m, err) } app.MountPoints = append(app.MountPoints, *mountPoint) } } if patchPorts != "" { ports := strings.Split(patchPorts, ":") for _, p := range ports { port, err := types.PortFromString(p) if err != nil { return fmt.Errorf("cannot parse port %q: %v", p, err) } app.Ports = append(app.Ports, *port) } } if patchIsolators != "" { isolators := strings.Split(patchIsolators, ":") for _, is := range isolators { name, isolatorStr, err := isolatorStrFromString(is) if err != nil { return fmt.Errorf("cannot parse isolator %q: %v", is, err) } if _, ok := types.ResourceIsolatorNames[name]; !ok { return fmt.Errorf("isolator %s is not supported for patching", name) } isolator := &types.Isolator{} if err := isolator.UnmarshalJSON([]byte(isolatorStr)); err != nil { return fmt.Errorf("cannot unmarshal isolator %v: %v", isolatorStr, err) } app.Isolators = append(app.Isolators, *isolator) } } return nil }
func patchManifest(im *schema.ImageManifest) error { if patchName != "" { name, err := types.NewACIdentifier(patchName) if err != nil { return err } im.Name = *name } var app *types.App = im.App if patchExec != "" { if app == nil { // if the original manifest was missing an app and // patchExec is set let's assume the user is trying to // inject one... im.App = &types.App{} app = im.App } app.Exec = strings.Split(patchExec, " ") } if patchUser != "" || patchGroup != "" || patchSupplementaryGIDs != "" || patchCaps != "" || patchMounts != "" || patchPorts != "" || patchIsolators != "" { // ...but if we still don't have an app and the user is trying // to patch one of its other parameters, it's an error if app == nil { return fmt.Errorf("no app in the supplied manifest and no exec command provided") } } if patchUser != "" { app.User = patchUser } if patchGroup != "" { app.Group = patchGroup } if patchSupplementaryGIDs != "" { app.SupplementaryGIDs = []int{} gids := strings.Split(patchSupplementaryGIDs, ",") for _, g := range gids { gid, err := strconv.Atoi(g) if err != nil { return fmt.Errorf("invalid supplementary group %q: %v", g, err) } app.SupplementaryGIDs = append(app.SupplementaryGIDs, gid) } } if patchCaps != "" { isolator := app.Isolators.GetByName(types.LinuxCapabilitiesRetainSetName) if isolator != nil { return fmt.Errorf("isolator already exists") } // Instantiate a Isolator with the content specified by the --capability // parameter. // TODO: Instead of creating a JSON and then unmarshalling it, the isolator // should be instantiated directory. But it requires a constructor, see: // https://github.com/appc/spec/issues/268 capsList := strings.Split(patchCaps, ",") caps := fmt.Sprintf(`"set": ["%s"]`, strings.Join(capsList, `", "`)) isolatorStr := getIsolatorStr(types.LinuxCapabilitiesRetainSetName, caps) isolator = &types.Isolator{} err := isolator.UnmarshalJSON([]byte(isolatorStr)) if err != nil { return fmt.Errorf("cannot parse capability %q: %v", patchCaps, err) } app.Isolators = append(app.Isolators, *isolator) } if patchMounts != "" { mounts := strings.Split(patchMounts, ":") for _, m := range mounts { mountPoint, err := types.MountPointFromString(m) if err != nil { return fmt.Errorf("cannot parse mount point %q: %v", m, err) } app.MountPoints = append(app.MountPoints, *mountPoint) } } if patchPorts != "" { ports := strings.Split(patchPorts, ":") for _, p := range ports { port, err := types.PortFromString(p) if err != nil { return fmt.Errorf("cannot parse port %q: %v", p, err) } app.Ports = append(app.Ports, *port) } } if patchIsolators != "" { isolators := strings.Split(patchIsolators, ":") for _, is := range isolators { name, isolatorStr, err := isolatorStrFromString(is) if err != nil { return fmt.Errorf("cannot parse isolator %q: %v", is, err) } if _, ok := types.ResourceIsolatorNames[name]; !ok { return fmt.Errorf("isolator %s is not supported for patching", name) } isolator := &types.Isolator{} if err := isolator.UnmarshalJSON([]byte(isolatorStr)); err != nil { return fmt.Errorf("cannot unmarshal isolator %v: %v", isolatorStr, err) } app.Isolators = append(app.Isolators, *isolator) } } return nil }
func patchManifest(im *schema.ImageManifest) error { if patchName != "" { name, err := types.NewACIdentifier(patchName) if err != nil { return err } im.Name = *name } if patchExec != "" { im.App.Exec = strings.Split(patchExec, " ") } if patchUser != "" { im.App.User = patchUser } if patchGroup != "" { im.App.Group = patchGroup } var app *types.App if patchCaps != "" || patchMounts != "" || patchPorts != "" || patchIsolators != "" { app = im.App if app == nil { return fmt.Errorf("no app in the manifest") } } if patchCaps != "" { isolator := app.Isolators.GetByName(types.LinuxCapabilitiesRetainSetName) if isolator != nil { return fmt.Errorf("isolator already exists") } // Instantiate a Isolator with the content specified by the --capability // parameter. // TODO: Instead of creating a JSON and then unmarshalling it, the isolator // should be instantiated directory. But it requires a constructor, see: // https://github.com/appc/spec/issues/268 capsList := strings.Split(patchCaps, ",") caps := fmt.Sprintf(`"set": ["%s"]`, strings.Join(capsList, `", "`)) isolatorStr := getIsolatorStr(types.LinuxCapabilitiesRetainSetName, caps) isolator = &types.Isolator{} err := isolator.UnmarshalJSON([]byte(isolatorStr)) if err != nil { return fmt.Errorf("cannot parse capability %q: %v", patchCaps, err) } app.Isolators = append(app.Isolators, *isolator) } if patchMounts != "" { mounts := strings.Split(patchMounts, ":") for _, m := range mounts { mountPoint, err := types.MountPointFromString(m) if err != nil { return fmt.Errorf("cannot parse mount point %q: %v", m, err) } app.MountPoints = append(app.MountPoints, *mountPoint) } } if patchPorts != "" { ports := strings.Split(patchPorts, ":") for _, p := range ports { port, err := types.PortFromString(p) if err != nil { return fmt.Errorf("cannot parse port %q: %v", p, err) } app.Ports = append(app.Ports, *port) } } if patchIsolators != "" { isolators := strings.Split(patchIsolators, ":") for _, is := range isolators { name, isolatorStr, err := isolatorStrFromString(is) if err != nil { return fmt.Errorf("cannot parse isolator %q: %v", is, err) } if _, ok := types.ResourceIsolatorNames[name]; !ok { return fmt.Errorf("isolator %s is not supported for patching", name) } isolator := &types.Isolator{} if err := isolator.UnmarshalJSON([]byte(isolatorStr)); err != nil { return fmt.Errorf("cannot unmarshal isolator %v: %v", isolatorStr, err) } app.Isolators = append(app.Isolators, *isolator) } } return nil }
func patchManifest(im *schema.ImageManifest) error { if patchName != "" { name, err := types.NewACIdentifier(patchName) if err != nil { return err } im.Name = *name } var app *types.App = im.App if patchExec != "" { if app == nil { // if the original manifest was missing an app and // patchExec is set let's assume the user is trying to // inject one... im.App = &types.App{} app = im.App } app.Exec = strings.Split(patchExec, " ") } if patchUser != "" || patchGroup != "" || patchSupplementaryGIDs != "" || patchCaps != "" || patchRevokeCaps != "" || patchMounts != "" || patchPorts != "" || patchIsolators != "" { // ...but if we still don't have an app and the user is trying // to patch one of its other parameters, it's an error if app == nil { return fmt.Errorf("no app in the supplied manifest and no exec command provided") } } if patchUser != "" { app.User = patchUser } if patchGroup != "" { app.Group = patchGroup } if patchSupplementaryGIDs != "" { app.SupplementaryGIDs = []int{} gids := strings.Split(patchSupplementaryGIDs, ",") for _, g := range gids { gid, err := strconv.Atoi(g) if err != nil { return fmt.Errorf("invalid supplementary group %q: %v", g, err) } app.SupplementaryGIDs = append(app.SupplementaryGIDs, gid) } } if patchCaps != "" { isolator := app.Isolators.GetByName(types.LinuxCapabilitiesRetainSetName) if isolator != nil { return fmt.Errorf("isolator already exists (os/linux/capabilities-retain-set)") } // Instantiate a Isolator with the content specified by the --capability // parameter. caps, err := types.NewLinuxCapabilitiesRetainSet(strings.Split(patchCaps, ",")...) if err != nil { return fmt.Errorf("cannot parse capability %q: %v", patchCaps, err) } isolator, err = caps.AsIsolator() if err != nil { return err } app.Isolators = append(app.Isolators, *isolator) } if patchRevokeCaps != "" { isolator := app.Isolators.GetByName(types.LinuxCapabilitiesRevokeSetName) if isolator != nil { return fmt.Errorf("isolator already exists (os/linux/capabilities-remove-set)") } // Instantiate a Isolator with the content specified by the --revoke-capability // parameter. caps, err := types.NewLinuxCapabilitiesRevokeSet(strings.Split(patchRevokeCaps, ",")...) if err != nil { return fmt.Errorf("cannot parse capability %q: %v", patchRevokeCaps, err) } isolator, err = caps.AsIsolator() if err != nil { return err } app.Isolators = append(app.Isolators, *isolator) } if patchMounts != "" { mounts := strings.Split(patchMounts, ":") for _, m := range mounts { mountPoint, err := types.MountPointFromString(m) if err != nil { return fmt.Errorf("cannot parse mount point %q: %v", m, err) } app.MountPoints = append(app.MountPoints, *mountPoint) } } if patchPorts != "" { ports := strings.Split(patchPorts, ":") for _, p := range ports { port, err := types.PortFromString(p) if err != nil { return fmt.Errorf("cannot parse port %q: %v", p, err) } app.Ports = append(app.Ports, *port) } } // Parse seccomp args and override existing seccomp isolators if patchSeccompMode != "" { seccompIsolator, err := parseSeccompArgs(patchSeccompMode, patchSeccompSet) if err != nil { return err } seccompReps := []types.ACIdentifier{types.LinuxSeccompRemoveSetName, types.LinuxSeccompRetainSetName} app.Isolators.ReplaceIsolatorsByName(*seccompIsolator, seccompReps) } else if patchSeccompSet != "" { return fmt.Errorf("--seccomp-set specified without --seccomp-mode") } if patchIsolators != "" { isolators := strings.Split(patchIsolators, ":") for _, is := range isolators { name, isolatorStr, err := isolatorStrFromString(is) if err != nil { return fmt.Errorf("cannot parse isolator %q: %v", is, err) } _, ok := types.ResourceIsolatorNames[name] switch name { case types.LinuxNoNewPrivilegesName: ok = true kv := strings.Split(is, ",") if len(kv) != 2 { return fmt.Errorf("isolator %s: invalid format", name) } isolatorStr = fmt.Sprintf(`{ "name": "%s", "value": %s }`, name, kv[1]) case types.LinuxSeccompRemoveSetName, types.LinuxSeccompRetainSetName: ok = false } if !ok { return fmt.Errorf("isolator %s is not supported for patching", name) } isolator := &types.Isolator{} if err := isolator.UnmarshalJSON([]byte(isolatorStr)); err != nil { return fmt.Errorf("cannot unmarshal isolator %v: %v", isolatorStr, err) } app.Isolators = append(app.Isolators, *isolator) } } return nil }