api/services: define the container metadata service
Working from feedback on the existing implementation, we have now introduced a central metadata object to represent the lifecycle and pin the resources required to implement what people today know as containers. This includes the runtime specification and the root filesystem snapshots. We also allow arbitrary labeling of the container. Such provisions will bring the containerd definition of container closer to what is expected by users. The objects that encompass today's ContainerService, centered around the runtime, will be known as tasks. These tasks take on the existing lifecycle behavior of containerd's containers, which means that they are deleted when they exit. Largely, there are no other changes except for naming. The `Container` object will operate purely as a metadata object. No runtime state will be held on `Container`. It only informs the execution service on what is required for creating tasks and the resources in use by that container. The resources referenced by that container will be deleted when the container is deleted, if not in use. In this sense, users can create, list, label and delete containers in a similar way as they do with docker today, without the complexity of runtime locks that plagues current implementations. Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
@@ -46,7 +46,8 @@ var checkpointCommand = cli.Command{
|
||||
if id == "" {
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
containers, err := getExecutionService(context)
|
||||
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -59,13 +60,13 @@ var checkpointCommand = cli.Command{
|
||||
return errors.Wrap(err, "failed resolving image store")
|
||||
}
|
||||
var spec specs.Spec
|
||||
info, err := containers.Info(ctx, &execution.InfoRequest{
|
||||
ID: id,
|
||||
info, err := tasks.Info(ctx, &execution.InfoRequest{
|
||||
ContainerID: id,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(info.Spec.Value, &spec); err != nil {
|
||||
if err := json.Unmarshal(info.Task.Spec.Value, &spec); err != nil {
|
||||
return err
|
||||
}
|
||||
stopped := context.Bool("exit")
|
||||
@@ -73,22 +74,22 @@ var checkpointCommand = cli.Command{
|
||||
// we pause the container and give us time to checkpoint the filesystem before
|
||||
// it resumes execution
|
||||
if !stopped {
|
||||
if _, err := containers.Pause(ctx, &execution.PauseRequest{
|
||||
ID: id,
|
||||
if _, err := tasks.Pause(ctx, &execution.PauseRequest{
|
||||
ContainerID: id,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if _, err := containers.Resume(ctx, &execution.ResumeRequest{
|
||||
ID: id,
|
||||
if _, err := tasks.Resume(ctx, &execution.ResumeRequest{
|
||||
ContainerID: id,
|
||||
}); err != nil {
|
||||
logrus.WithError(err).Error("ctr: unable to resume container")
|
||||
}
|
||||
}()
|
||||
}
|
||||
checkpoint, err := containers.Checkpoint(ctx, &execution.CheckpointRequest{
|
||||
ID: id,
|
||||
Exit: context.Bool("exit"),
|
||||
checkpoint, err := tasks.Checkpoint(ctx, &execution.CheckpointRequest{
|
||||
ContainerID: id,
|
||||
Exit: context.Bool("exit"),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
gocontext "context"
|
||||
|
||||
containersapi "github.com/containerd/containerd/api/services/containers"
|
||||
"github.com/containerd/containerd/api/services/execution"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
@@ -13,10 +14,15 @@ var deleteCommand = cli.Command{
|
||||
Usage: "delete an existing container",
|
||||
ArgsUsage: "CONTAINER",
|
||||
Action: func(context *cli.Context) error {
|
||||
containers, err := getExecutionService(context)
|
||||
containers, err := getContainersService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
snapshotter, err := getSnapshotter(context)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -26,13 +32,20 @@ var deleteCommand = cli.Command{
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
ctx := gocontext.TODO()
|
||||
_, err = containers.Delete(ctx, &execution.DeleteRequest{
|
||||
_, err = containers.Delete(ctx, &containersapi.DeleteContainerRequest{
|
||||
ID: id,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to delete container")
|
||||
}
|
||||
|
||||
_, err = tasks.Delete(ctx, &execution.DeleteRequest{
|
||||
ContainerID: id,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to delete container")
|
||||
}
|
||||
|
||||
if err := snapshotter.Remove(ctx, id); err != nil {
|
||||
return errors.Wrapf(err, "failed to remove snapshot %q", id)
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ var eventsCommand = cli.Command{
|
||||
Name: "events",
|
||||
Usage: "display containerd events",
|
||||
Action: func(context *cli.Context) error {
|
||||
containers, err := getExecutionService(context)
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events, err := containers.Events(gocontext.Background(), &execution.EventsRequest{})
|
||||
events, err := tasks.Events(gocontext.Background(), &execution.EventsRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -37,11 +37,11 @@ var execCommand = cli.Command{
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
|
||||
containers, err := getExecutionService(context)
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events, err := containers.Events(ctx, &execution.EventsRequest{})
|
||||
events, err := tasks.Events(ctx, &execution.EventsRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,12 +66,12 @@ var execCommand = cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
response, err := containers.Exec(ctx, request)
|
||||
response, err := tasks.Exec(ctx, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if request.Terminal {
|
||||
if err := handleConsoleResize(ctx, containers, id, response.Pid, con); err != nil {
|
||||
if err := handleConsoleResize(ctx, tasks, id, response.Pid, con); err != nil {
|
||||
logrus.WithError(err).Error("console resize")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func newExecRequest(context *cli.Context, tmpDir, id string) (*execution.ExecReq
|
||||
return nil, err
|
||||
}
|
||||
return &execution.ExecRequest{
|
||||
ID: id,
|
||||
ContainerID: id,
|
||||
Spec: &protobuf.Any{
|
||||
TypeUrl: specs.Version,
|
||||
Value: data,
|
||||
|
||||
@@ -23,7 +23,7 @@ func newExecRequest(context *cli.Context, tmpDir, id string) (*execution.ExecReq
|
||||
}
|
||||
now := time.Now().UnixNano()
|
||||
request := &execution.ExecRequest{
|
||||
ID: id,
|
||||
ContainerID: id,
|
||||
Spec: &protobuf.Any{
|
||||
TypeUrl: specs.Version,
|
||||
Value: data,
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
gocontext "context"
|
||||
"fmt"
|
||||
|
||||
containersapi "github.com/containerd/containerd/api/services/containers"
|
||||
"github.com/containerd/containerd/api/services/execution"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
@@ -26,11 +27,30 @@ var infoCommand = cli.Command{
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
|
||||
containers, err := getExecutionService(context)
|
||||
containers, err := getContainersService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
response, err := containers.Info(gocontext.Background(), &execution.InfoRequest{ID: id})
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
containerResponse, err := containers.Get(gocontext.TODO(), &containersapi.GetContainerRequest{ID: id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(stevvooe): Just dumping the container and the task, for now. We
|
||||
// should split this into two separate commands.
|
||||
cjson, err := json.MarshalIndent(containerResponse, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(string(cjson))
|
||||
|
||||
response, err := tasks.Info(gocontext.Background(), &execution.InfoRequest{ContainerID: id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ var killCommand = cli.Command{
|
||||
}
|
||||
|
||||
killRequest := &execution.KillRequest{
|
||||
ID: id,
|
||||
Signal: uint32(signal),
|
||||
ContainerID: id,
|
||||
Signal: uint32(signal),
|
||||
PidOrAll: &execution.KillRequest_Pid{
|
||||
Pid: uint32(pid),
|
||||
},
|
||||
@@ -62,11 +62,11 @@ var killCommand = cli.Command{
|
||||
}
|
||||
}
|
||||
|
||||
containers, err := getExecutionService(context)
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = containers.Kill(gocontext.Background(), killRequest)
|
||||
_, err = tasks.Kill(gocontext.Background(), killRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,10 +6,16 @@ import (
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
containersapi "github.com/containerd/containerd/api/services/containers"
|
||||
"github.com/containerd/containerd/api/services/execution"
|
||||
tasktypes "github.com/containerd/containerd/api/types/task"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var containersCommand = cli.Command{
|
||||
Name: "containers",
|
||||
}
|
||||
|
||||
var listCommand = cli.Command{
|
||||
Name: "list",
|
||||
Aliases: []string{"ls"},
|
||||
@@ -22,11 +28,18 @@ var listCommand = cli.Command{
|
||||
},
|
||||
Action: func(context *cli.Context) error {
|
||||
quiet := context.Bool("quiet")
|
||||
containers, err := getExecutionService(context)
|
||||
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
response, err := containers.List(gocontext.Background(), &execution.ListRequest{})
|
||||
|
||||
containers, err := getContainersService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response, err := containers.List(gocontext.Background(), &containersapi.ListContainersRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -36,13 +49,35 @@ var listCommand = cli.Command{
|
||||
fmt.Println(c.ID)
|
||||
}
|
||||
} else {
|
||||
|
||||
tasksResponse, err := tasks.List(gocontext.TODO(), &execution.ListRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Join with tasks to get status.
|
||||
tasksByContainerID := map[string]*tasktypes.Task{}
|
||||
for _, task := range tasksResponse.Tasks {
|
||||
task.Descriptor()
|
||||
tasksByContainerID[task.ContainerID] = task
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0)
|
||||
fmt.Fprintln(w, "ID\tPID\tSTATUS")
|
||||
fmt.Fprintln(w, "ID\tIMAGE\tPID\tSTATUS")
|
||||
for _, c := range response.Containers {
|
||||
if _, err := fmt.Fprintf(w, "%s\t%d\t%s\n",
|
||||
var status string
|
||||
task, ok := tasksByContainerID[c.ID]
|
||||
if ok {
|
||||
status = task.Status.String()
|
||||
} else {
|
||||
status = "STOPPED" // TODO(stevvooe): Is this assumption correct?
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%d\t%s\n",
|
||||
c.ID,
|
||||
c.Pid,
|
||||
c.Status.String(),
|
||||
c.Image,
|
||||
task.Pid,
|
||||
status,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ var pauseCommand = cli.Command{
|
||||
Usage: "pause an existing container",
|
||||
ArgsUsage: "CONTAINER",
|
||||
Action: func(context *cli.Context) error {
|
||||
containers, err := getExecutionService(context)
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -21,8 +21,8 @@ var pauseCommand = cli.Command{
|
||||
if id == "" {
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
_, err = containers.Pause(gocontext.Background(), &execution.PauseRequest{
|
||||
ID: id,
|
||||
_, err = tasks.Pause(gocontext.Background(), &execution.PauseRequest{
|
||||
ContainerID: id,
|
||||
})
|
||||
return err
|
||||
},
|
||||
|
||||
@@ -27,15 +27,15 @@ var psCommand = cli.Command{
|
||||
}
|
||||
|
||||
pr := &execution.ProcessesRequest{
|
||||
ID: id,
|
||||
ContainerID: id,
|
||||
}
|
||||
|
||||
containers, err := getExecutionService(context)
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := containers.Processes(gocontext.Background(), pr)
|
||||
resp, err := tasks.Processes(gocontext.Background(), pr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ var resumeCommand = cli.Command{
|
||||
Usage: "resume a paused container",
|
||||
ArgsUsage: "CONTAINER",
|
||||
Action: func(context *cli.Context) error {
|
||||
containers, err := getExecutionService(context)
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -21,8 +21,8 @@ var resumeCommand = cli.Command{
|
||||
if id == "" {
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
_, err = containers.Resume(gocontext.Background(), &execution.ResumeRequest{
|
||||
ID: id,
|
||||
_, err = tasks.Resume(gocontext.Background(), &execution.ResumeRequest{
|
||||
ContainerID: id,
|
||||
})
|
||||
return err
|
||||
},
|
||||
|
||||
@@ -80,7 +80,11 @@ var runCommand = cli.Command{
|
||||
if id == "" {
|
||||
return errors.New("container id must be provided")
|
||||
}
|
||||
containers, err := getExecutionService(context)
|
||||
containers, err := getContainersService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tasks, err := getTasksService(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -89,7 +93,7 @@ var runCommand = cli.Command{
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
events, err := containers.Events(ctx, &execution.EventsRequest{})
|
||||
events, err := tasks.Events(ctx, &execution.EventsRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -227,11 +231,22 @@ var runCommand = cli.Command{
|
||||
return err
|
||||
}
|
||||
if len(spec) == 0 {
|
||||
if spec, err = newSpec(context, &imageConfig.Config, ref); err != nil {
|
||||
if spec, err = newContainerSpec(context, &imageConfig.Config, ref); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
create, err := newCreateRequest(context, id, tmpDir, checkpoint, mounts, spec)
|
||||
|
||||
createContainer, err := newCreateContainerRequest(context, id, id, spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = containers.Create(ctx, createContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
create, err := newCreateTaskRequest(context, id, tmpDir, checkpoint, mounts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -247,22 +262,22 @@ var runCommand = cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
response, err := containers.Create(ctx, create)
|
||||
response, err := tasks.Create(ctx, create)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pid := response.Pid
|
||||
if create.Terminal {
|
||||
if err := handleConsoleResize(ctx, containers, id, pid, con); err != nil {
|
||||
if err := handleConsoleResize(ctx, tasks, id, pid, con); err != nil {
|
||||
logrus.WithError(err).Error("console resize")
|
||||
}
|
||||
} else {
|
||||
sigc := forwardAllSignals(containers, id)
|
||||
sigc := forwardAllSignals(tasks, id)
|
||||
defer stopCatch(sigc)
|
||||
}
|
||||
if checkpoint == nil {
|
||||
if _, err := containers.Start(ctx, &execution.StartRequest{
|
||||
ID: id,
|
||||
if _, err := tasks.Start(ctx, &execution.StartRequest{
|
||||
ContainerID: id,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -274,8 +289,8 @@ var runCommand = cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := containers.Delete(ctx, &execution.DeleteRequest{
|
||||
ID: response.ID,
|
||||
if _, err := tasks.Delete(ctx, &execution.DeleteRequest{
|
||||
ContainerID: response.ContainerID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/containerd/console"
|
||||
containersapi "github.com/containerd/containerd/api/services/containers"
|
||||
"github.com/containerd/containerd/api/services/execution"
|
||||
"github.com/containerd/containerd/api/types/descriptor"
|
||||
"github.com/containerd/containerd/api/types/mount"
|
||||
@@ -265,7 +266,7 @@ func getConfig(context *cli.Context, imageConfig *ocispec.ImageConfig, rootfs st
|
||||
return customSpec(config, rootfs)
|
||||
}
|
||||
|
||||
func newSpec(context *cli.Context, config *ocispec.ImageConfig, imageRef string) ([]byte, error) {
|
||||
func newContainerSpec(context *cli.Context, config *ocispec.ImageConfig, imageRef string) ([]byte, error) {
|
||||
s, err := getConfig(context, config, context.String("rootfs"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -277,26 +278,31 @@ func newSpec(context *cli.Context, config *ocispec.ImageConfig, imageRef string)
|
||||
return json.Marshal(s)
|
||||
}
|
||||
|
||||
func newCreateRequest(context *cli.Context, id, tmpDir string, checkpoint *ocispec.Descriptor, mounts []mountt.Mount, spec []byte) (*execution.CreateRequest, error) {
|
||||
create := &execution.CreateRequest{
|
||||
ID: id,
|
||||
Spec: &protobuf.Any{
|
||||
TypeUrl: specs.Version,
|
||||
Value: spec,
|
||||
func newCreateContainerRequest(context *cli.Context, id, snapshot string, spec []byte) (*containersapi.CreateContainerRequest, error) {
|
||||
create := &containersapi.CreateContainerRequest{
|
||||
Container: containersapi.Container{
|
||||
ID: id,
|
||||
Spec: &protobuf.Any{
|
||||
TypeUrl: specs.Version,
|
||||
Value: spec,
|
||||
},
|
||||
Runtime: context.String("runtime"),
|
||||
RootFS: snapshot,
|
||||
},
|
||||
Runtime: context.String("runtime"),
|
||||
Terminal: context.Bool("tty"),
|
||||
Stdin: filepath.Join(tmpDir, "stdin"),
|
||||
Stdout: filepath.Join(tmpDir, "stdout"),
|
||||
Stderr: filepath.Join(tmpDir, "stderr"),
|
||||
}
|
||||
if checkpoint != nil {
|
||||
create.Checkpoint = &descriptor.Descriptor{
|
||||
MediaType: checkpoint.MediaType,
|
||||
Size_: checkpoint.Size,
|
||||
Digest: checkpoint.Digest,
|
||||
}
|
||||
|
||||
return create, nil
|
||||
}
|
||||
|
||||
func newCreateTaskRequest(context *cli.Context, id, tmpDir string, checkpoint *ocispec.Descriptor, mounts []mountt.Mount) (*execution.CreateRequest, error) {
|
||||
create := &execution.CreateRequest{
|
||||
ContainerID: id,
|
||||
Terminal: context.Bool("tty"),
|
||||
Stdin: filepath.Join(tmpDir, "stdin"),
|
||||
Stdout: filepath.Join(tmpDir, "stdout"),
|
||||
Stderr: filepath.Join(tmpDir, "stderr"),
|
||||
}
|
||||
|
||||
for _, m := range mounts {
|
||||
create.Rootfs = append(create.Rootfs, &mount.Mount{
|
||||
Type: m.Type,
|
||||
@@ -304,20 +310,29 @@ func newCreateRequest(context *cli.Context, id, tmpDir string, checkpoint *ocisp
|
||||
Options: m.Options,
|
||||
})
|
||||
}
|
||||
|
||||
if checkpoint != nil {
|
||||
create.Checkpoint = &descriptor.Descriptor{
|
||||
MediaType: checkpoint.MediaType,
|
||||
Size_: checkpoint.Size,
|
||||
Digest: checkpoint.Digest,
|
||||
}
|
||||
}
|
||||
|
||||
return create, nil
|
||||
}
|
||||
|
||||
func handleConsoleResize(ctx context.Context, service execution.ContainerServiceClient, id string, pid uint32, con console.Console) error {
|
||||
func handleConsoleResize(ctx context.Context, service execution.TasksClient, id string, pid uint32, con console.Console) error {
|
||||
// do an initial resize of the console
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := service.Pty(ctx, &execution.PtyRequest{
|
||||
ID: id,
|
||||
Pid: pid,
|
||||
Width: uint32(size.Width),
|
||||
Height: uint32(size.Height),
|
||||
ContainerID: id,
|
||||
Pid: pid,
|
||||
Width: uint32(size.Width),
|
||||
Height: uint32(size.Height),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -331,10 +346,10 @@ func handleConsoleResize(ctx context.Context, service execution.ContainerService
|
||||
continue
|
||||
}
|
||||
if _, err := service.Pty(ctx, &execution.PtyRequest{
|
||||
ID: id,
|
||||
Pid: pid,
|
||||
Width: uint32(size.Width),
|
||||
Height: uint32(size.Height),
|
||||
ContainerID: id,
|
||||
Pid: pid,
|
||||
Width: uint32(size.Width),
|
||||
Height: uint32(size.Height),
|
||||
}); err != nil {
|
||||
logrus.WithError(err).Error("resize pty")
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/containerd/console"
|
||||
containersapi "github.com/containerd/containerd/api/services/containers"
|
||||
"github.com/containerd/containerd/api/services/execution"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/mount"
|
||||
@@ -117,7 +118,7 @@ func getConfig(context *cli.Context, imageConfig *ocispec.ImageConfig, rootfs st
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func newSpec(context *cli.Context, config *ocispec.ImageConfig, imageRef string) ([]byte, error) {
|
||||
func newContainerSpec(context *cli.Context, config *ocispec.ImageConfig, imageRef string) ([]byte, error) {
|
||||
spec, err := getConfig(context, config, context.String("rootfs"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -136,17 +137,28 @@ func newSpec(context *cli.Context, config *ocispec.ImageConfig, imageRef string)
|
||||
return json.Marshal(rtSpec)
|
||||
}
|
||||
|
||||
func newCreateRequest(context *cli.Context, id, tmpDir string, checkpoint *ocispec.Descriptor, mounts []mount.Mount, spec []byte) (*execution.CreateRequest, error) {
|
||||
create := &execution.CreateRequest{
|
||||
ID: id,
|
||||
Spec: &protobuf.Any{
|
||||
TypeUrl: specs.Version,
|
||||
Value: spec,
|
||||
func newCreateContainerRequest(context *cli.Context, id, snapshot string, spec []byte) (*containersapi.CreateContainerRequest, error) {
|
||||
create := &containersapi.CreateContainerRequest{
|
||||
Container: containersapi.Container{
|
||||
ID: id,
|
||||
Spec: &protobuf.Any{
|
||||
TypeUrl: specs.Version,
|
||||
Value: spec,
|
||||
},
|
||||
Runtime: context.String("runtime"),
|
||||
RootFS: snapshot,
|
||||
},
|
||||
Runtime: context.String("runtime"),
|
||||
Terminal: context.Bool("tty"),
|
||||
Stdin: fmt.Sprintf(`%s\ctr-%s-stdin`, pipeRoot, id),
|
||||
Stdout: fmt.Sprintf(`%s\ctr-%s-stdout`, pipeRoot, id),
|
||||
}
|
||||
|
||||
return create, nil
|
||||
}
|
||||
|
||||
func newCreateTaskRequest(context *cli.Context, id, tmpDir string, checkpoint *ocispec.Descriptor, mounts []mount.Mount) (*execution.CreateRequest, error) {
|
||||
create := &execution.CreateRequest{
|
||||
ContainerID: id,
|
||||
Terminal: context.Bool("tty"),
|
||||
Stdin: fmt.Sprintf(`%s\ctr-%s-stdin`, pipeRoot, id),
|
||||
Stdout: fmt.Sprintf(`%s\ctr-%s-stdout`, pipeRoot, id),
|
||||
}
|
||||
if !create.Terminal {
|
||||
create.Stderr = fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id)
|
||||
@@ -154,7 +166,7 @@ func newCreateRequest(context *cli.Context, id, tmpDir string, checkpoint *ocisp
|
||||
return create, nil
|
||||
}
|
||||
|
||||
func handleConsoleResize(ctx context.Context, service execution.ContainerServiceClient, id string, pid uint32, con console.Console) error {
|
||||
func handleConsoleResize(ctx context.Context, service execution.TasksClient, id string, pid uint32, con console.Console) error {
|
||||
// do an initial resize of the console
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
@@ -173,10 +185,10 @@ func handleConsoleResize(ctx context.Context, service execution.ContainerService
|
||||
|
||||
if size.Width != prevSize.Width || size.Height != prevSize.Height {
|
||||
if _, err := service.Pty(ctx, &execution.PtyRequest{
|
||||
ID: id,
|
||||
Pid: pid,
|
||||
Width: uint32(size.Width),
|
||||
Height: uint32(size.Height),
|
||||
ContainerID: id,
|
||||
Pid: pid,
|
||||
Width: uint32(size.Width),
|
||||
Height: uint32(size.Height),
|
||||
}); err != nil {
|
||||
log.G(ctx).WithError(err).Error("resize pty")
|
||||
}
|
||||
|
||||
@@ -13,13 +13,14 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
containersapi "github.com/containerd/containerd/api/services/containers"
|
||||
contentapi "github.com/containerd/containerd/api/services/content"
|
||||
diffapi "github.com/containerd/containerd/api/services/diff"
|
||||
"github.com/containerd/containerd/api/services/execution"
|
||||
imagesapi "github.com/containerd/containerd/api/services/images"
|
||||
snapshotapi "github.com/containerd/containerd/api/services/snapshot"
|
||||
versionservice "github.com/containerd/containerd/api/services/version"
|
||||
"github.com/containerd/containerd/api/types/container"
|
||||
"github.com/containerd/containerd/api/types/task"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
contentservice "github.com/containerd/containerd/services/content"
|
||||
@@ -34,12 +35,20 @@ import (
|
||||
|
||||
var grpcConn *grpc.ClientConn
|
||||
|
||||
func getExecutionService(context *cli.Context) (execution.ContainerServiceClient, error) {
|
||||
func getContainersService(context *cli.Context) (containersapi.ContainersClient, error) {
|
||||
conn, err := getGRPCConnection(context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return execution.NewContainerServiceClient(conn), nil
|
||||
return containersapi.NewContainersClient(conn), nil
|
||||
}
|
||||
|
||||
func getTasksService(context *cli.Context) (execution.TasksClient, error) {
|
||||
conn, err := getGRPCConnection(context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return execution.NewTasksClient(conn), nil
|
||||
}
|
||||
|
||||
func getContentStore(context *cli.Context) (content.Store, error) {
|
||||
@@ -94,13 +103,13 @@ func getTempDir(id string) (string, error) {
|
||||
return tmpDir, nil
|
||||
}
|
||||
|
||||
func waitContainer(events execution.ContainerService_EventsClient, id string, pid uint32) (uint32, error) {
|
||||
func waitContainer(events execution.Tasks_EventsClient, id string, pid uint32) (uint32, error) {
|
||||
for {
|
||||
e, err := events.Recv()
|
||||
if err != nil {
|
||||
return 255, err
|
||||
}
|
||||
if e.Type != container.Event_EXIT {
|
||||
if e.Type != task.Event_EXIT {
|
||||
continue
|
||||
}
|
||||
if e.ID == id && e.Pid == pid {
|
||||
@@ -109,7 +118,7 @@ func waitContainer(events execution.ContainerService_EventsClient, id string, pi
|
||||
}
|
||||
}
|
||||
|
||||
func forwardAllSignals(containers execution.ContainerServiceClient, id string) chan os.Signal {
|
||||
func forwardAllSignals(containers execution.TasksClient, id string) chan os.Signal {
|
||||
sigc := make(chan os.Signal, 128)
|
||||
signal.Notify(sigc)
|
||||
|
||||
@@ -117,8 +126,8 @@ func forwardAllSignals(containers execution.ContainerServiceClient, id string) c
|
||||
for s := range sigc {
|
||||
logrus.Debug("Forwarding signal ", s)
|
||||
killRequest := &execution.KillRequest{
|
||||
ID: id,
|
||||
Signal: uint32(s.(syscall.Signal)),
|
||||
ContainerID: id,
|
||||
Signal: uint32(s.(syscall.Signal)),
|
||||
PidOrAll: &execution.KillRequest_All{
|
||||
All: false,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user