Skip to content

Commit 777cc50

Browse files
authored
Merge pull request #2592 from jterry75/specs_with_platform
Merges the oci package for Linux and Windows
2 parents 7e66292 + c818a6b commit 777cc50

9 files changed

Lines changed: 1076 additions & 1141 deletions

File tree

cmd/ctr/commands/run/run_windows.go

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,12 @@ import (
2222
"github.com/containerd/console"
2323
"github.com/containerd/containerd"
2424
"github.com/containerd/containerd/cmd/ctr/commands"
25-
"github.com/containerd/containerd/containers"
2625
"github.com/containerd/containerd/oci"
2726
specs "github.com/opencontainers/runtime-spec/specs-go"
2827
"github.com/sirupsen/logrus"
2928
"github.com/urfave/cli"
3029
)
3130

32-
func withTTY(terminal bool) oci.SpecOpts {
33-
if !terminal {
34-
return func(ctx gocontext.Context, client oci.Client, c *containers.Container, s *specs.Spec) error {
35-
s.Process.Terminal = false
36-
return nil
37-
}
38-
}
39-
40-
con := console.Current()
41-
size, err := con.Size()
42-
if err != nil {
43-
logrus.WithError(err).Error("console size")
44-
}
45-
return oci.WithTTY(int(size.Width), int(size.Height))
46-
}
47-
4831
// NewContainer creates a new container
4932
func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli.Context) (containerd.Container, error) {
5033
var (
@@ -73,7 +56,17 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
7356
opts = append(opts, oci.WithImageConfig(image))
7457
opts = append(opts, oci.WithEnv(context.StringSlice("env")))
7558
opts = append(opts, withMounts(context))
76-
opts = append(opts, withTTY(context.Bool("tty")))
59+
if context.Bool("tty") {
60+
opts = append(opts, oci.WithTTY)
61+
62+
con := console.Current()
63+
size, err := con.Size()
64+
if err != nil {
65+
logrus.WithError(err).Error("console size")
66+
}
67+
opts = append(opts, oci.WithTTYSize(int(size.Width), int(size.Height)))
68+
}
69+
7770
if len(args) > 0 {
7871
opts = append(opts, oci.WithProcessArgs(args...))
7972
}

oci/spec.go

Lines changed: 202 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,55 @@ package oci
1818

1919
import (
2020
"context"
21+
"path/filepath"
22+
23+
"github.com/containerd/containerd/namespaces"
24+
"github.com/containerd/containerd/platforms"
2125

2226
"github.com/containerd/containerd/containers"
2327
specs "github.com/opencontainers/runtime-spec/specs-go"
2428
)
2529

30+
const (
31+
rwm = "rwm"
32+
defaultRootfsPath = "rootfs"
33+
)
34+
35+
var (
36+
defaultUnixEnv = []string{
37+
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
38+
}
39+
)
40+
2641
// Spec is a type alias to the OCI runtime spec to allow third part SpecOpts
2742
// to be created without the "issues" with go vendoring and package imports
2843
type Spec = specs.Spec
2944

3045
// GenerateSpec will generate a default spec from the provided image
3146
// for use as a containerd container
3247
func GenerateSpec(ctx context.Context, client Client, c *containers.Container, opts ...SpecOpts) (*Spec, error) {
33-
s, err := createDefaultSpec(ctx, c.ID)
48+
return GenerateSpecWithPlatform(ctx, client, platforms.DefaultString(), c, opts...)
49+
}
50+
51+
// GenerateSpecWithPlatform will generate a default spec from the provided image
52+
// for use as a containerd container in the platform requested.
53+
func GenerateSpecWithPlatform(ctx context.Context, client Client, platform string, c *containers.Container, opts ...SpecOpts) (*Spec, error) {
54+
plat, err := platforms.Parse(platform)
3455
if err != nil {
3556
return nil, err
3657
}
3758

38-
return s, ApplyOpts(ctx, client, c, s, opts...)
59+
var s Spec
60+
if plat.OS == "windows" {
61+
err = populateDefaultWindowsSpec(ctx, &s, c.ID)
62+
} else {
63+
err = populateDefaultUnixSpec(ctx, &s, c.ID)
64+
}
65+
if err != nil {
66+
return nil, err
67+
}
68+
69+
return &s, ApplyOpts(ctx, client, c, &s, opts...)
3970
}
4071

4172
// ApplyOpts applys the options to the given spec, injecting data from the
@@ -50,7 +81,173 @@ func ApplyOpts(ctx context.Context, client Client, c *containers.Container, s *S
5081
return nil
5182
}
5283

53-
func createDefaultSpec(ctx context.Context, id string) (*Spec, error) {
54-
var s Spec
55-
return &s, populateDefaultSpec(ctx, &s, id)
84+
func defaultUnixCaps() []string {
85+
return []string{
86+
"CAP_CHOWN",
87+
"CAP_DAC_OVERRIDE",
88+
"CAP_FSETID",
89+
"CAP_FOWNER",
90+
"CAP_MKNOD",
91+
"CAP_NET_RAW",
92+
"CAP_SETGID",
93+
"CAP_SETUID",
94+
"CAP_SETFCAP",
95+
"CAP_SETPCAP",
96+
"CAP_NET_BIND_SERVICE",
97+
"CAP_SYS_CHROOT",
98+
"CAP_KILL",
99+
"CAP_AUDIT_WRITE",
100+
}
101+
}
102+
103+
func defaultUnixNamespaces() []specs.LinuxNamespace {
104+
return []specs.LinuxNamespace{
105+
{
106+
Type: specs.PIDNamespace,
107+
},
108+
{
109+
Type: specs.IPCNamespace,
110+
},
111+
{
112+
Type: specs.UTSNamespace,
113+
},
114+
{
115+
Type: specs.MountNamespace,
116+
},
117+
{
118+
Type: specs.NetworkNamespace,
119+
},
120+
}
121+
}
122+
123+
func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error {
124+
ns, err := namespaces.NamespaceRequired(ctx)
125+
if err != nil {
126+
return err
127+
}
128+
129+
*s = Spec{
130+
Version: specs.Version,
131+
Root: &specs.Root{
132+
Path: defaultRootfsPath,
133+
},
134+
Process: &specs.Process{
135+
Env: defaultUnixEnv,
136+
Cwd: "/",
137+
NoNewPrivileges: true,
138+
User: specs.User{
139+
UID: 0,
140+
GID: 0,
141+
},
142+
Capabilities: &specs.LinuxCapabilities{
143+
Bounding: defaultUnixCaps(),
144+
Permitted: defaultUnixCaps(),
145+
Inheritable: defaultUnixCaps(),
146+
Effective: defaultUnixCaps(),
147+
},
148+
Rlimits: []specs.POSIXRlimit{
149+
{
150+
Type: "RLIMIT_NOFILE",
151+
Hard: uint64(1024),
152+
Soft: uint64(1024),
153+
},
154+
},
155+
},
156+
Mounts: []specs.Mount{
157+
{
158+
Destination: "/proc",
159+
Type: "proc",
160+
Source: "proc",
161+
},
162+
{
163+
Destination: "/dev",
164+
Type: "tmpfs",
165+
Source: "tmpfs",
166+
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
167+
},
168+
{
169+
Destination: "/dev/pts",
170+
Type: "devpts",
171+
Source: "devpts",
172+
Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
173+
},
174+
{
175+
Destination: "/dev/shm",
176+
Type: "tmpfs",
177+
Source: "shm",
178+
Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
179+
},
180+
{
181+
Destination: "/dev/mqueue",
182+
Type: "mqueue",
183+
Source: "mqueue",
184+
Options: []string{"nosuid", "noexec", "nodev"},
185+
},
186+
{
187+
Destination: "/sys",
188+
Type: "sysfs",
189+
Source: "sysfs",
190+
Options: []string{"nosuid", "noexec", "nodev", "ro"},
191+
},
192+
{
193+
Destination: "/run",
194+
Type: "tmpfs",
195+
Source: "tmpfs",
196+
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
197+
},
198+
},
199+
Linux: &specs.Linux{
200+
MaskedPaths: []string{
201+
"/proc/acpi",
202+
"/proc/kcore",
203+
"/proc/keys",
204+
"/proc/latency_stats",
205+
"/proc/timer_list",
206+
"/proc/timer_stats",
207+
"/proc/sched_debug",
208+
"/sys/firmware",
209+
"/proc/scsi",
210+
},
211+
ReadonlyPaths: []string{
212+
"/proc/asound",
213+
"/proc/bus",
214+
"/proc/fs",
215+
"/proc/irq",
216+
"/proc/sys",
217+
"/proc/sysrq-trigger",
218+
},
219+
CgroupsPath: filepath.Join("/", ns, id),
220+
Resources: &specs.LinuxResources{
221+
Devices: []specs.LinuxDeviceCgroup{
222+
{
223+
Allow: false,
224+
Access: rwm,
225+
},
226+
},
227+
},
228+
Namespaces: defaultUnixNamespaces(),
229+
},
230+
}
231+
return nil
232+
}
233+
234+
func populateDefaultWindowsSpec(ctx context.Context, s *Spec, id string) error {
235+
*s = Spec{
236+
Version: specs.Version,
237+
Root: &specs.Root{},
238+
Process: &specs.Process{
239+
Cwd: `C:\`,
240+
ConsoleSize: &specs.Box{
241+
Width: 80,
242+
Height: 20,
243+
},
244+
},
245+
Windows: &specs.Windows{
246+
IgnoreFlushesDuringBoot: true,
247+
Network: &specs.WindowsNetwork{
248+
AllowUnqualifiedDNSQuery: true,
249+
},
250+
},
251+
}
252+
return nil
56253
}

0 commit comments

Comments
 (0)