From a217d8c86c9349c4e306bcfbaa92ca6109325895 Mon Sep 17 00:00:00 2001 From: Haiyan Meng Date: Thu, 28 Jul 2016 17:37:23 -0400 Subject: [PATCH] Modify generate API Signed-off-by: Haiyan Meng --- cmd/ocitools/generate.go | 121 ++++++++++++++++++++++++++++++++--- generate/generate.go | 133 ++++++++++----------------------------- 2 files changed, 144 insertions(+), 110 deletions(-) diff --git a/cmd/ocitools/generate.go b/cmd/ocitools/generate.go index 03e1b29d8..c33656c96 100644 --- a/cmd/ocitools/generate.go +++ b/cmd/ocitools/generate.go @@ -1,8 +1,11 @@ package main import ( + "fmt" "os" "runtime" + "strconv" + "strings" "github.com/opencontainers/ocitools/generate" rspec "github.com/opencontainers/runtime-spec/specs-go" @@ -117,7 +120,11 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { if context.IsSet("label") { annotations := context.StringSlice("label") for _, s := range annotations { - if err := g.AddAnnotation(s); err != nil { + pair := strings.Split(s, "=") + if len(pair) != 2 { + return fmt.Errorf("incorrectly specified annotation: %s", s) + } + if err := g.AddAnnotation(pair[0], pair[1]); err != nil { return err } } @@ -184,7 +191,11 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { if context.IsSet("sysctl") { sysctls := context.StringSlice("sysctl") for _, s := range sysctls { - g.AddLinuxSysctl(s) + pair := strings.Split(s, "=") + if len(pair) != 2 { + return fmt.Errorf("incorrectly specified sysctl: %s", s) + } + g.AddLinuxSysctl(pair[0], pair[1]) } } @@ -239,7 +250,11 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { if context.IsSet("tmpfs") { tmpfsSlice := context.StringSlice("tmpfs") for _, s := range tmpfsSlice { - if err := g.AddTmpfsMount(s); err != nil { + dest, options, err := parseTmpfsMount(s) + if err != nil { + return err + } + if err := g.AddTmpfsMount(dest, options); err != nil { return err } } @@ -253,7 +268,12 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { if context.IsSet("bind") { binds := context.StringSlice("bind") for _, bind := range binds { - if err := g.AddBindMount(bind); err != nil { + source, dest, options, err := parseBindMount(bind) + if err != nil { + return err + } + + if err := g.AddBindMount(source, dest, options); err != nil { return err } } @@ -262,7 +282,8 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { if context.IsSet("prestart") { preStartHooks := context.StringSlice("prestart") for _, hook := range preStartHooks { - if err := g.AddPreStartHook(hook); err != nil { + path, args := parseHook(hook) + if err := g.AddPreStartHook(path, args); err != nil { return err } } @@ -271,7 +292,8 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { if context.IsSet("poststop") { postStopHooks := context.StringSlice("poststop") for _, hook := range postStopHooks { - if err := g.AddPostStopHook(hook); err != nil { + path, args := parseHook(hook) + if err := g.AddPostStopHook(path, args); err != nil { return err } } @@ -280,7 +302,8 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { if context.IsSet("poststart") { postStartHooks := context.StringSlice("poststart") for _, hook := range postStartHooks { - if err := g.AddPostStartHook(hook); err != nil { + path, args := parseHook(hook) + if err := g.AddPostStartHook(path, args); err != nil { return err } } @@ -294,13 +317,23 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { } for _, uidMap := range uidMaps { - if err := g.AddLinuxUIDMapping(uidMap); err != nil { + hid, cid, size, err := parseIDMapping(uidMap) + if err != nil { + return err + } + + if err := g.AddLinuxUIDMapping(hid, cid, size); err != nil { return err } } for _, gidMap := range gidMaps { - if err := g.AddLinuxGIDMapping(gidMap); err != nil { + hid, cid, size, err := parseIDMapping(gidMap) + if err != nil { + return err + } + + if err := g.AddLinuxGIDMapping(hid, cid, size); err != nil { return err } } @@ -386,3 +419,73 @@ func setupLinuxNamespaces(g *generate.Generator, needsNewUser bool, nsMaps map[s g.AddOrReplaceLinuxNamespace(nsName, nsPath) } } + +func parseIDMapping(idms string) (uint32, uint32, uint32, error) { + idm := strings.Split(idms, ":") + if len(idm) != 3 { + return 0, 0, 0, fmt.Errorf("idmappings error: %s", idms) + } + + hid, err := strconv.Atoi(idm[0]) + if err != nil { + return 0, 0, 0, err + } + + cid, err := strconv.Atoi(idm[1]) + if err != nil { + return 0, 0, 0, err + } + + size, err := strconv.Atoi(idm[2]) + if err != nil { + return 0, 0, 0, err + } + + return uint32(hid), uint32(cid), uint32(size), nil +} + +func parseHook(s string) (string, []string) { + parts := strings.Split(s, ":") + args := []string{} + path := parts[0] + if len(parts) > 1 { + args = parts[1:] + } + return path, args +} + +func parseTmpfsMount(s string) (string, []string, error) { + var dest string + var options []string + var err error + + parts := strings.Split(s, ":") + if len(parts) == 2 { + dest = parts[0] + options = strings.Split(parts[1], ",") + } else if len(parts) == 1 { + dest = parts[0] + options = []string{"rw", "noexec", "nosuid", "nodev", "size=65536k"} + } else { + err = fmt.Errorf("invalid value for --tmpfs") + } + + return dest, options, err +} + +func parseBindMount(s string) (string, string, string, error) { + var source, dest string + options := "ro" + + bparts := strings.SplitN(s, ":", 3) + switch len(bparts) { + case 2: + source, dest = bparts[0], bparts[1] + case 3: + source, dest, options = bparts[0], bparts[1], bparts[2] + default: + return source, dest, options, fmt.Errorf("--bind should have format src:dest:[options]") + } + + return source, dest, options, nil +} diff --git a/generate/generate.go b/generate/generate.go index 407a875c2..7bacfdc2d 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -244,14 +244,9 @@ func (g *Generator) ClearAnnotations() { } // AddAnnotation adds an annotation into g.spec.Annotations. -func (g *Generator) AddAnnotation(s string) error { +func (g *Generator) AddAnnotation(key, value string) error { g.initSpecAnnotations() - - pair := strings.Split(s, "=") - if len(pair) != 2 { - return fmt.Errorf("incorrectly specified annotation: %s", s) - } - g.spec.Annotations[pair[0]] = pair[1] + g.spec.Annotations[key] = value return nil } @@ -461,14 +456,9 @@ func (g *Generator) ClearLinuxSysctl() { } // AddLinuxSysctl adds a new sysctl config into g.spec.Linux.Sysctl. -func (g *Generator) AddLinuxSysctl(s string) error { +func (g *Generator) AddLinuxSysctl(key, value string) error { g.initSpecLinuxSysctl() - - pair := strings.Split(s, "=") - if len(pair) != 2 { - return fmt.Errorf("incorrectly specified sysctl: %s", s) - } - g.spec.Linux.Sysctl[pair[0]] = pair[1] + g.spec.Linux.Sysctl[key] = value return nil } @@ -752,35 +742,6 @@ func (g *Generator) RemoveSeccompSyscall(name string, action string) error { return nil } -func parseIDMapping(idms string) (rspec.IDMapping, error) { - idm := strings.Split(idms, ":") - if len(idm) != 3 { - return rspec.IDMapping{}, fmt.Errorf("idmappings error: %s", idms) - } - - hid, err := strconv.Atoi(idm[0]) - if err != nil { - return rspec.IDMapping{}, err - } - - cid, err := strconv.Atoi(idm[1]) - if err != nil { - return rspec.IDMapping{}, err - } - - size, err := strconv.Atoi(idm[2]) - if err != nil { - return rspec.IDMapping{}, err - } - - idMapping := rspec.IDMapping{ - HostID: uint32(hid), - ContainerID: uint32(cid), - Size: uint32(size), - } - return idMapping, nil -} - // ClearLinuxUIDMappings clear g.spec.Linux.UIDMappings. func (g *Generator) ClearLinuxUIDMappings() { if g.spec == nil || g.spec.Linux == nil { @@ -790,14 +751,15 @@ func (g *Generator) ClearLinuxUIDMappings() { } // AddLinuxUIDMapping adds uidMap into g.spec.Linux.UIDMappings. -func (g *Generator) AddLinuxUIDMapping(uidMap string) error { - r, err := parseIDMapping(uidMap) - if err != nil { - return err +func (g *Generator) AddLinuxUIDMapping(hid, cid, size uint32) error { + idMapping := rspec.IDMapping{ + HostID: hid, + ContainerID: cid, + Size: size, } g.initSpecLinux() - g.spec.Linux.UIDMappings = append(g.spec.Linux.UIDMappings, r) + g.spec.Linux.UIDMappings = append(g.spec.Linux.UIDMappings, idMapping) return nil } @@ -810,14 +772,15 @@ func (g *Generator) ClearLinuxGIDMappings() { } // AddLinuxGIDMapping adds gidMap into g.spec.Linux.GIDMappings. -func (g *Generator) AddLinuxGIDMapping(gidMap string) error { - r, err := parseIDMapping(gidMap) - if err != nil { - return err +func (g *Generator) AddLinuxGIDMapping(hid, cid, size uint32) error { + idMapping := rspec.IDMapping{ + HostID: hid, + ContainerID: cid, + Size: size, } g.initSpecLinux() - g.spec.Linux.GIDMappings = append(g.spec.Linux.GIDMappings, r) + g.spec.Linux.GIDMappings = append(g.spec.Linux.GIDMappings, idMapping) return nil } @@ -839,16 +802,6 @@ func (g *Generator) SetLinuxRootPropagation(rp string) error { return nil } -func parseHook(s string) rspec.Hook { - parts := strings.Split(s, ":") - args := []string{} - path := parts[0] - if len(parts) > 1 { - args = parts[1:] - } - return rspec.Hook{Path: path, Args: args} -} - // ClearPreStartHooks clear g.spec.Hooks.Prestart. func (g *Generator) ClearPreStartHooks() { if g.spec == nil { @@ -858,9 +811,9 @@ func (g *Generator) ClearPreStartHooks() { } // AddPreStartHook add a prestart hook into g.spec.Hooks.Prestart. -func (g *Generator) AddPreStartHook(s string) error { - hook := parseHook(s) +func (g *Generator) AddPreStartHook(path string, args []string) error { g.initSpec() + hook := rspec.Hook{Path: path, Args: args} g.spec.Hooks.Prestart = append(g.spec.Hooks.Prestart, hook) return nil } @@ -874,9 +827,9 @@ func (g *Generator) ClearPostStopHooks() { } // AddPostStopHook adds a poststop hook into g.spec.Hooks.Poststop. -func (g *Generator) AddPostStopHook(s string) error { - hook := parseHook(s) +func (g *Generator) AddPostStopHook(path string, args []string) error { g.initSpec() + hook := rspec.Hook{Path: path, Args: args} g.spec.Hooks.Poststop = append(g.spec.Hooks.Poststop, hook) return nil } @@ -890,35 +843,20 @@ func (g *Generator) ClearPostStartHooks() { } // AddPostStartHook adds a poststart hook into g.spec.Hooks.Poststart. -func (g *Generator) AddPostStartHook(s string) error { - hook := parseHook(s) +func (g *Generator) AddPostStartHook(path string, args []string) error { g.initSpec() + hook := rspec.Hook{Path: path, Args: args} g.spec.Hooks.Poststart = append(g.spec.Hooks.Poststart, hook) return nil } // AddTmpfsMount adds a tmpfs mount into g.spec.Mounts. -func (g *Generator) AddTmpfsMount(dest string) error { - mnt := rspec.Mount{} - - parts := strings.Split(dest, ":") - if len(parts) == 2 { - options := strings.Split(parts[1], ",") - mnt = rspec.Mount{ - Destination: parts[0], - Type: "tmpfs", - Source: "tmpfs", - Options: options, - } - } else if len(parts) == 1 { - mnt = rspec.Mount{ - Destination: parts[0], - Type: "tmpfs", - Source: "tmpfs", - Options: []string{"rw", "noexec", "nosuid", "nodev", "size=65536k"}, - } - } else { - return fmt.Errorf("invalid value for --tmpfs") +func (g *Generator) AddTmpfsMount(dest string, options []string) error { + mnt := rspec.Mount{ + Destination: dest, + Type: "tmpfs", + Source: "tmpfs", + Options: options, } g.initSpec() @@ -950,20 +888,13 @@ func (g *Generator) AddCgroupsMount(mountCgroupOption string) error { } // AddBindMount adds a bind mount into g.spec.Mounts. -func (g *Generator) AddBindMount(bind string) error { - var source, dest string - options := "ro" - bparts := strings.SplitN(bind, ":", 3) - switch len(bparts) { - case 2: - source, dest = bparts[0], bparts[1] - case 3: - source, dest, options = bparts[0], bparts[1], bparts[2] - default: - return fmt.Errorf("--bind should have format src:dest:[options]") +func (g *Generator) AddBindMount(source, dest, options string) error { + if options == "" { + options = "ro" } defaultOptions := []string{"bind"} + mnt := rspec.Mount{ Destination: dest, Type: "bind",