214
									
								
								client/task_opts.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								client/task_opts.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,214 @@ | ||||
| /* | ||||
|    Copyright The containerd Authors. | ||||
|  | ||||
|    Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|    you may not use this file except in compliance with the License. | ||||
|    You may obtain a copy of the License at | ||||
|  | ||||
|        http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|    Unless required by applicable law or agreed to in writing, software | ||||
|    distributed under the License is distributed on an "AS IS" BASIS, | ||||
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|    See the License for the specific language governing permissions and | ||||
|    limitations under the License. | ||||
| */ | ||||
|  | ||||
| package client | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/containerd/containerd/v2/api/types" | ||||
| 	"github.com/containerd/containerd/v2/errdefs" | ||||
| 	"github.com/containerd/containerd/v2/images" | ||||
| 	"github.com/containerd/containerd/v2/mount" | ||||
| 	"github.com/containerd/containerd/v2/runtime/v2/runc/options" | ||||
| 	"github.com/opencontainers/runtime-spec/specs-go" | ||||
| ) | ||||
|  | ||||
| // NewTaskOpts allows the caller to set options on a new task | ||||
| type NewTaskOpts func(context.Context, *Client, *TaskInfo) error | ||||
|  | ||||
| // WithRootFS allows a task to be created without a snapshot being allocated to its container | ||||
| func WithRootFS(mounts []mount.Mount) NewTaskOpts { | ||||
| 	return func(ctx context.Context, c *Client, ti *TaskInfo) error { | ||||
| 		ti.RootFS = mounts | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithRuntimePath will force task service to use a custom path to the runtime binary | ||||
| // instead of resolving it from runtime name. | ||||
| func WithRuntimePath(absRuntimePath string) NewTaskOpts { | ||||
| 	return func(ctx context.Context, client *Client, info *TaskInfo) error { | ||||
| 		info.RuntimePath = absRuntimePath | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithTaskCheckpoint allows a task to be created with live runtime and memory data from a | ||||
| // previous checkpoint. Additional software such as CRIU may be required to | ||||
| // restore a task from a checkpoint | ||||
| func WithTaskCheckpoint(im Image) NewTaskOpts { | ||||
| 	return func(ctx context.Context, c *Client, info *TaskInfo) error { | ||||
| 		desc := im.Target() | ||||
| 		id := desc.Digest | ||||
| 		index, err := decodeIndex(ctx, c.ContentStore(), desc) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for _, m := range index.Manifests { | ||||
| 			if m.MediaType == images.MediaTypeContainerd1Checkpoint { | ||||
| 				info.Checkpoint = &types.Descriptor{ | ||||
| 					MediaType:   m.MediaType, | ||||
| 					Size:        m.Size, | ||||
| 					Digest:      m.Digest.String(), | ||||
| 					Annotations: m.Annotations, | ||||
| 				} | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		return fmt.Errorf("checkpoint not found in index %s", id) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithCheckpointName sets the image name for the checkpoint | ||||
| func WithCheckpointName(name string) CheckpointTaskOpts { | ||||
| 	return func(r *CheckpointTaskInfo) error { | ||||
| 		r.Name = name | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithCheckpointImagePath sets image path for checkpoint option | ||||
| func WithCheckpointImagePath(path string) CheckpointTaskOpts { | ||||
| 	return func(r *CheckpointTaskInfo) error { | ||||
| 		if r.Options == nil { | ||||
| 			r.Options = &options.CheckpointOptions{} | ||||
| 		} | ||||
| 		opts, ok := r.Options.(*options.CheckpointOptions) | ||||
| 		if !ok { | ||||
| 			return errors.New("invalid runtime v2 checkpoint options format") | ||||
| 		} | ||||
| 		opts.ImagePath = path | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithRestoreImagePath sets image path for create option | ||||
| func WithRestoreImagePath(path string) NewTaskOpts { | ||||
| 	return func(ctx context.Context, c *Client, ti *TaskInfo) error { | ||||
| 		if ti.Options == nil { | ||||
| 			ti.Options = &options.Options{} | ||||
| 		} | ||||
| 		opts, ok := ti.Options.(*options.Options) | ||||
| 		if !ok { | ||||
| 			return errors.New("invalid runtime v2 options format") | ||||
| 		} | ||||
| 		opts.CriuImagePath = path | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithRestoreWorkPath sets criu work path for create option | ||||
| func WithRestoreWorkPath(path string) NewTaskOpts { | ||||
| 	return func(ctx context.Context, c *Client, ti *TaskInfo) error { | ||||
| 		if ti.Options == nil { | ||||
| 			ti.Options = &options.Options{} | ||||
| 		} | ||||
| 		opts, ok := ti.Options.(*options.Options) | ||||
| 		if !ok { | ||||
| 			return errors.New("invalid runtime v2 options format") | ||||
| 		} | ||||
| 		opts.CriuWorkPath = path | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ProcessDeleteOpts allows the caller to set options for the deletion of a task | ||||
| type ProcessDeleteOpts func(context.Context, Process) error | ||||
|  | ||||
| // WithProcessKill will forcefully kill and delete a process | ||||
| func WithProcessKill(ctx context.Context, p Process) error { | ||||
| 	ctx, cancel := context.WithCancel(ctx) | ||||
| 	defer cancel() | ||||
| 	// ignore errors to wait and kill as we are forcefully killing | ||||
| 	// the process and don't care about the exit status | ||||
| 	s, err := p.Wait(ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := p.Kill(ctx, syscall.SIGKILL, WithKillAll); err != nil { | ||||
| 		// Kill might still return an IsNotFound error, even if it actually | ||||
| 		// killed the process. | ||||
| 		if errdefs.IsNotFound(err) { | ||||
| 			select { | ||||
| 			case <-ctx.Done(): | ||||
| 				return ctx.Err() | ||||
| 			case <-s: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		if errdefs.IsFailedPrecondition(err) { | ||||
| 			return nil | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| 	// wait for the process to fully stop before letting the rest of the deletion complete | ||||
| 	<-s | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // KillInfo contains information on how to process a Kill action | ||||
| type KillInfo struct { | ||||
| 	// All kills all processes inside the task | ||||
| 	// only valid on tasks, ignored on processes | ||||
| 	All bool | ||||
| 	// ExecID is the ID of a process to kill | ||||
| 	ExecID string | ||||
| } | ||||
|  | ||||
| // KillOpts allows options to be set for the killing of a process | ||||
| type KillOpts func(context.Context, *KillInfo) error | ||||
|  | ||||
| // WithKillAll kills all processes for a task | ||||
| func WithKillAll(ctx context.Context, i *KillInfo) error { | ||||
| 	i.All = true | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // WithKillExecID specifies the process ID | ||||
| func WithKillExecID(execID string) KillOpts { | ||||
| 	return func(ctx context.Context, i *KillInfo) error { | ||||
| 		i.ExecID = execID | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithResources sets the provided resources for task updates. Resources must be | ||||
| // either a *specs.LinuxResources or a *specs.WindowsResources | ||||
| func WithResources(resources interface{}) UpdateTaskOpts { | ||||
| 	return func(ctx context.Context, client *Client, r *UpdateTaskInfo) error { | ||||
| 		switch resources.(type) { | ||||
| 		case *specs.LinuxResources: | ||||
| 		case *specs.WindowsResources: | ||||
| 		default: | ||||
| 			return errors.New("WithResources requires a *specs.LinuxResources or *specs.WindowsResources") | ||||
| 		} | ||||
|  | ||||
| 		r.Resources = resources | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WithAnnotations sets the provided annotations for task updates. | ||||
| func WithAnnotations(annotations map[string]string) UpdateTaskOpts { | ||||
| 	return func(ctx context.Context, client *Client, r *UpdateTaskInfo) error { | ||||
| 		r.Annotations = annotations | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Derek McGowan
					Derek McGowan