Merge pull request #2268 from justincormack/init-null-spec

Consistently add empty types where they are nil in spec
This commit is contained in:
Michael Crosby 2018-04-03 10:42:07 -04:00 committed by GitHub
commit d1b3ea4061
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 10 deletions

View File

@ -27,9 +27,17 @@ import (
// SpecOpts sets spec specific information to a newly generated OCI spec // SpecOpts sets spec specific information to a newly generated OCI spec
type SpecOpts func(context.Context, Client, *containers.Container, *specs.Spec) error type SpecOpts func(context.Context, Client, *containers.Container, *specs.Spec) error
// setProcess sets Process to empty if unset
func setProcess(s *specs.Spec) {
if s.Process == nil {
s.Process = &specs.Process{}
}
}
// WithProcessArgs replaces the args on the generated spec // WithProcessArgs replaces the args on the generated spec
func WithProcessArgs(args ...string) SpecOpts { func WithProcessArgs(args ...string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setProcess(s)
s.Process.Args = args s.Process.Args = args
return nil return nil
} }
@ -38,6 +46,7 @@ func WithProcessArgs(args ...string) SpecOpts {
// WithProcessCwd replaces the current working directory on the generated spec // WithProcessCwd replaces the current working directory on the generated spec
func WithProcessCwd(cwd string) SpecOpts { func WithProcessCwd(cwd string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setProcess(s)
s.Process.Cwd = cwd s.Process.Cwd = cwd
return nil return nil
} }
@ -55,6 +64,7 @@ func WithHostname(name string) SpecOpts {
func WithEnv(environmentVariables []string) SpecOpts { func WithEnv(environmentVariables []string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
if len(environmentVariables) > 0 { if len(environmentVariables) > 0 {
setProcess(s)
s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, environmentVariables) s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, environmentVariables)
} }
return nil return nil

View File

@ -43,14 +43,38 @@ import (
// WithTTY sets the information on the spec as well as the environment variables for // WithTTY sets the information on the spec as well as the environment variables for
// using a TTY // using a TTY
func WithTTY(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { func WithTTY(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setProcess(s)
s.Process.Terminal = true s.Process.Terminal = true
s.Process.Env = append(s.Process.Env, "TERM=xterm") s.Process.Env = append(s.Process.Env, "TERM=xterm")
return nil return nil
} }
// setRoot sets Root to empty if unset
func setRoot(s *specs.Spec) {
if s.Root == nil {
s.Root = &specs.Root{}
}
}
// setLinux sets Linux to empty if unset
func setLinux(s *specs.Spec) {
if s.Linux == nil {
s.Linux = &specs.Linux{}
}
}
// setCapabilities sets Linux Capabilities to empty if unset
func setCapabilities(s *specs.Spec) {
setProcess(s)
if s.Process.Capabilities == nil {
s.Process.Capabilities = &specs.LinuxCapabilities{}
}
}
// WithHostNamespace allows a task to run inside the host's linux namespace // WithHostNamespace allows a task to run inside the host's linux namespace
func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts { func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setLinux(s)
for i, n := range s.Linux.Namespaces { for i, n := range s.Linux.Namespaces {
if n.Type == ns { if n.Type == ns {
s.Linux.Namespaces = append(s.Linux.Namespaces[:i], s.Linux.Namespaces[i+1:]...) s.Linux.Namespaces = append(s.Linux.Namespaces[:i], s.Linux.Namespaces[i+1:]...)
@ -65,6 +89,7 @@ func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts {
// spec, the existing namespace is replaced by the one provided. // spec, the existing namespace is replaced by the one provided.
func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts { func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setLinux(s)
for i, n := range s.Linux.Namespaces { for i, n := range s.Linux.Namespaces {
if n.Type == ns.Type { if n.Type == ns.Type {
before := s.Linux.Namespaces[:i] before := s.Linux.Namespaces[:i]
@ -105,10 +130,7 @@ func WithImageConfig(image Image) SpecOpts {
return fmt.Errorf("unknown image config media type %s", ic.MediaType) return fmt.Errorf("unknown image config media type %s", ic.MediaType)
} }
if s.Process == nil { setProcess(s)
s.Process = &specs.Process{}
}
s.Process.Env = append(s.Process.Env, config.Env...) s.Process.Env = append(s.Process.Env, config.Env...)
cmd := config.Cmd cmd := config.Cmd
s.Process.Args = append(config.Entrypoint, cmd...) s.Process.Args = append(config.Entrypoint, cmd...)
@ -127,9 +149,7 @@ func WithImageConfig(image Image) SpecOpts {
// WithRootFSPath specifies unmanaged rootfs path. // WithRootFSPath specifies unmanaged rootfs path.
func WithRootFSPath(path string) SpecOpts { func WithRootFSPath(path string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
if s.Root == nil { setRoot(s)
s.Root = &specs.Root{}
}
s.Root.Path = path s.Root.Path = path
// Entrypoint is not set here (it's up to caller) // Entrypoint is not set here (it's up to caller)
return nil return nil
@ -139,9 +159,7 @@ func WithRootFSPath(path string) SpecOpts {
// WithRootFSReadonly sets specs.Root.Readonly to true // WithRootFSReadonly sets specs.Root.Readonly to true
func WithRootFSReadonly() SpecOpts { func WithRootFSReadonly() SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
if s.Root == nil { setRoot(s)
s.Root = &specs.Root{}
}
s.Root.Readonly = true s.Root.Readonly = true
return nil return nil
} }
@ -149,6 +167,7 @@ func WithRootFSReadonly() SpecOpts {
// WithNoNewPrivileges sets no_new_privileges on the process for the container // WithNoNewPrivileges sets no_new_privileges on the process for the container
func WithNoNewPrivileges(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { func WithNoNewPrivileges(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setProcess(s)
s.Process.NoNewPrivileges = true s.Process.NoNewPrivileges = true
return nil return nil
} }
@ -191,6 +210,7 @@ func WithHostLocaltime(_ context.Context, _ Client, _ *containers.Container, s *
func WithUserNamespace(container, host, size uint32) SpecOpts { func WithUserNamespace(container, host, size uint32) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
var hasUserns bool var hasUserns bool
setLinux(s)
for _, ns := range s.Linux.Namespaces { for _, ns := range s.Linux.Namespaces {
if ns.Type == specs.UserNamespace { if ns.Type == specs.UserNamespace {
hasUserns = true hasUserns = true
@ -216,6 +236,7 @@ func WithUserNamespace(container, host, size uint32) SpecOpts {
// WithCgroup sets the container's cgroup path // WithCgroup sets the container's cgroup path
func WithCgroup(path string) SpecOpts { func WithCgroup(path string) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setLinux(s)
s.Linux.CgroupsPath = path s.Linux.CgroupsPath = path
return nil return nil
} }
@ -229,6 +250,7 @@ func WithNamespacedCgroup() SpecOpts {
if err != nil { if err != nil {
return err return err
} }
setLinux(s)
s.Linux.CgroupsPath = filepath.Join("/", namespace, c.ID) s.Linux.CgroupsPath = filepath.Join("/", namespace, c.ID)
return nil return nil
} }
@ -239,6 +261,7 @@ func WithNamespacedCgroup() SpecOpts {
// user, uid, user:group, uid:gid, uid:group, user:gid // user, uid, user:group, uid:gid, uid:group, user:gid
func WithUser(userstr string) SpecOpts { func WithUser(userstr string) SpecOpts {
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) error { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) error {
setProcess(s)
parts := strings.Split(userstr, ":") parts := strings.Split(userstr, ":")
switch len(parts) { switch len(parts) {
case 1: case 1:
@ -316,6 +339,7 @@ func WithUser(userstr string) SpecOpts {
// WithUIDGID allows the UID and GID for the Process to be set // WithUIDGID allows the UID and GID for the Process to be set
func WithUIDGID(uid, gid uint32) SpecOpts { func WithUIDGID(uid, gid uint32) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setProcess(s)
s.Process.User.UID = uid s.Process.User.UID = uid
s.Process.User.GID = gid s.Process.User.GID = gid
return nil return nil
@ -328,6 +352,7 @@ func WithUIDGID(uid, gid uint32) SpecOpts {
// uid, and not returns error. // uid, and not returns error.
func WithUserID(uid uint32) SpecOpts { func WithUserID(uid uint32) SpecOpts {
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) {
setProcess(s)
if c.Snapshotter == "" && c.SnapshotKey == "" { if c.Snapshotter == "" && c.SnapshotKey == "" {
if !isRootfsAbs(s.Root.Path) { if !isRootfsAbs(s.Root.Path) {
return errors.Errorf("rootfs absolute path is required") return errors.Errorf("rootfs absolute path is required")
@ -380,6 +405,7 @@ func WithUserID(uid uint32) SpecOpts {
// it returns error. // it returns error.
func WithUsername(username string) SpecOpts { func WithUsername(username string) SpecOpts {
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) {
setProcess(s)
if c.Snapshotter == "" && c.SnapshotKey == "" { if c.Snapshotter == "" && c.SnapshotKey == "" {
if !isRootfsAbs(s.Root.Path) { if !isRootfsAbs(s.Root.Path) {
return errors.Errorf("rootfs absolute path is required") return errors.Errorf("rootfs absolute path is required")
@ -419,6 +445,8 @@ func WithUsername(username string) SpecOpts {
// WithAllCapabilities set all linux capabilities for the process // WithAllCapabilities set all linux capabilities for the process
func WithAllCapabilities(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { func WithAllCapabilities(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setCapabilities(s)
caps := getAllCapabilities() caps := getAllCapabilities()
s.Process.Capabilities.Bounding = caps s.Process.Capabilities.Bounding = caps

View File

@ -33,6 +33,7 @@ import (
// WithImageConfig configures the spec to from the configuration of an Image // WithImageConfig configures the spec to from the configuration of an Image
func WithImageConfig(image Image) SpecOpts { func WithImageConfig(image Image) SpecOpts {
return func(ctx context.Context, client Client, _ *containers.Container, s *specs.Spec) error { return func(ctx context.Context, client Client, _ *containers.Container, s *specs.Spec) error {
setProcess(s)
ic, err := image.Config(ctx) ic, err := image.Config(ctx)
if err != nil { if err != nil {
return err return err
@ -67,6 +68,7 @@ func WithImageConfig(image Image) SpecOpts {
// using a TTY // using a TTY
func WithTTY(width, height int) SpecOpts { func WithTTY(width, height int) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error { return func(_ context.Context, _ Client, _ *containers.Container, s *specs.Spec) error {
setProcess(s)
s.Process.Terminal = true s.Process.Terminal = true
if s.Process.ConsoleSize == nil { if s.Process.ConsoleSize == nil {
s.Process.ConsoleSize = &specs.Box{} s.Process.ConsoleSize = &specs.Box{}
@ -80,6 +82,7 @@ func WithTTY(width, height int) SpecOpts {
// WithUsername sets the username on the process // WithUsername sets the username on the process
func WithUsername(username string) SpecOpts { func WithUsername(username string) SpecOpts {
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) error { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) error {
setProcess(s)
s.Process.User.Username = username s.Process.User.Username = username
return nil return nil
} }