Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions cmd/oci-runtime-tool/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"fmt"
"os"
"runtime"
"strconv"
"strings"

Expand All @@ -15,7 +14,7 @@ import (

var generateFlags = []cli.Flag{
cli.StringFlag{Name: "apparmor", Usage: "specifies the the apparmor profile for the container"},
cli.StringFlag{Name: "arch", Value: runtime.GOARCH, Usage: "architecture the container is created for"},
cli.StringFlag{Name: "arch", Usage: "architecture the container is created for"},
cli.StringSliceFlag{Name: "args", Usage: "command to run in the container"},
cli.StringSliceFlag{Name: "bind", Usage: "bind mount directories src:dest[:options...]"},
cli.StringSliceFlag{Name: "cap-add", Usage: "add Linux capabilities"},
Expand Down Expand Up @@ -52,7 +51,7 @@ var generateFlags = []cli.Flag{
cli.StringFlag{Name: "network", Usage: "network namespace"},
cli.BoolFlag{Name: "no-new-privileges", Usage: "set no new privileges bit for the container process"},
cli.IntFlag{Name: "oom-score-adj", Usage: "oom_score_adj for the container"},
cli.StringFlag{Name: "os", Value: runtime.GOOS, Usage: "operating system the container is created for"},
cli.StringFlag{Name: "os", Usage: "operating system the container is created for"},
cli.StringFlag{Name: "output", Usage: "output file (defaults to stdout)"},
cli.StringFlag{Name: "pid", Usage: "pid namespace"},
cli.StringSliceFlag{Name: "poststart", Usage: "set command to run in poststart hooks"},
Expand Down Expand Up @@ -92,21 +91,28 @@ var generateCommand = cli.Command{
Before: before,
Action: func(context *cli.Context) error {
// Start from the default template.
specgen := generate.New()
var osPointer *string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename the variable to specOs? I don't like that we have Pointer in the name. Go doesn't recommend hungarian notation.

if context.IsSet("os") {
goos := context.String("os")
osPointer = &goos
}
specgen, err := generate.New(osPointer)
if err != nil {
return err
}

var template string
if context.IsSet("template") {
template = context.String("template")
}
if template != "" {
var err error
specgen, err = generate.NewFromFile(template)
if err != nil {
return err
}
}

err := setupSpec(&specgen, context)
err = setupSpec(&specgen, context)
if err != nil {
return err
}
Expand Down Expand Up @@ -141,8 +147,19 @@ func setupSpec(g *generate.Generator, context *cli.Context) error {
g.SetHostname(context.String("hostname"))
}

g.SetPlatformOS(context.String("os"))
g.SetPlatformArch(context.String("arch"))
if context.IsSet("os") {
err := g.SetPlatformOS(context.String("os"))
if err != nil {
return err
}
}

if context.IsSet("arch") {
err := g.SetPlatformArch(context.String("arch"))
if err != nil {
return err
}
}

if context.IsSet("label") {
annotations := context.StringSlice("label")
Expand Down
99 changes: 61 additions & 38 deletions generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate/seccomp"
"github.com/Sirupsen/logrus"
"github.com/syndtr/gocapability/capability"
)

Expand All @@ -30,8 +31,14 @@ type ExportOptions struct {
Seccomp bool // seccomp toggles if only seccomp should be exported
}

// New creates a spec Generator with the default spec.
func New() Generator {
// New creates a spec Generator with the default spec for the target
// OS (which defaults to runtime.GOOS).
func New(os *string) (generator Generator, err error) {
var goos string
goos = runtime.GOOS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goos := runtime.GOOS

if os == nil {
os = &goos
}
spec := rspec.Spec{
Version: rspec.Version,
Platform: rspec.Platform{
Expand All @@ -44,41 +51,45 @@ func New() Generator {
},
Process: rspec.Process{
Terminal: false,
User: rspec.User{},
Args: []string{
"sh",
},
Env: []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm",
},
Cwd: "/",
Capabilities: []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
},
Rlimits: []rspec.Rlimit{
{
Type: "RLIMIT_NOFILE",
Hard: uint64(1024),
Soft: uint64(1024),
},
},
},
Hostname: "mrsdalloway",
Mounts: []rspec.Mount{
}

if *os == "linux" {
spec.Process.User = rspec.User{}
spec.Process.Env = []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm",
}
spec.Process.Cwd = "/"
spec.Process.Capabilities = []string{
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE",
}
spec.Process.Rlimits = []rspec.Rlimit{
{
Type: "RLIMIT_NOFILE",
Hard: uint64(1024),
Soft: uint64(1024),
},
}

spec.Mounts = []rspec.Mount{
{
Destination: "/proc",
Type: "proc",
Expand Down Expand Up @@ -115,8 +126,9 @@ func New() Generator {
Source: "sysfs",
Options: []string{"nosuid", "noexec", "nodev", "ro"},
},
},
Linux: &rspec.Linux{
}

spec.Linux = &rspec.Linux{
Resources: &rspec.Resources{
Devices: []rspec.DeviceCgroup{
{
Expand All @@ -143,12 +155,15 @@ func New() Generator {
},
},
Devices: []rspec.Device{},
},
}
} else {
return generator, fmt.Errorf("no defaults configured for %s", *os)
}
spec.Linux.Seccomp = seccomp.DefaultProfile(&spec)
return Generator{
generator = Generator{
spec: &spec,
}
return generator, nil
}

// NewFromSpec creates a spec Generator from a given spec.
Expand Down Expand Up @@ -270,15 +285,23 @@ func (g *Generator) RemoveAnnotation(key string) {
}

// SetPlatformOS sets g.spec.Process.OS.
func (g *Generator) SetPlatformOS(os string) {
func (g *Generator) SetPlatformOS(os string) error {
if g.HostSpecific && os != runtime.GOOS {
return fmt.Errorf("cannot set platform.os to %s on a %s host", os, runtime.GOOS)
}
g.initSpec()
g.spec.Platform.OS = os
return nil
}

// SetPlatformArch sets g.spec.Platform.Arch.
func (g *Generator) SetPlatformArch(arch string) {
func (g *Generator) SetPlatformArch(arch string) error {
if g.HostSpecific && arch != runtime.GOARCH {
logrus.Warnf("setting platform.arch to %s on a %s host", arch, runtime.GOARCH)
}
g.initSpec()
g.spec.Platform.Arch = arch
return nil
}

// SetProcessUID sets g.spec.Process.User.UID.
Expand Down
8 changes: 7 additions & 1 deletion man/oci-runtime-tool-generate.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,13 @@ read the configuration from `config.json`.
Specifies oom_score_adj for the container.

**--os**=OS
Operating system used within the container
Operating system used within the container. When no template is
set, the default is to use the `GOOS` ocitools was built with and to
default other settings based on this setting. For example, if
`GOOS` is `linux`, `ocitools generate` will generate a default Linux
config, `ocitools generate --os=windows` will generate a default
Windows config, and `ocitools --host-specific generate --os=windows`
will exit with an error.

**--output**=PATH
Instead of writing the configuration JSON to stdout, write it to a
Expand Down
11 changes: 11 additions & 0 deletions validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"reflect"
"runtime"
"strings"
"unicode"
"unicode/utf8"
Expand Down Expand Up @@ -164,6 +165,16 @@ func (v *Validator) CheckPlatform() (msgs []string) {
}
msgs = append(msgs, fmt.Sprintf("Operation system %q of the bundle is not supported yet.", platform.OS))

if hostCheck {
if platform.OS != runtime.GOOS {
msgs = append(msgs, fmt.Sprintf("platform.os is %s, not %s", platform.OS, runtime.GOOS))
}
if platform.Arch != runtime.GOARCH {
// warning, not an error, since kernels can support multiple architectures
msgs = append(msgs, fmt.Sprintf("platform.arch is %s, not %s", platform.Arch, runtime.GOARCH))
}
}

return
}

Expand Down