Add context and client to SpecOpts
In order to do more advanced spec generation with images, snapshots, etc, we need to inject the context and client into the spec generation code. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
ba69f5d488
commit
fa14f2ef3a
@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import specs "github.com/opencontainers/runtime-spec/specs-go"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
// WithApparmor sets the provided apparmor profile to the spec
|
// WithApparmor sets the provided apparmor profile to the spec
|
||||||
func WithApparmorProfile(profile string) SpecOpts {
|
func WithApparmorProfile(profile string) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Process.ApparmorProfile = profile
|
s.Process.ApparmorProfile = profile
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ func BenchmarkContainerCreate(b *testing.B) {
|
|||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spec, err := GenerateSpec(WithImageConfig(ctx, image), withTrue())
|
spec, err := GenerateSpec(ctx, client, WithImageConfig(image), withTrue())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
return
|
||||||
@ -63,7 +63,7 @@ func BenchmarkContainerStart(b *testing.B) {
|
|||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spec, err := GenerateSpec(WithImageConfig(ctx, image), withTrue())
|
spec, err := GenerateSpec(ctx, client, WithImageConfig(image), withTrue())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -98,7 +98,7 @@ func test(c config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logrus.Info("generating spec from image")
|
logrus.Info("generating spec from image")
|
||||||
spec, err := containerd.GenerateSpec(containerd.WithImageConfig(ctx, image), containerd.WithProcessArgs("true"))
|
spec, err := containerd.GenerateSpec(ctx, client, containerd.WithImageConfig(image), containerd.WithProcessArgs("true"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ type killer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withEnv(context *cli.Context) containerd.SpecOpts {
|
func withEnv(context *cli.Context) containerd.SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ gocontext.Context, _ *containerd.Client, s *specs.Spec) error {
|
||||||
env := context.StringSlice("env")
|
env := context.StringSlice("env")
|
||||||
if len(env) > 0 {
|
if len(env) > 0 {
|
||||||
s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, env)
|
s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, env)
|
||||||
@ -34,7 +34,7 @@ func withEnv(context *cli.Context) containerd.SpecOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withMounts(context *cli.Context) containerd.SpecOpts {
|
func withMounts(context *cli.Context) containerd.SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ gocontext.Context, _ *containerd.Client, s *specs.Spec) error {
|
||||||
for _, mount := range context.StringSlice("mount") {
|
for _, mount := range context.StringSlice("mount") {
|
||||||
m, err := parseMountFlag(mount)
|
m, err := parseMountFlag(mount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -90,7 +90,7 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
opts = append(opts, containerd.WithImageConfig(ctx, image))
|
opts = append(opts, containerd.WithImageConfig(image))
|
||||||
cOpts = append(cOpts, containerd.WithImage(image))
|
cOpts = append(cOpts, containerd.WithImage(image))
|
||||||
cOpts = append(cOpts, containerd.WithSnapshotter(context.String("snapshotter")))
|
cOpts = append(cOpts, containerd.WithSnapshotter(context.String("snapshotter")))
|
||||||
if context.Bool("readonly") {
|
if context.Bool("readonly") {
|
||||||
@ -111,7 +111,7 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
|||||||
if context.Bool("net-host") {
|
if context.Bool("net-host") {
|
||||||
opts = append(opts, setHostNetworking())
|
opts = append(opts, setHostNetworking())
|
||||||
}
|
}
|
||||||
spec, err := containerd.GenerateSpec(opts...)
|
spec, err := containerd.GenerateSpec(ctx, client, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ func TestCheckpointRestore(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spec, err := GenerateSpec(WithImageConfig(ctx, image), WithProcessArgs("sleep", "100"))
|
spec, err := GenerateSpec(ctx, client, WithImageConfig(image), WithProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -113,7 +113,7 @@ func TestCheckpointRestoreNewContainer(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spec, err := GenerateSpec(WithImageConfig(ctx, image), WithProcessArgs("sleep", "100"))
|
spec, err := GenerateSpec(ctx, client, WithImageConfig(image), WithProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -211,7 +211,7 @@ func TestCheckpointLeaveRunning(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spec, err := GenerateSpec(WithImageConfig(ctx, image), WithProcessArgs("sleep", "100"))
|
spec, err := GenerateSpec(ctx, client, WithImageConfig(image), WithProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -39,7 +39,7 @@ func TestContainerUpdate(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spec, err := generateSpec(WithImageConfig(ctx, image), withProcessArgs("sleep", "30"))
|
spec, err := generateSpec(ctx, client, WithImageConfig(image), withProcessArgs("sleep", "30"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -127,7 +127,7 @@ func TestShimInCgroup(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
spec, err := GenerateSpec(WithImageConfig(ctx, image), WithProcessArgs("sleep", "30"))
|
spec, err := GenerateSpec(ctx, client, WithImageConfig(image), WithProcessArgs("sleep", "30"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -202,7 +202,7 @@ func TestDaemonRestart(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "30"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "30"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -55,15 +55,15 @@ func TestNewContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
spec, err := generateSpec()
|
ctx, cancel := testContext()
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
spec, err := generateSpec(ctx, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := testContext()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
container, err := client.NewContainer(ctx, id, WithSpec(spec))
|
container, err := client.NewContainer(ctx, id, WithSpec(spec))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@ -107,7 +107,7 @@ func TestContainerStart(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withExitStatus(7))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withExitStatus(7))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -185,7 +185,7 @@ func TestContainerOutput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("echo", expected))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("echo", expected))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -258,7 +258,7 @@ func TestContainerExec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "100"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -357,7 +357,7 @@ func TestContainerPids(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "100"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -435,7 +435,7 @@ func TestContainerCloseIO(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withCat())
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withCat())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -505,7 +505,7 @@ func TestDeleteRunningContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "100"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -573,7 +573,7 @@ func TestContainerKill(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "10"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "10"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -642,7 +642,7 @@ func TestContainerNoBinaryExists(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), WithProcessArgs("nothing"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), WithProcessArgs("nothing"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -696,7 +696,7 @@ func TestContainerExecNoBinaryExists(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "100"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -769,8 +769,8 @@ func TestUserNamespaces(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(
|
spec, err := generateSpec(ctx, client,
|
||||||
withImageConfig(ctx, image),
|
withImageConfig(image),
|
||||||
withExitStatus(7),
|
withExitStatus(7),
|
||||||
withUserNamespace(0, 1000, 10000),
|
withUserNamespace(0, 1000, 10000),
|
||||||
)
|
)
|
||||||
@ -852,7 +852,7 @@ func TestWaitStoppedTask(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withExitStatus(7))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withExitStatus(7))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -928,7 +928,7 @@ func TestWaitStoppedProcess(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "100"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -1027,7 +1027,7 @@ func TestTaskForceDelete(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "30"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "30"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -1080,7 +1080,7 @@ func TestProcessForceDelete(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "30"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "30"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -1160,8 +1160,8 @@ func TestContainerHostname(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(
|
spec, err := generateSpec(ctx, client,
|
||||||
withImageConfig(ctx, image),
|
withImageConfig(image),
|
||||||
withProcessArgs("hostname"),
|
withProcessArgs("hostname"),
|
||||||
WithHostname(expected),
|
WithHostname(expected),
|
||||||
)
|
)
|
||||||
@ -1243,7 +1243,7 @@ func TestContainerExitedAtSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withTrue())
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withTrue())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -1315,7 +1315,7 @@ func TestDeleteContainerExecCreated(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := generateSpec(withImageConfig(ctx, image), withProcessArgs("sleep", "100"))
|
spec, err := generateSpec(ctx, client, withImageConfig(image), withProcessArgs("sleep", "100"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -11,12 +11,12 @@ import (
|
|||||||
|
|
||||||
const newLine = "\n"
|
const newLine = "\n"
|
||||||
|
|
||||||
func generateSpec(opts ...SpecOpts) (*specs.Spec, error) {
|
func generateSpec(ctx context.Context, client *Client, opts ...SpecOpts) (*specs.Spec, error) {
|
||||||
return GenerateSpec(opts...)
|
return GenerateSpec(ctx, client, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func withExitStatus(es int) SpecOpts {
|
func withExitStatus(es int) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Process.Args = []string{"sh", "-c", fmt.Sprintf("exit %d", es)}
|
s.Process.Args = []string{"sh", "-c", fmt.Sprintf("exit %d", es)}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -42,14 +42,9 @@ func withExecArgs(s *specs.Process, args ...string) {
|
|||||||
s.Args = args
|
s.Args = args
|
||||||
}
|
}
|
||||||
|
|
||||||
func withImageConfig(ctx context.Context, i Image) SpecOpts {
|
var (
|
||||||
return WithImageConfig(ctx, i)
|
withUserNamespace = WithUserNamespace
|
||||||
}
|
withRemappedSnapshot = WithRemappedSnapshot
|
||||||
|
withNewSnapshot = WithNewSnapshot
|
||||||
func withNewSnapshot(id string, i Image) NewContainerOpts {
|
withImageConfig = WithImageConfig
|
||||||
return WithNewSnapshot(id, i)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
var withUserNamespace = WithUserNamespace
|
|
||||||
|
|
||||||
var withRemappedSnapshot = WithRemappedSnapshot
|
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
|
|
||||||
const newLine = "\r\n"
|
const newLine = "\r\n"
|
||||||
|
|
||||||
func generateSpec(opts ...SpecOpts) (*specs.Spec, error) {
|
func generateSpec(ctx context.Context, client *Client, opts ...SpecOpts) (*specs.Spec, error) {
|
||||||
spec, err := GenerateSpec(opts...)
|
spec, err := GenerateSpec(ctx, client, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ func generateSpec(opts ...SpecOpts) (*specs.Spec, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withExitStatus(es int) SpecOpts {
|
func withExitStatus(es int) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Process.Args = []string{"powershell", "-noprofile", "exit", strconv.Itoa(es)}
|
s.Process.Args = []string{"powershell", "-noprofile", "exit", strconv.Itoa(es)}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -50,11 +50,9 @@ func withExecArgs(s *specs.Process, args ...string) {
|
|||||||
s.Args = append([]string{"powershell", "-noprofile"}, args...)
|
s.Args = append([]string{"powershell", "-noprofile"}, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func withImageConfig(ctx context.Context, i Image) SpecOpts {
|
func withImageConfig(i Image) SpecOpts {
|
||||||
// TODO: when windows has a snapshotter remove the withImageConfig helper
|
// TODO: when windows has a snapshotter remove the withImageConfig helper
|
||||||
return func(s *specs.Spec) error {
|
return withNoop
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func withNewSnapshot(id string, i Image) NewContainerOpts {
|
func withNewSnapshot(id string, i Image) NewContainerOpts {
|
||||||
@ -65,9 +63,7 @@ func withNewSnapshot(id string, i Image) NewContainerOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func withUserNamespace(u, g, s uint32) SpecOpts {
|
func withUserNamespace(u, g, s uint32) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return withNoop
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func withRemappedSnapshot(id string, i Image, u, g uint32) NewContainerOpts {
|
func withRemappedSnapshot(id string, i Image, u, g uint32) NewContainerOpts {
|
||||||
@ -75,3 +71,7 @@ func withRemappedSnapshot(id string, i Image, u, g uint32) NewContainerOpts {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withNoop(_ context.Context, _ *Client, _ *specs.Spec) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
10
spec.go
10
spec.go
@ -1,16 +1,20 @@
|
|||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import specs "github.com/opencontainers/runtime-spec/specs-go"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
// GenerateSpec will generate a default spec from the provided image
|
// GenerateSpec will generate a default spec from the provided image
|
||||||
// for use as a containerd container
|
// for use as a containerd container
|
||||||
func GenerateSpec(opts ...SpecOpts) (*specs.Spec, error) {
|
func GenerateSpec(ctx context.Context, client *Client, opts ...SpecOpts) (*specs.Spec, error) {
|
||||||
s, err := createDefaultSpec()
|
s, err := createDefaultSpec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
if err := o(s); err != nil {
|
if err := o(ctx, client, s); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
spec_opts.go
12
spec_opts.go
@ -1,13 +1,17 @@
|
|||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import specs "github.com/opencontainers/runtime-spec/specs-go"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
// 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(s *specs.Spec) error
|
type SpecOpts func(context.Context, *Client, *specs.Spec) error
|
||||||
|
|
||||||
// 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(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Process.Args = args
|
s.Process.Args = args
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -15,7 +19,7 @@ func WithProcessArgs(args ...string) SpecOpts {
|
|||||||
|
|
||||||
// WithHostname sets the container's hostname
|
// WithHostname sets the container's hostname
|
||||||
func WithHostname(name string) SpecOpts {
|
func WithHostname(name string) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Hostname = name
|
s.Hostname = name
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ 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(s *specs.Spec) error {
|
func WithTTY(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
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
|
||||||
@ -30,7 +30,7 @@ func WithTTY(s *specs.Spec) error {
|
|||||||
|
|
||||||
// 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(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
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:]...)
|
||||||
@ -44,7 +44,7 @@ func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts {
|
|||||||
// WithLinuxNamespace uses the passed in namespace for the spec. If a namespace of the same type already exists in the
|
// WithLinuxNamespace uses the passed in namespace for the spec. If a namespace of the same type already exists in the
|
||||||
// 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(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
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]
|
||||||
@ -60,11 +60,11 @@ func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithImageConfig configures the spec to from the configuration of an Image
|
// WithImageConfig configures the spec to from the configuration of an Image
|
||||||
func WithImageConfig(ctx context.Context, i Image) SpecOpts {
|
func WithImageConfig(i Image) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(ctx context.Context, client *Client, s *specs.Spec) error {
|
||||||
var (
|
var (
|
||||||
image = i.(*image)
|
image = i.(*image)
|
||||||
store = image.client.ContentStore()
|
store = client.ContentStore()
|
||||||
)
|
)
|
||||||
ic, err := image.i.Config(ctx, store)
|
ic, err := image.i.Config(ctx, store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -129,7 +129,7 @@ func WithImageConfig(ctx context.Context, i Image) SpecOpts {
|
|||||||
|
|
||||||
// WithRootFSPath specifies unmanaged rootfs path.
|
// WithRootFSPath specifies unmanaged rootfs path.
|
||||||
func WithRootFSPath(path string, readonly bool) SpecOpts {
|
func WithRootFSPath(path string, readonly bool) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Root = &specs.Root{
|
s.Root = &specs.Root{
|
||||||
Path: path,
|
Path: path,
|
||||||
Readonly: readonly,
|
Readonly: readonly,
|
||||||
@ -160,13 +160,13 @@ func WithResources(resources *specs.LinuxResources) UpdateTaskOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithNoNewPrivileges sets no_new_privileges on the process for the container
|
// WithNoNewPrivileges sets no_new_privileges on the process for the container
|
||||||
func WithNoNewPrivileges(s *specs.Spec) error {
|
func WithNoNewPrivileges(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Process.NoNewPrivileges = true
|
s.Process.NoNewPrivileges = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithHostHostsFile bind-mounts the host's /etc/hosts into the container as readonly
|
// WithHostHostsFile bind-mounts the host's /etc/hosts into the container as readonly
|
||||||
func WithHostHostsFile(s *specs.Spec) error {
|
func WithHostHostsFile(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Mounts = append(s.Mounts, specs.Mount{
|
s.Mounts = append(s.Mounts, specs.Mount{
|
||||||
Destination: "/etc/hosts",
|
Destination: "/etc/hosts",
|
||||||
Type: "bind",
|
Type: "bind",
|
||||||
@ -177,7 +177,7 @@ func WithHostHostsFile(s *specs.Spec) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithHostResolvconf bind-mounts the host's /etc/resolv.conf into the container as readonly
|
// WithHostResolvconf bind-mounts the host's /etc/resolv.conf into the container as readonly
|
||||||
func WithHostResolvconf(s *specs.Spec) error {
|
func WithHostResolvconf(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Mounts = append(s.Mounts, specs.Mount{
|
s.Mounts = append(s.Mounts, specs.Mount{
|
||||||
Destination: "/etc/resolv.conf",
|
Destination: "/etc/resolv.conf",
|
||||||
Type: "bind",
|
Type: "bind",
|
||||||
@ -188,7 +188,7 @@ func WithHostResolvconf(s *specs.Spec) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithHostLocaltime bind-mounts the host's /etc/localtime into the container as readonly
|
// WithHostLocaltime bind-mounts the host's /etc/localtime into the container as readonly
|
||||||
func WithHostLocaltime(s *specs.Spec) error {
|
func WithHostLocaltime(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Mounts = append(s.Mounts, specs.Mount{
|
s.Mounts = append(s.Mounts, specs.Mount{
|
||||||
Destination: "/etc/localtime",
|
Destination: "/etc/localtime",
|
||||||
Type: "bind",
|
Type: "bind",
|
||||||
@ -201,7 +201,7 @@ func WithHostLocaltime(s *specs.Spec) error {
|
|||||||
// WithUserNamespace sets the uid and gid mappings for the task
|
// WithUserNamespace sets the uid and gid mappings for the task
|
||||||
// this can be called multiple times to add more mappings to the generated spec
|
// this can be called multiple times to add more mappings to the generated spec
|
||||||
func WithUserNamespace(container, host, size uint32) SpecOpts {
|
func WithUserNamespace(container, host, size uint32) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
var hasUserns bool
|
var hasUserns bool
|
||||||
for _, ns := range s.Linux.Namespaces {
|
for _, ns := range s.Linux.Namespaces {
|
||||||
if ns.Type == specs.UserNamespace {
|
if ns.Type == specs.UserNamespace {
|
||||||
@ -271,7 +271,7 @@ func WithRemappedSnapshot(id string, i Image, uid, gid uint32) NewContainerOpts
|
|||||||
|
|
||||||
// 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(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Linux.CgroupsPath = path
|
s.Linux.CgroupsPath = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -279,8 +279,8 @@ func WithCgroup(path string) SpecOpts {
|
|||||||
|
|
||||||
// WithNamespacedCgroup uses the namespace set on the context to create a
|
// WithNamespacedCgroup uses the namespace set on the context to create a
|
||||||
// root directory for containers in the cgroup with the id as the subcgroup
|
// root directory for containers in the cgroup with the id as the subcgroup
|
||||||
func WithNamespacedCgroup(ctx context.Context, id string) SpecOpts {
|
func WithNamespacedCgroup(id string) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(ctx context.Context, _ *Client, s *specs.Spec) error {
|
||||||
namespace, err := namespaces.NamespaceRequired(ctx)
|
namespace, err := namespaces.NamespaceRequired(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -292,7 +292,7 @@ func WithNamespacedCgroup(ctx context.Context, id string) SpecOpts {
|
|||||||
|
|
||||||
// WithUserIDs allows the UID and GID for the Process to be set
|
// WithUserIDs allows the UID and GID for the Process to be set
|
||||||
func WithUserIDs(uid, gid uint32) SpecOpts {
|
func WithUserIDs(uid, gid uint32) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Process.User.UID = uid
|
s.Process.User.UID = uid
|
||||||
s.Process.User.GID = gid
|
s.Process.User.GID = gid
|
||||||
return nil
|
return nil
|
||||||
|
@ -15,11 +15,11 @@ import (
|
|||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WithImageConfig(ctx context.Context, i Image) SpecOpts {
|
func WithImageConfig(i Image) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(ctx context.Context, client *Client, s *specs.Spec) error {
|
||||||
var (
|
var (
|
||||||
image = i.(*image)
|
image = i.(*image)
|
||||||
store = image.client.ContentStore()
|
store = client.ContentStore()
|
||||||
)
|
)
|
||||||
ic, err := image.i.Config(ctx, store)
|
ic, err := image.i.Config(ctx, store)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -52,7 +52,7 @@ func WithImageConfig(ctx context.Context, i Image) SpecOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WithTTY(width, height int) SpecOpts {
|
func WithTTY(width, height int) SpecOpts {
|
||||||
return func(s *specs.Spec) error {
|
return func(_ context.Context, _ *Client, s *specs.Spec) error {
|
||||||
s.Process.Terminal = true
|
s.Process.Terminal = true
|
||||||
s.Process.ConsoleSize.Width = uint(width)
|
s.Process.ConsoleSize.Width = uint(width)
|
||||||
s.Process.ConsoleSize.Height = uint(height)
|
s.Process.ConsoleSize.Height = uint(height)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -11,7 +12,7 @@ import (
|
|||||||
func TestGenerateSpec(t *testing.T) {
|
func TestGenerateSpec(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s, err := GenerateSpec()
|
s, err := GenerateSpec(context.Background(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -51,7 +52,7 @@ func TestGenerateSpec(t *testing.T) {
|
|||||||
func TestSpecWithTTY(t *testing.T) {
|
func TestSpecWithTTY(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s, err := GenerateSpec(WithTTY)
|
s, err := GenerateSpec(context.Background(), nil, WithTTY)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -68,7 +69,7 @@ func TestWithLinuxNamespace(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
replacedNS := specs.LinuxNamespace{Type: specs.NetworkNamespace, Path: "/var/run/netns/test"}
|
replacedNS := specs.LinuxNamespace{Type: specs.NetworkNamespace, Path: "/var/run/netns/test"}
|
||||||
s, err := GenerateSpec(WithLinuxNamespace(replacedNS))
|
s, err := GenerateSpec(context.Background(), nil, WithLinuxNamespace(replacedNS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user