Merge pull request #44365 from vvoland/c8d-contexts
imageservice: Add context to various methods
This commit is contained in:
commit
e7f034fe4e
42 changed files with 343 additions and 299 deletions
|
@ -32,14 +32,14 @@ type copyBackend interface {
|
|||
|
||||
// stateBackend includes functions to implement to provide container state lifecycle functionality.
|
||||
type stateBackend interface {
|
||||
ContainerCreate(config types.ContainerCreateConfig) (container.CreateResponse, error)
|
||||
ContainerCreate(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error)
|
||||
ContainerKill(name string, signal string) error
|
||||
ContainerPause(name string) error
|
||||
ContainerRename(oldName, newName string) error
|
||||
ContainerResize(name string, height, width int) error
|
||||
ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
|
||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
||||
ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
ContainerStart(ctx context.Context, name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
ContainerStop(ctx context.Context, name string, options container.StopOptions) error
|
||||
ContainerUnpause(name string) error
|
||||
ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error)
|
||||
|
@ -54,7 +54,7 @@ type monitorBackend interface {
|
|||
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
|
||||
ContainerTop(name string, psArgs string) (*container.ContainerTopOKBody, error)
|
||||
|
||||
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
||||
Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error)
|
||||
}
|
||||
|
||||
// attachBackend includes function to implement to provide container attaching functionality.
|
||||
|
@ -68,7 +68,7 @@ type systemBackend interface {
|
|||
}
|
||||
|
||||
type commitBackend interface {
|
||||
CreateImageFromContainer(name string, config *backend.CreateImageConfig) (imageID string, err error)
|
||||
CreateImageFromContainer(ctx context.Context, name string, config *backend.CreateImageConfig) (imageID string, err error)
|
||||
}
|
||||
|
||||
// Backend is all the methods that need to be implemented to provide container specific functionality.
|
||||
|
|
|
@ -58,7 +58,7 @@ func (s *containerRouter) postCommit(ctx context.Context, w http.ResponseWriter,
|
|||
Changes: r.Form["changes"],
|
||||
}
|
||||
|
||||
imgID, err := s.backend.CreateImageFromContainer(r.Form.Get("container"), commitCfg)
|
||||
imgID, err := s.backend.CreateImageFromContainer(ctx, r.Form.Get("container"), commitCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response
|
|||
config.Limit = limit
|
||||
}
|
||||
|
||||
containers, err := s.backend.Containers(config)
|
||||
containers, err := s.backend.Containers(ctx, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
|
|||
|
||||
checkpoint := r.Form.Get("checkpoint")
|
||||
checkpointDir := r.Form.Get("checkpoint-dir")
|
||||
if err := s.backend.ContainerStart(vars["name"], hostConfig, checkpoint, checkpointDir); err != nil {
|
||||
if err := s.backend.ContainerStart(ctx, vars["name"], hostConfig, checkpoint, checkpointDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -578,7 +578,7 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
|||
hostConfig.PidsLimit = nil
|
||||
}
|
||||
|
||||
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
||||
ccr, err := s.backend.ContainerCreate(ctx, types.ContainerCreateConfig{
|
||||
Name: name,
|
||||
Config: config,
|
||||
HostConfig: hostConfig,
|
||||
|
|
|
@ -31,7 +31,7 @@ type imageBackend interface {
|
|||
|
||||
type importExportBackend interface {
|
||||
LoadImage(ctx context.Context, inTar io.ReadCloser, outStream io.Writer, quiet bool) error
|
||||
ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
|
||||
ImportImage(ctx context.Context, src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
|
||||
ExportImage(ctx context.Context, names []string, outStream io.Writer) error
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ func (ir *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrit
|
|||
progressErr = ir.backend.PullImage(ctx, img, tag, platform, metaHeaders, authConfig, output)
|
||||
} else { // import
|
||||
src := r.Form.Get("fromSrc")
|
||||
progressErr = ir.backend.ImportImage(src, repo, platform, tag, message, r.Body, output, r.Form["changes"])
|
||||
progressErr = ir.backend.ImportImage(ctx, src, repo, platform, tag, message, r.Body, output, r.Form["changes"])
|
||||
}
|
||||
if progressErr != nil {
|
||||
if !output.Flushed() {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
type Backend interface {
|
||||
Init(req types.InitRequest) (string, error)
|
||||
Join(req types.JoinRequest) error
|
||||
Leave(force bool) error
|
||||
Leave(ctx context.Context, force bool) error
|
||||
Inspect() (types.Swarm, error)
|
||||
Update(uint64, types.Spec, types.UpdateFlags) error
|
||||
GetUnlockKey() (string, error)
|
||||
|
|
|
@ -56,7 +56,7 @@ func (sr *swarmRouter) leaveCluster(ctx context.Context, w http.ResponseWriter,
|
|||
}
|
||||
|
||||
force := httputils.BoolValue(r, "force")
|
||||
return sr.backend.Leave(force)
|
||||
return sr.backend.Leave(ctx, force)
|
||||
}
|
||||
|
||||
func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
|
|
|
@ -60,13 +60,13 @@ type ExecBackend interface {
|
|||
// ContainerAttachRaw attaches to container.
|
||||
ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error
|
||||
// ContainerCreateIgnoreImagesArgsEscaped creates a new Docker container and returns potential warnings
|
||||
ContainerCreateIgnoreImagesArgsEscaped(config types.ContainerCreateConfig) (container.CreateResponse, error)
|
||||
ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error)
|
||||
// ContainerRm removes a container specified by `id`.
|
||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
||||
// ContainerKill stops the container execution abruptly.
|
||||
ContainerKill(containerID string, sig string) error
|
||||
// ContainerStart starts a new container
|
||||
ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
ContainerStart(ctx context.Context, containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
// ContainerWait stops processing until the given container is stopped.
|
||||
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ type Result struct {
|
|||
// ImageCacheBuilder represents a generator for stateful image cache.
|
||||
type ImageCacheBuilder interface {
|
||||
// MakeImageCache creates a stateful image cache.
|
||||
MakeImageCache(cacheFrom []string) ImageCache
|
||||
MakeImageCache(ctx context.Context, cacheFrom []string) (ImageCache, error)
|
||||
}
|
||||
|
||||
// ImageCache abstracts an image cache.
|
||||
|
|
|
@ -95,7 +95,7 @@ func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b.build(source, dockerfile)
|
||||
return b.build(ctx, source, dockerfile)
|
||||
}
|
||||
|
||||
// builderOptions are the dependencies required by the builder
|
||||
|
@ -117,8 +117,7 @@ type Builder struct {
|
|||
Aux *streamformatter.AuxFormatter
|
||||
Output io.Writer
|
||||
|
||||
docker builder.Backend
|
||||
clientCtx context.Context
|
||||
docker builder.Backend
|
||||
|
||||
idMapping idtools.IdentityMapping
|
||||
disableCommit bool
|
||||
|
@ -130,14 +129,18 @@ type Builder struct {
|
|||
}
|
||||
|
||||
// newBuilder creates a new Dockerfile builder from an optional dockerfile and a Options.
|
||||
func newBuilder(clientCtx context.Context, options builderOptions) (*Builder, error) {
|
||||
func newBuilder(ctx context.Context, options builderOptions) (*Builder, error) {
|
||||
config := options.Options
|
||||
if config == nil {
|
||||
config = new(types.ImageBuildOptions)
|
||||
}
|
||||
|
||||
imageProber, err := newImageProber(ctx, options.Backend, config.CacheFrom, config.NoCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b := &Builder{
|
||||
clientCtx: clientCtx,
|
||||
options: config,
|
||||
Stdout: options.ProgressWriter.StdoutFormatter,
|
||||
Stderr: options.ProgressWriter.StderrFormatter,
|
||||
|
@ -145,9 +148,9 @@ func newBuilder(clientCtx context.Context, options builderOptions) (*Builder, er
|
|||
Output: options.ProgressWriter.Output,
|
||||
docker: options.Backend,
|
||||
idMapping: options.IDMapping,
|
||||
imageSources: newImageSources(clientCtx, options),
|
||||
imageSources: newImageSources(options),
|
||||
pathCache: options.PathCache,
|
||||
imageProber: newImageProber(options.Backend, config.CacheFrom, config.NoCache),
|
||||
imageProber: imageProber,
|
||||
containerManager: newContainerManager(options.Backend),
|
||||
}
|
||||
|
||||
|
@ -181,7 +184,7 @@ func buildLabelOptions(labels map[string]string, stages []instructions.Stage) {
|
|||
|
||||
// Build runs the Dockerfile builder by parsing the Dockerfile and executing
|
||||
// the instructions from the file.
|
||||
func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*builder.Result, error) {
|
||||
func (b *Builder) build(ctx context.Context, source builder.Source, dockerfile *parser.Result) (*builder.Result, error) {
|
||||
defer b.imageSources.Unmount()
|
||||
|
||||
stages, metaArgs, err := instructions.Parse(dockerfile.AST)
|
||||
|
@ -205,7 +208,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil
|
|||
buildLabelOptions(b.options.Labels, stages)
|
||||
|
||||
dockerfile.PrintWarnings(b.Stderr)
|
||||
dispatchState, err := b.dispatchDockerfileWithCancellation(stages, metaArgs, dockerfile.EscapeToken, source)
|
||||
dispatchState, err := b.dispatchDockerfileWithCancellation(ctx, stages, metaArgs, dockerfile.EscapeToken, source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -244,7 +247,7 @@ func printCommand(out io.Writer, currentCommandIndex int, totalCommands int, cmd
|
|||
return currentCommandIndex + 1
|
||||
}
|
||||
|
||||
func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.Stage, metaArgs []instructions.ArgCommand, escapeToken rune, source builder.Source) (*dispatchState, error) {
|
||||
func (b *Builder) dispatchDockerfileWithCancellation(ctx context.Context, parseResult []instructions.Stage, metaArgs []instructions.ArgCommand, escapeToken rune, source builder.Source) (*dispatchState, error) {
|
||||
dispatchRequest := dispatchRequest{}
|
||||
buildArgs := NewBuildArgs(b.options.BuildArgs)
|
||||
totalCommands := len(metaArgs) + len(parseResult)
|
||||
|
@ -272,14 +275,14 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
|
|||
dispatchRequest = newDispatchRequest(b, escapeToken, source, buildArgs, stagesResults)
|
||||
|
||||
currentCommandIndex = printCommand(b.Stdout, currentCommandIndex, totalCommands, stage.SourceCode)
|
||||
if err := initializeStage(dispatchRequest, &stage); err != nil {
|
||||
if err := initializeStage(ctx, dispatchRequest, &stage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchRequest.state.updateRunConfig()
|
||||
fmt.Fprintf(b.Stdout, " ---> %s\n", stringid.TruncateID(dispatchRequest.state.imageID))
|
||||
for _, cmd := range stage.Commands {
|
||||
select {
|
||||
case <-b.clientCtx.Done():
|
||||
case <-ctx.Done():
|
||||
logrus.Debug("Builder: build cancelled!")
|
||||
fmt.Fprint(b.Stdout, "Build cancelled\n")
|
||||
buildsFailed.WithValues(metricsBuildCanceled).Inc()
|
||||
|
@ -290,7 +293,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
|
|||
|
||||
currentCommandIndex = printCommand(b.Stdout, currentCommandIndex, totalCommands, cmd)
|
||||
|
||||
if err := dispatch(dispatchRequest, cmd); err != nil {
|
||||
if err := dispatch(ctx, dispatchRequest, cmd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchRequest.state.updateRunConfig()
|
||||
|
@ -317,7 +320,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
|
|||
// coming from the query parameter of the same name.
|
||||
//
|
||||
// TODO: Remove?
|
||||
func BuildFromConfig(config *container.Config, changes []string, os string) (*container.Config, error) {
|
||||
func BuildFromConfig(ctx context.Context, config *container.Config, changes []string, os string) (*container.Config, error) {
|
||||
if len(changes) == 0 {
|
||||
return config, nil
|
||||
}
|
||||
|
@ -327,7 +330,7 @@ func BuildFromConfig(config *container.Config, changes []string, os string) (*co
|
|||
return nil, errdefs.InvalidParameter(err)
|
||||
}
|
||||
|
||||
b, err := newBuilder(context.Background(), builderOptions{
|
||||
b, err := newBuilder(ctx, builderOptions{
|
||||
Options: &types.ImageBuildOptions{NoCache: true},
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -360,7 +363,7 @@ func BuildFromConfig(config *container.Config, changes []string, os string) (*co
|
|||
dispatchRequest.state.imageID = config.Image
|
||||
dispatchRequest.state.operatingSystem = os
|
||||
for _, cmd := range commands {
|
||||
err := dispatch(dispatchRequest, cmd)
|
||||
err := dispatch(ctx, dispatchRequest, cmd)
|
||||
if err != nil {
|
||||
return nil, errdefs.InvalidParameter(err)
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ func newContainerManager(docker builder.ExecBackend) *containerManager {
|
|||
}
|
||||
|
||||
// Create a container
|
||||
func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig) (container.CreateResponse, error) {
|
||||
container, err := c.backend.ContainerCreateIgnoreImagesArgsEscaped(types.ContainerCreateConfig{
|
||||
func (c *containerManager) Create(ctx context.Context, runConfig *container.Config, hostConfig *container.HostConfig) (container.CreateResponse, error) {
|
||||
container, err := c.backend.ContainerCreateIgnoreImagesArgsEscaped(ctx, types.ContainerCreateConfig{
|
||||
Config: runConfig,
|
||||
HostConfig: hostConfig,
|
||||
})
|
||||
|
@ -69,7 +69,7 @@ func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr i
|
|||
}
|
||||
}()
|
||||
|
||||
if err := c.backend.ContainerStart(cID, nil, "", ""); err != nil {
|
||||
if err := c.backend.ContainerStart(ctx, cID, nil, "", ""); err != nil {
|
||||
close(finished)
|
||||
logCancellationError(cancelErrCh, "error from ContainerStart: "+err.Error())
|
||||
return err
|
||||
|
|
|
@ -9,6 +9,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
|
@ -35,7 +36,7 @@ import (
|
|||
//
|
||||
// Sets the environment variable foo to bar, also makes interpolation
|
||||
// in the dockerfile available from the next statement on via ${foo}.
|
||||
func dispatchEnv(d dispatchRequest, c *instructions.EnvCommand) error {
|
||||
func dispatchEnv(ctx context.Context, d dispatchRequest, c *instructions.EnvCommand) error {
|
||||
runConfig := d.state.runConfig
|
||||
commitMessage := bytes.NewBufferString("ENV")
|
||||
for _, e := range c.Env {
|
||||
|
@ -57,21 +58,21 @@ func dispatchEnv(d dispatchRequest, c *instructions.EnvCommand) error {
|
|||
runConfig.Env = append(runConfig.Env, newVar)
|
||||
}
|
||||
}
|
||||
return d.builder.commit(d.state, commitMessage.String())
|
||||
return d.builder.commit(ctx, d.state, commitMessage.String())
|
||||
}
|
||||
|
||||
// MAINTAINER some text <maybe@an.email.address>
|
||||
//
|
||||
// Sets the maintainer metadata.
|
||||
func dispatchMaintainer(d dispatchRequest, c *instructions.MaintainerCommand) error {
|
||||
func dispatchMaintainer(ctx context.Context, d dispatchRequest, c *instructions.MaintainerCommand) error {
|
||||
d.state.maintainer = c.Maintainer
|
||||
return d.builder.commit(d.state, "MAINTAINER "+c.Maintainer)
|
||||
return d.builder.commit(ctx, d.state, "MAINTAINER "+c.Maintainer)
|
||||
}
|
||||
|
||||
// LABEL some json data describing the image
|
||||
//
|
||||
// Sets the Label variable foo to bar,
|
||||
func dispatchLabel(d dispatchRequest, c *instructions.LabelCommand) error {
|
||||
func dispatchLabel(ctx context.Context, d dispatchRequest, c *instructions.LabelCommand) error {
|
||||
if d.state.runConfig.Labels == nil {
|
||||
d.state.runConfig.Labels = make(map[string]string)
|
||||
}
|
||||
|
@ -80,14 +81,14 @@ func dispatchLabel(d dispatchRequest, c *instructions.LabelCommand) error {
|
|||
d.state.runConfig.Labels[v.Key] = v.Value
|
||||
commitStr += " " + v.String()
|
||||
}
|
||||
return d.builder.commit(d.state, commitStr)
|
||||
return d.builder.commit(ctx, d.state, commitStr)
|
||||
}
|
||||
|
||||
// ADD foo /path
|
||||
//
|
||||
// Add the file 'foo' to '/path'. Tarball and Remote URL (http, https) handling
|
||||
// exist here. If you do not wish to have this automatic handling, use COPY.
|
||||
func dispatchAdd(d dispatchRequest, c *instructions.AddCommand) error {
|
||||
func dispatchAdd(ctx context.Context, d dispatchRequest, c *instructions.AddCommand) error {
|
||||
if c.Chmod != "" {
|
||||
return errors.New("the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
|
||||
}
|
||||
|
@ -102,20 +103,20 @@ func dispatchAdd(d dispatchRequest, c *instructions.AddCommand) error {
|
|||
copyInstruction.chownStr = c.Chown
|
||||
copyInstruction.allowLocalDecompression = true
|
||||
|
||||
return d.builder.performCopy(d, copyInstruction)
|
||||
return d.builder.performCopy(ctx, d, copyInstruction)
|
||||
}
|
||||
|
||||
// COPY foo /path
|
||||
//
|
||||
// Same as 'ADD' but without the tar and remote url handling.
|
||||
func dispatchCopy(d dispatchRequest, c *instructions.CopyCommand) error {
|
||||
func dispatchCopy(ctx context.Context, d dispatchRequest, c *instructions.CopyCommand) error {
|
||||
if c.Chmod != "" {
|
||||
return errors.New("the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
|
||||
}
|
||||
var im *imageMount
|
||||
var err error
|
||||
if c.From != "" {
|
||||
im, err = d.getImageMount(c.From)
|
||||
im, err = d.getImageMount(ctx, c.From)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "invalid from flag value %s", c.From)
|
||||
}
|
||||
|
@ -130,10 +131,10 @@ func dispatchCopy(d dispatchRequest, c *instructions.CopyCommand) error {
|
|||
if c.From != "" && copyInstruction.chownStr == "" {
|
||||
copyInstruction.preserveOwnership = true
|
||||
}
|
||||
return d.builder.performCopy(d, copyInstruction)
|
||||
return d.builder.performCopy(ctx, d, copyInstruction)
|
||||
}
|
||||
|
||||
func (d *dispatchRequest) getImageMount(imageRefOrID string) (*imageMount, error) {
|
||||
func (d *dispatchRequest) getImageMount(ctx context.Context, imageRefOrID string) (*imageMount, error) {
|
||||
if imageRefOrID == "" {
|
||||
// TODO: this could return the source in the default case as well?
|
||||
return nil, nil
|
||||
|
@ -148,12 +149,15 @@ func (d *dispatchRequest) getImageMount(imageRefOrID string) (*imageMount, error
|
|||
imageRefOrID = stage.Image
|
||||
localOnly = true
|
||||
}
|
||||
return d.builder.imageSources.Get(imageRefOrID, localOnly, d.builder.platform)
|
||||
return d.builder.imageSources.Get(ctx, imageRefOrID, localOnly, d.builder.platform)
|
||||
}
|
||||
|
||||
// FROM [--platform=platform] imagename[:tag | @digest] [AS build-stage-name]
|
||||
func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
|
||||
d.builder.imageProber.Reset()
|
||||
func initializeStage(ctx context.Context, d dispatchRequest, cmd *instructions.Stage) error {
|
||||
err := d.builder.imageProber.Reset(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var platform *specs.Platform
|
||||
if v := cmd.Platform; v != "" {
|
||||
|
@ -169,7 +173,7 @@ func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
|
|||
platform = &p
|
||||
}
|
||||
|
||||
image, err := d.getFromImage(d.shlex, cmd.BaseName, platform)
|
||||
image, err := d.getFromImage(ctx, d.shlex, cmd.BaseName, platform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -180,12 +184,12 @@ func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
|
|||
if len(state.runConfig.OnBuild) > 0 {
|
||||
triggers := state.runConfig.OnBuild
|
||||
state.runConfig.OnBuild = nil
|
||||
return dispatchTriggeredOnBuild(d, triggers)
|
||||
return dispatchTriggeredOnBuild(ctx, d, triggers)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func dispatchTriggeredOnBuild(d dispatchRequest, triggers []string) error {
|
||||
func dispatchTriggeredOnBuild(ctx context.Context, d dispatchRequest, triggers []string) error {
|
||||
fmt.Fprintf(d.builder.Stdout, "# Executing %d build trigger", len(triggers))
|
||||
if len(triggers) > 1 {
|
||||
fmt.Fprint(d.builder.Stdout, "s")
|
||||
|
@ -208,7 +212,7 @@ func dispatchTriggeredOnBuild(d dispatchRequest, triggers []string) error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
err = dispatch(d, cmd)
|
||||
err = dispatch(ctx, d, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -229,7 +233,7 @@ func (d *dispatchRequest) getExpandedString(shlex *shell.Lex, str string) (strin
|
|||
return name, nil
|
||||
}
|
||||
|
||||
func (d *dispatchRequest) getImageOrStage(name string, platform *specs.Platform) (builder.Image, error) {
|
||||
func (d *dispatchRequest) getImageOrStage(ctx context.Context, name string, platform *specs.Platform) (builder.Image, error) {
|
||||
var localOnly bool
|
||||
if im, ok := d.stages.getByName(name); ok {
|
||||
name = im.Image
|
||||
|
@ -256,13 +260,14 @@ func (d *dispatchRequest) getImageOrStage(name string, platform *specs.Platform)
|
|||
}
|
||||
return builder.Image(imageImage), nil
|
||||
}
|
||||
imageMount, err := d.builder.imageSources.Get(name, localOnly, platform)
|
||||
imageMount, err := d.builder.imageSources.Get(ctx, name, localOnly, platform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return imageMount.Image(), nil
|
||||
}
|
||||
func (d *dispatchRequest) getFromImage(shlex *shell.Lex, basename string, platform *specs.Platform) (builder.Image, error) {
|
||||
|
||||
func (d *dispatchRequest) getFromImage(ctx context.Context, shlex *shell.Lex, basename string, platform *specs.Platform) (builder.Image, error) {
|
||||
name, err := d.getExpandedString(shlex, basename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -273,18 +278,18 @@ func (d *dispatchRequest) getFromImage(shlex *shell.Lex, basename string, platfo
|
|||
return nil, errors.Errorf("base name (%s) should not be blank", basename)
|
||||
}
|
||||
|
||||
return d.getImageOrStage(name, platform)
|
||||
return d.getImageOrStage(ctx, name, platform)
|
||||
}
|
||||
|
||||
func dispatchOnbuild(d dispatchRequest, c *instructions.OnbuildCommand) error {
|
||||
func dispatchOnbuild(ctx context.Context, d dispatchRequest, c *instructions.OnbuildCommand) error {
|
||||
d.state.runConfig.OnBuild = append(d.state.runConfig.OnBuild, c.Expression)
|
||||
return d.builder.commit(d.state, "ONBUILD "+c.Expression)
|
||||
return d.builder.commit(ctx, d.state, "ONBUILD "+c.Expression)
|
||||
}
|
||||
|
||||
// WORKDIR /tmp
|
||||
//
|
||||
// Set the working directory for future RUN/CMD/etc statements.
|
||||
func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
|
||||
func dispatchWorkdir(ctx context.Context, d dispatchRequest, c *instructions.WorkdirCommand) error {
|
||||
runConfig := d.state.runConfig
|
||||
var err error
|
||||
runConfig.WorkingDir, err = normalizeWorkdir(d.state.operatingSystem, runConfig.WorkingDir, c.Path)
|
||||
|
@ -305,7 +310,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
|
|||
comment := "WORKDIR " + runConfig.WorkingDir
|
||||
runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment, d.state.operatingSystem))
|
||||
|
||||
containerID, err := d.builder.probeAndCreate(d.state, runConfigWithCommentCmd)
|
||||
containerID, err := d.builder.probeAndCreate(ctx, d.state, runConfigWithCommentCmd)
|
||||
if err != nil || containerID == "" {
|
||||
return err
|
||||
}
|
||||
|
@ -326,7 +331,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
|
|||
// RUN echo hi # sh -c echo hi (Linux and LCOW)
|
||||
// RUN echo hi # cmd /S /C echo hi (Windows)
|
||||
// RUN [ "echo", "hi" ] # echo hi
|
||||
func dispatchRun(d dispatchRequest, c *instructions.RunCommand) error {
|
||||
func dispatchRun(ctx context.Context, d dispatchRequest, c *instructions.RunCommand) error {
|
||||
if !system.IsOSSupported(d.state.operatingSystem) {
|
||||
return system.ErrNotSupportedOperatingSystem
|
||||
}
|
||||
|
@ -360,12 +365,12 @@ func dispatchRun(d dispatchRequest, c *instructions.RunCommand) error {
|
|||
withEntrypointOverride(saveCmd, strslice.StrSlice{""}),
|
||||
withoutHealthcheck())
|
||||
|
||||
cID, err := d.builder.create(runConfig)
|
||||
cID, err := d.builder.create(ctx, runConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.builder.containerManager.Run(d.builder.clientCtx, cID, d.builder.Stdout, d.builder.Stderr); err != nil {
|
||||
if err := d.builder.containerManager.Run(ctx, cID, d.builder.Stdout, d.builder.Stderr); err != nil {
|
||||
if err, ok := err.(*statusCodeError); ok {
|
||||
// TODO: change error type, because jsonmessage.JSONError assumes HTTP
|
||||
msg := fmt.Sprintf(
|
||||
|
@ -420,7 +425,7 @@ func prependEnvOnCmd(buildArgs *BuildArgs, buildArgVars []string, cmd strslice.S
|
|||
//
|
||||
// Set the default command to run in the container (which may be empty).
|
||||
// Argument handling is the same as RUN.
|
||||
func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
|
||||
func dispatchCmd(ctx context.Context, d dispatchRequest, c *instructions.CmdCommand) error {
|
||||
runConfig := d.state.runConfig
|
||||
cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
|
||||
|
||||
|
@ -436,7 +441,7 @@ func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
|
|||
runConfig.Cmd = cmd
|
||||
runConfig.ArgsEscaped = argsEscaped
|
||||
|
||||
if err := d.builder.commit(d.state, fmt.Sprintf("CMD %q", cmd)); err != nil {
|
||||
if err := d.builder.commit(ctx, d.state, fmt.Sprintf("CMD %q", cmd)); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(c.ShellDependantCmdLine.CmdLine) != 0 {
|
||||
|
@ -450,7 +455,7 @@ func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
|
|||
//
|
||||
// Set the default healthcheck command to run in the container (which may be empty).
|
||||
// Argument handling is the same as RUN.
|
||||
func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand) error {
|
||||
func dispatchHealthcheck(ctx context.Context, d dispatchRequest, c *instructions.HealthCheckCommand) error {
|
||||
runConfig := d.state.runConfig
|
||||
if runConfig.Healthcheck != nil {
|
||||
oldCmd := runConfig.Healthcheck.Test
|
||||
|
@ -459,7 +464,7 @@ func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand)
|
|||
}
|
||||
}
|
||||
runConfig.Healthcheck = c.Health
|
||||
return d.builder.commit(d.state, fmt.Sprintf("HEALTHCHECK %q", runConfig.Healthcheck))
|
||||
return d.builder.commit(ctx, d.state, fmt.Sprintf("HEALTHCHECK %q", runConfig.Healthcheck))
|
||||
}
|
||||
|
||||
// ENTRYPOINT /usr/sbin/nginx
|
||||
|
@ -469,7 +474,7 @@ func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand)
|
|||
//
|
||||
// Handles command processing similar to CMD and RUN, only req.runConfig.Entrypoint
|
||||
// is initialized at newBuilder time instead of through argument parsing.
|
||||
func dispatchEntrypoint(d dispatchRequest, c *instructions.EntrypointCommand) error {
|
||||
func dispatchEntrypoint(ctx context.Context, d dispatchRequest, c *instructions.EntrypointCommand) error {
|
||||
runConfig := d.state.runConfig
|
||||
cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
|
||||
|
||||
|
@ -491,14 +496,14 @@ func dispatchEntrypoint(d dispatchRequest, c *instructions.EntrypointCommand) er
|
|||
runConfig.Cmd = nil
|
||||
}
|
||||
|
||||
return d.builder.commit(d.state, fmt.Sprintf("ENTRYPOINT %q", runConfig.Entrypoint))
|
||||
return d.builder.commit(ctx, d.state, fmt.Sprintf("ENTRYPOINT %q", runConfig.Entrypoint))
|
||||
}
|
||||
|
||||
// EXPOSE 6667/tcp 7000/tcp
|
||||
//
|
||||
// Expose ports for links and port mappings. This all ends up in
|
||||
// req.runConfig.ExposedPorts for runconfig.
|
||||
func dispatchExpose(d dispatchRequest, c *instructions.ExposeCommand, envs []string) error {
|
||||
func dispatchExpose(ctx context.Context, d dispatchRequest, c *instructions.ExposeCommand, envs []string) error {
|
||||
// custom multi word expansion
|
||||
// expose $FOO with FOO="80 443" is expanded as EXPOSE [80,443]. This is the only command supporting word to words expansion
|
||||
// so the word processing has been de-generalized
|
||||
|
@ -524,22 +529,22 @@ func dispatchExpose(d dispatchRequest, c *instructions.ExposeCommand, envs []str
|
|||
d.state.runConfig.ExposedPorts[p] = struct{}{}
|
||||
}
|
||||
|
||||
return d.builder.commit(d.state, "EXPOSE "+strings.Join(c.Ports, " "))
|
||||
return d.builder.commit(ctx, d.state, "EXPOSE "+strings.Join(c.Ports, " "))
|
||||
}
|
||||
|
||||
// USER foo
|
||||
//
|
||||
// Set the user to 'foo' for future commands and when running the
|
||||
// ENTRYPOINT/CMD at container run time.
|
||||
func dispatchUser(d dispatchRequest, c *instructions.UserCommand) error {
|
||||
func dispatchUser(ctx context.Context, d dispatchRequest, c *instructions.UserCommand) error {
|
||||
d.state.runConfig.User = c.User
|
||||
return d.builder.commit(d.state, fmt.Sprintf("USER %v", c.User))
|
||||
return d.builder.commit(ctx, d.state, fmt.Sprintf("USER %v", c.User))
|
||||
}
|
||||
|
||||
// VOLUME /foo
|
||||
//
|
||||
// Expose the volume /foo for use. Will also accept the JSON array form.
|
||||
func dispatchVolume(d dispatchRequest, c *instructions.VolumeCommand) error {
|
||||
func dispatchVolume(ctx context.Context, d dispatchRequest, c *instructions.VolumeCommand) error {
|
||||
if d.state.runConfig.Volumes == nil {
|
||||
d.state.runConfig.Volumes = map[string]struct{}{}
|
||||
}
|
||||
|
@ -549,19 +554,19 @@ func dispatchVolume(d dispatchRequest, c *instructions.VolumeCommand) error {
|
|||
}
|
||||
d.state.runConfig.Volumes[v] = struct{}{}
|
||||
}
|
||||
return d.builder.commit(d.state, fmt.Sprintf("VOLUME %v", c.Volumes))
|
||||
return d.builder.commit(ctx, d.state, fmt.Sprintf("VOLUME %v", c.Volumes))
|
||||
}
|
||||
|
||||
// STOPSIGNAL signal
|
||||
//
|
||||
// Set the signal that will be used to kill the container.
|
||||
func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) error {
|
||||
func dispatchStopSignal(ctx context.Context, d dispatchRequest, c *instructions.StopSignalCommand) error {
|
||||
_, err := signal.ParseSignal(c.Signal)
|
||||
if err != nil {
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
d.state.runConfig.StopSignal = c.Signal
|
||||
return d.builder.commit(d.state, fmt.Sprintf("STOPSIGNAL %v", c.Signal))
|
||||
return d.builder.commit(ctx, d.state, fmt.Sprintf("STOPSIGNAL %v", c.Signal))
|
||||
}
|
||||
|
||||
// ARG name[=value]
|
||||
|
@ -569,7 +574,7 @@ func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) er
|
|||
// Adds the variable foo to the trusted list of variables that can be passed
|
||||
// to builder using the --build-arg flag for expansion/substitution or passing to 'run'.
|
||||
// Dockerfile author may optionally set a default value of this variable.
|
||||
func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
|
||||
func dispatchArg(ctx context.Context, d dispatchRequest, c *instructions.ArgCommand) error {
|
||||
var commitStr strings.Builder
|
||||
commitStr.WriteString("ARG ")
|
||||
for i, arg := range c.Args {
|
||||
|
@ -584,13 +589,13 @@ func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
|
|||
d.state.buildArgs.AddArg(arg.Key, arg.Value)
|
||||
}
|
||||
|
||||
return d.builder.commit(d.state, commitStr.String())
|
||||
return d.builder.commit(ctx, d.state, commitStr.String())
|
||||
}
|
||||
|
||||
// SHELL powershell -command
|
||||
//
|
||||
// Set the non-default shell to use.
|
||||
func dispatchShell(d dispatchRequest, c *instructions.ShellCommand) error {
|
||||
func dispatchShell(ctx context.Context, d dispatchRequest, c *instructions.ShellCommand) error {
|
||||
d.state.runConfig.Shell = c.Shell
|
||||
return d.builder.commit(d.state, fmt.Sprintf("SHELL %v", d.state.runConfig.Shell))
|
||||
return d.builder.commit(ctx, d.state, fmt.Sprintf("SHELL %v", d.state.runConfig.Shell))
|
||||
}
|
||||
|
|
|
@ -23,28 +23,32 @@ import (
|
|||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func newBuilderWithMockBackend() *Builder {
|
||||
func newBuilderWithMockBackend(t *testing.T) *Builder {
|
||||
t.Helper()
|
||||
mockBackend := &MockBackend{}
|
||||
opts := &types.ImageBuildOptions{}
|
||||
ctx := context.Background()
|
||||
|
||||
imageProber, err := newImageProber(ctx, mockBackend, nil, false)
|
||||
assert.NilError(t, err, "Could not create image prober")
|
||||
|
||||
b := &Builder{
|
||||
options: opts,
|
||||
docker: mockBackend,
|
||||
Stdout: new(bytes.Buffer),
|
||||
clientCtx: ctx,
|
||||
disableCommit: true,
|
||||
imageSources: newImageSources(ctx, builderOptions{
|
||||
imageSources: newImageSources(builderOptions{
|
||||
Options: opts,
|
||||
Backend: mockBackend,
|
||||
}),
|
||||
imageProber: newImageProber(mockBackend, nil, false),
|
||||
imageProber: imageProber,
|
||||
containerManager: newContainerManager(mockBackend),
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestEnv2Variables(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
envCommand := &instructions.EnvCommand{
|
||||
Env: instructions.KeyValuePairs{
|
||||
|
@ -52,7 +56,7 @@ func TestEnv2Variables(t *testing.T) {
|
|||
instructions.KeyValuePair{Key: "var2", Value: "val2"},
|
||||
},
|
||||
}
|
||||
err := dispatch(sb, envCommand)
|
||||
err := dispatch(context.TODO(), sb, envCommand)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := []string{
|
||||
|
@ -63,7 +67,7 @@ func TestEnv2Variables(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
sb.state.runConfig.Env = []string{"var1=old", "var2=fromenv"}
|
||||
envCommand := &instructions.EnvCommand{
|
||||
|
@ -71,7 +75,7 @@ func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
|
|||
instructions.KeyValuePair{Key: "var1", Value: "val1"},
|
||||
},
|
||||
}
|
||||
err := dispatch(sb, envCommand)
|
||||
err := dispatch(context.TODO(), sb, envCommand)
|
||||
assert.NilError(t, err)
|
||||
expected := []string{
|
||||
"var1=val1",
|
||||
|
@ -82,10 +86,10 @@ func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
|
|||
|
||||
func TestMaintainer(t *testing.T) {
|
||||
maintainerEntry := "Some Maintainer <maintainer@example.com>"
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
cmd := &instructions.MaintainerCommand{Maintainer: maintainerEntry}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(maintainerEntry, sb.state.maintainer))
|
||||
}
|
||||
|
@ -94,14 +98,14 @@ func TestLabel(t *testing.T) {
|
|||
labelName := "label"
|
||||
labelValue := "value"
|
||||
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
cmd := &instructions.LabelCommand{
|
||||
Labels: instructions.KeyValuePairs{
|
||||
instructions.KeyValuePair{Key: labelName, Value: labelValue},
|
||||
},
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, is.Contains(sb.state.runConfig.Labels, labelName))
|
||||
|
@ -109,12 +113,12 @@ func TestLabel(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFromScratch(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
cmd := &instructions.Stage{
|
||||
BaseName: "scratch",
|
||||
}
|
||||
err := initializeStage(sb, cmd)
|
||||
err := initializeStage(context.TODO(), sb, cmd)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
assert.Check(t, is.Error(err, "Windows does not support FROM scratch"))
|
||||
|
@ -135,7 +139,7 @@ func TestFromWithArg(t *testing.T) {
|
|||
assert.Check(t, is.Equal("alpine"+tag, name))
|
||||
return &mockImage{id: "expectedthisid"}, nil, nil
|
||||
}
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
b.docker.(*MockBackend).getImageFunc = getImage
|
||||
args := NewBuildArgs(make(map[string]*string))
|
||||
|
||||
|
@ -151,7 +155,7 @@ func TestFromWithArg(t *testing.T) {
|
|||
|
||||
sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
|
||||
assert.NilError(t, err)
|
||||
err = initializeStage(sb, cmd)
|
||||
err = initializeStage(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Equal(expected, sb.state.imageID))
|
||||
|
@ -161,7 +165,7 @@ func TestFromWithArg(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
args := NewBuildArgs(make(map[string]*string))
|
||||
|
||||
metaArg := instructions.ArgCommand{}
|
||||
|
@ -172,7 +176,7 @@ func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
|
|||
|
||||
sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
|
||||
assert.NilError(t, err)
|
||||
err = initializeStage(sb, cmd)
|
||||
err = initializeStage(context.TODO(), sb, cmd)
|
||||
assert.Error(t, err, "base name (${THETAG}) should not be blank")
|
||||
}
|
||||
|
||||
|
@ -183,7 +187,7 @@ func TestFromWithUndefinedArg(t *testing.T) {
|
|||
assert.Check(t, is.Equal("alpine", name))
|
||||
return &mockImage{id: "expectedthisid"}, nil, nil
|
||||
}
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
b.docker.(*MockBackend).getImageFunc = getImage
|
||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
|
||||
|
@ -192,41 +196,41 @@ func TestFromWithUndefinedArg(t *testing.T) {
|
|||
cmd := &instructions.Stage{
|
||||
BaseName: "alpine${THETAG}",
|
||||
}
|
||||
err := initializeStage(sb, cmd)
|
||||
err := initializeStage(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(expected, sb.state.imageID))
|
||||
}
|
||||
|
||||
func TestFromMultiStageWithNamedStage(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
firstFrom := &instructions.Stage{BaseName: "someimg", Name: "base"}
|
||||
secondFrom := &instructions.Stage{BaseName: "base"}
|
||||
previousResults := newStagesBuildResults()
|
||||
firstSB := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), previousResults)
|
||||
secondSB := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), previousResults)
|
||||
err := initializeStage(firstSB, firstFrom)
|
||||
err := initializeStage(context.TODO(), firstSB, firstFrom)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, firstSB.state.hasFromImage())
|
||||
previousResults.indexed["base"] = firstSB.state.runConfig
|
||||
previousResults.flat = append(previousResults.flat, firstSB.state.runConfig)
|
||||
err = initializeStage(secondSB, secondFrom)
|
||||
err = initializeStage(context.TODO(), secondSB, secondFrom)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, secondSB.state.hasFromImage())
|
||||
}
|
||||
|
||||
func TestOnbuild(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
cmd := &instructions.OnbuildCommand{
|
||||
Expression: "ADD . /app/src",
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal("ADD . /app/src", sb.state.runConfig.OnBuild[0]))
|
||||
}
|
||||
|
||||
func TestWorkdir(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
sb.state.baseImage = &mockImage{}
|
||||
workingDir := "/app"
|
||||
|
@ -237,13 +241,13 @@ func TestWorkdir(t *testing.T) {
|
|||
Path: workingDir,
|
||||
}
|
||||
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(workingDir, sb.state.runConfig.WorkingDir))
|
||||
}
|
||||
|
||||
func TestCmd(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
sb.state.baseImage = &mockImage{}
|
||||
command := "./executable"
|
||||
|
@ -254,7 +258,7 @@ func TestCmd(t *testing.T) {
|
|||
PrependShell: true,
|
||||
},
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
var expectedCommand strslice.StrSlice
|
||||
|
@ -269,14 +273,14 @@ func TestCmd(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHealthcheckNone(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
cmd := &instructions.HealthCheckCommand{
|
||||
Health: &container.HealthConfig{
|
||||
Test: []string{"NONE"},
|
||||
},
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
||||
|
@ -284,7 +288,7 @@ func TestHealthcheckNone(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestHealthcheckCmd(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
|
||||
cmd := &instructions.HealthCheckCommand{
|
||||
|
@ -292,7 +296,7 @@ func TestHealthcheckCmd(t *testing.T) {
|
|||
Test: expectedTest,
|
||||
},
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
||||
|
@ -300,7 +304,7 @@ func TestHealthcheckCmd(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEntrypoint(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
sb.state.baseImage = &mockImage{}
|
||||
entrypointCmd := "/usr/sbin/nginx"
|
||||
|
@ -311,7 +315,7 @@ func TestEntrypoint(t *testing.T) {
|
|||
PrependShell: true,
|
||||
},
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, sb.state.runConfig.Entrypoint != nil)
|
||||
|
||||
|
@ -325,14 +329,14 @@ func TestEntrypoint(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestExpose(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
|
||||
exposedPort := "80"
|
||||
cmd := &instructions.ExposeCommand{
|
||||
Ports: []string{exposedPort},
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Assert(t, sb.state.runConfig.ExposedPorts != nil)
|
||||
|
@ -344,19 +348,19 @@ func TestExpose(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUser(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
|
||||
cmd := &instructions.UserCommand{
|
||||
User: "test",
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal("test", sb.state.runConfig.User))
|
||||
}
|
||||
|
||||
func TestVolume(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
|
||||
exposedVolume := "/foo"
|
||||
|
@ -364,7 +368,7 @@ func TestVolume(t *testing.T) {
|
|||
cmd := &instructions.VolumeCommand{
|
||||
Volumes: []string{exposedVolume},
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, sb.state.runConfig.Volumes != nil)
|
||||
assert.Check(t, is.Len(sb.state.runConfig.Volumes, 1))
|
||||
|
@ -376,7 +380,7 @@ func TestStopSignal(t *testing.T) {
|
|||
t.Skip("Windows does not support stopsignal")
|
||||
return
|
||||
}
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
sb.state.baseImage = &mockImage{}
|
||||
signal := "SIGKILL"
|
||||
|
@ -384,19 +388,19 @@ func TestStopSignal(t *testing.T) {
|
|||
cmd := &instructions.StopSignalCommand{
|
||||
Signal: signal,
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(signal, sb.state.runConfig.StopSignal))
|
||||
}
|
||||
|
||||
func TestArg(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
|
||||
argName := "foo"
|
||||
argVal := "bar"
|
||||
cmd := &instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{Key: argName, Value: &argVal}}}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := map[string]string{argName: argVal}
|
||||
|
@ -404,13 +408,13 @@ func TestArg(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestShell(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
|
||||
shellCmd := "powershell"
|
||||
cmd := &instructions.ShellCommand{Shell: strslice.StrSlice{shellCmd}}
|
||||
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedShell := strslice.StrSlice([]string{shellCmd})
|
||||
|
@ -430,7 +434,7 @@ func TestPrependEnvOnCmd(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRunWithBuildArgs(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
args := NewBuildArgs(make(map[string]*string))
|
||||
args.argsFromOptions["HTTP_PROXY"] = strPtr("FOO")
|
||||
b.disableCommit = false
|
||||
|
@ -462,7 +466,11 @@ func TestRunWithBuildArgs(t *testing.T) {
|
|||
mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
|
||||
return imageCache
|
||||
}
|
||||
b.imageProber = newImageProber(mockBackend, nil, false)
|
||||
|
||||
imageProber, err := newImageProber(context.TODO(), mockBackend, nil, false)
|
||||
assert.NilError(t, err, "Could not create image prober")
|
||||
b.imageProber = imageProber
|
||||
|
||||
mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ROLayer, error) {
|
||||
return &mockImage{
|
||||
id: "abcdef",
|
||||
|
@ -484,7 +492,7 @@ func TestRunWithBuildArgs(t *testing.T) {
|
|||
return "", nil
|
||||
}
|
||||
from := &instructions.Stage{BaseName: "abcdef"}
|
||||
err := initializeStage(sb, from)
|
||||
err = initializeStage(context.TODO(), sb, from)
|
||||
assert.NilError(t, err)
|
||||
sb.state.buildArgs.AddArg("one", strPtr("two"))
|
||||
|
||||
|
@ -504,14 +512,14 @@ func TestRunWithBuildArgs(t *testing.T) {
|
|||
runinst.CmdLine = strslice.StrSlice{"echo foo"}
|
||||
runinst.PrependShell = true
|
||||
|
||||
assert.NilError(t, dispatch(sb, runinst))
|
||||
assert.NilError(t, dispatch(context.TODO(), sb, runinst))
|
||||
|
||||
// Check that runConfig.Cmd has not been modified by run
|
||||
assert.Check(t, is.DeepEqual(origCmd, sb.state.runConfig.Cmd))
|
||||
}
|
||||
|
||||
func TestRunIgnoresHealthcheck(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
args := NewBuildArgs(make(map[string]*string))
|
||||
sb := newDispatchRequest(b, '`', nil, args, newStagesBuildResults())
|
||||
b.disableCommit = false
|
||||
|
@ -528,7 +536,10 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
|||
mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
|
||||
return imageCache
|
||||
}
|
||||
b.imageProber = newImageProber(mockBackend, nil, false)
|
||||
imageProber, err := newImageProber(context.TODO(), mockBackend, nil, false)
|
||||
assert.NilError(t, err, "Could not create image prober")
|
||||
|
||||
b.imageProber = imageProber
|
||||
mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ROLayer, error) {
|
||||
return &mockImage{
|
||||
id: "abcdef",
|
||||
|
@ -542,7 +553,7 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
|||
return "", nil
|
||||
}
|
||||
from := &instructions.Stage{BaseName: "abcdef"}
|
||||
err := initializeStage(sb, from)
|
||||
err = initializeStage(context.TODO(), sb, from)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
|
||||
|
@ -559,7 +570,7 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
cmd := healthint.(*instructions.HealthCheckCommand)
|
||||
|
||||
assert.NilError(t, dispatch(sb, cmd))
|
||||
assert.NilError(t, dispatch(context.TODO(), sb, cmd))
|
||||
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
||||
|
||||
mockBackend.containerCreateFunc = func(config types.ContainerCreateConfig) (container.CreateResponse, error) {
|
||||
|
@ -574,12 +585,12 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
|||
run := runint.(*instructions.RunCommand)
|
||||
run.PrependShell = true
|
||||
|
||||
assert.NilError(t, dispatch(sb, run))
|
||||
assert.NilError(t, dispatch(context.TODO(), sb, run))
|
||||
assert.Check(t, is.DeepEqual(expectedTest, sb.state.runConfig.Healthcheck.Test))
|
||||
}
|
||||
|
||||
func TestDispatchUnsupportedOptions(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
sb.state.baseImage = &mockImage{}
|
||||
sb.state.operatingSystem = runtime.GOOS
|
||||
|
@ -592,7 +603,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
|
|||
},
|
||||
Chmod: "0655",
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.Error(t, err, "the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
|
||||
})
|
||||
|
||||
|
@ -604,7 +615,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
|
|||
},
|
||||
Chmod: "0655",
|
||||
}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.Error(t, err, "the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
|
||||
})
|
||||
|
||||
|
@ -618,7 +629,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
|
|||
// one or more of these flags will be supported in future
|
||||
for _, f := range []string{"mount", "network", "security", "any-flag"} {
|
||||
cmd.FlagsUsed = []string{f}
|
||||
err := dispatch(sb, cmd)
|
||||
err := dispatch(context.TODO(), sb, cmd)
|
||||
assert.Error(t, err, fmt.Sprintf("the --%s option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled", f))
|
||||
}
|
||||
})
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -34,7 +35,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
|
||||
func dispatch(ctx context.Context, d dispatchRequest, cmd instructions.Command) (err error) {
|
||||
if c, ok := cmd.(instructions.PlatformSpecific); ok {
|
||||
err := c.CheckPlatform(d.state.operatingSystem)
|
||||
if err != nil {
|
||||
|
@ -65,39 +66,39 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
|
|||
}()
|
||||
switch c := cmd.(type) {
|
||||
case *instructions.EnvCommand:
|
||||
return dispatchEnv(d, c)
|
||||
return dispatchEnv(ctx, d, c)
|
||||
case *instructions.MaintainerCommand:
|
||||
return dispatchMaintainer(d, c)
|
||||
return dispatchMaintainer(ctx, d, c)
|
||||
case *instructions.LabelCommand:
|
||||
return dispatchLabel(d, c)
|
||||
return dispatchLabel(ctx, d, c)
|
||||
case *instructions.AddCommand:
|
||||
return dispatchAdd(d, c)
|
||||
return dispatchAdd(ctx, d, c)
|
||||
case *instructions.CopyCommand:
|
||||
return dispatchCopy(d, c)
|
||||
return dispatchCopy(ctx, d, c)
|
||||
case *instructions.OnbuildCommand:
|
||||
return dispatchOnbuild(d, c)
|
||||
return dispatchOnbuild(ctx, d, c)
|
||||
case *instructions.WorkdirCommand:
|
||||
return dispatchWorkdir(d, c)
|
||||
return dispatchWorkdir(ctx, d, c)
|
||||
case *instructions.RunCommand:
|
||||
return dispatchRun(d, c)
|
||||
return dispatchRun(ctx, d, c)
|
||||
case *instructions.CmdCommand:
|
||||
return dispatchCmd(d, c)
|
||||
return dispatchCmd(ctx, d, c)
|
||||
case *instructions.HealthCheckCommand:
|
||||
return dispatchHealthcheck(d, c)
|
||||
return dispatchHealthcheck(ctx, d, c)
|
||||
case *instructions.EntrypointCommand:
|
||||
return dispatchEntrypoint(d, c)
|
||||
return dispatchEntrypoint(ctx, d, c)
|
||||
case *instructions.ExposeCommand:
|
||||
return dispatchExpose(d, c, envs)
|
||||
return dispatchExpose(ctx, d, c, envs)
|
||||
case *instructions.UserCommand:
|
||||
return dispatchUser(d, c)
|
||||
return dispatchUser(ctx, d, c)
|
||||
case *instructions.VolumeCommand:
|
||||
return dispatchVolume(d, c)
|
||||
return dispatchVolume(ctx, d, c)
|
||||
case *instructions.StopSignalCommand:
|
||||
return dispatchStopSignal(d, c)
|
||||
return dispatchStopSignal(ctx, d, c)
|
||||
case *instructions.ArgCommand:
|
||||
return dispatchArg(d, c)
|
||||
return dispatchArg(ctx, d, c)
|
||||
case *instructions.ShellCommand:
|
||||
return dispatchShell(d, c)
|
||||
return dispatchShell(ctx, d, c)
|
||||
}
|
||||
return errors.Errorf("unsupported command type: %v", reflect.TypeOf(cmd))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
@ -127,9 +128,9 @@ func TestDispatch(t *testing.T) {
|
|||
}
|
||||
}()
|
||||
|
||||
b := newBuilderWithMockBackend()
|
||||
b := newBuilderWithMockBackend(t)
|
||||
sb := newDispatchRequest(b, '`', buildContext, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||
err = dispatch(sb, tc.cmd)
|
||||
err = dispatch(context.TODO(), sb, tc.cmd)
|
||||
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type getAndMountFunc func(string, bool, *specs.Platform) (builder.Image, builder.ROLayer, error)
|
||||
type getAndMountFunc func(context.Context, string, bool, *specs.Platform) (builder.Image, builder.ROLayer, error)
|
||||
|
||||
// imageSources mounts images and provides a cache for mounted images. It tracks
|
||||
// all images so they can be unmounted at the end of the build.
|
||||
|
@ -23,8 +23,8 @@ type imageSources struct {
|
|||
getImage getAndMountFunc
|
||||
}
|
||||
|
||||
func newImageSources(ctx context.Context, options builderOptions) *imageSources {
|
||||
getAndMount := func(idOrRef string, localOnly bool, platform *specs.Platform) (builder.Image, builder.ROLayer, error) {
|
||||
func newImageSources(options builderOptions) *imageSources {
|
||||
getAndMount := func(ctx context.Context, idOrRef string, localOnly bool, platform *specs.Platform) (builder.Image, builder.ROLayer, error) {
|
||||
pullOption := backend.PullOptionNoPull
|
||||
if !localOnly {
|
||||
if options.Options.PullParent {
|
||||
|
@ -47,12 +47,12 @@ func newImageSources(ctx context.Context, options builderOptions) *imageSources
|
|||
}
|
||||
}
|
||||
|
||||
func (m *imageSources) Get(idOrRef string, localOnly bool, platform *specs.Platform) (*imageMount, error) {
|
||||
func (m *imageSources) Get(ctx context.Context, idOrRef string, localOnly bool, platform *specs.Platform) (*imageMount, error) {
|
||||
if im, ok := m.byImageID[idOrRef]; ok {
|
||||
return im, nil
|
||||
}
|
||||
|
||||
image, layer, err := m.getImage(idOrRef, localOnly, platform)
|
||||
image, layer, err := m.getImage(ctx, idOrRef, localOnly, platform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
@ -16,7 +17,7 @@ func getMockImageSource(getImageImage builder.Image, getImageLayer builder.ROLay
|
|||
return &imageSources{
|
||||
byImageID: make(map[string]*imageMount),
|
||||
mounts: []*imageMount{},
|
||||
getImage: func(name string, localOnly bool, platform *ocispec.Platform) (builder.Image, builder.ROLayer, error) {
|
||||
getImage: func(_ context.Context, name string, localOnly bool, platform *ocispec.Platform) (builder.Image, builder.ROLayer, error) {
|
||||
return getImageImage, getImageLayer, getImageError
|
||||
},
|
||||
}
|
||||
|
@ -100,7 +101,8 @@ func TestAddFromScratchPopulatesPlatformIfNil(t *testing.T) {
|
|||
|
||||
func TestImageSourceGetAddsToMounts(t *testing.T) {
|
||||
is := getMockImageSource(nil, nil, nil)
|
||||
_, err := is.Get("test", false, nil)
|
||||
ctx := context.Background()
|
||||
_, err := is.Get(ctx, "test", false, nil)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(is.mounts), 1)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/builder"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -9,30 +11,42 @@ import (
|
|||
// ImageProber exposes an Image cache to the Builder. It supports resetting a
|
||||
// cache.
|
||||
type ImageProber interface {
|
||||
Reset()
|
||||
Reset(ctx context.Context) error
|
||||
Probe(parentID string, runConfig *container.Config) (string, error)
|
||||
}
|
||||
|
||||
type resetFunc func(context.Context) (builder.ImageCache, error)
|
||||
|
||||
type imageProber struct {
|
||||
cache builder.ImageCache
|
||||
reset func() builder.ImageCache
|
||||
reset resetFunc
|
||||
cacheBusted bool
|
||||
}
|
||||
|
||||
func newImageProber(cacheBuilder builder.ImageCacheBuilder, cacheFrom []string, noCache bool) ImageProber {
|
||||
func newImageProber(ctx context.Context, cacheBuilder builder.ImageCacheBuilder, cacheFrom []string, noCache bool) (ImageProber, error) {
|
||||
if noCache {
|
||||
return &nopProber{}
|
||||
return &nopProber{}, nil
|
||||
}
|
||||
|
||||
reset := func() builder.ImageCache {
|
||||
return cacheBuilder.MakeImageCache(cacheFrom)
|
||||
reset := func(ctx context.Context) (builder.ImageCache, error) {
|
||||
return cacheBuilder.MakeImageCache(ctx, cacheFrom)
|
||||
}
|
||||
return &imageProber{cache: reset(), reset: reset}
|
||||
|
||||
cache, err := reset(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &imageProber{cache: cache, reset: reset}, nil
|
||||
}
|
||||
|
||||
func (c *imageProber) Reset() {
|
||||
c.cache = c.reset()
|
||||
func (c *imageProber) Reset(ctx context.Context) error {
|
||||
newCache, err := c.reset(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.cache = newCache
|
||||
c.cacheBusted = false
|
||||
return nil
|
||||
}
|
||||
|
||||
// Probe checks if cache match can be found for current build instruction.
|
||||
|
@ -56,7 +70,9 @@ func (c *imageProber) Probe(parentID string, runConfig *container.Config) (strin
|
|||
|
||||
type nopProber struct{}
|
||||
|
||||
func (c *nopProber) Reset() {}
|
||||
func (c *nopProber) Reset(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *nopProber) Probe(_ string, _ *container.Config) (string, error) {
|
||||
return "", nil
|
||||
|
|
|
@ -4,6 +4,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
|||
// non-contiguous functionality. Please read the comments.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -27,7 +28,7 @@ func (b *Builder) getArchiver() *archive.Archiver {
|
|||
return chrootarchive.NewArchiver(b.idMapping)
|
||||
}
|
||||
|
||||
func (b *Builder) commit(dispatchState *dispatchState, comment string) error {
|
||||
func (b *Builder) commit(ctx context.Context, dispatchState *dispatchState, comment string) error {
|
||||
if b.disableCommit {
|
||||
return nil
|
||||
}
|
||||
|
@ -36,7 +37,7 @@ func (b *Builder) commit(dispatchState *dispatchState, comment string) error {
|
|||
}
|
||||
|
||||
runConfigWithCommentCmd := copyRunConfig(dispatchState.runConfig, withCmdComment(comment, dispatchState.operatingSystem))
|
||||
id, err := b.probeAndCreate(dispatchState, runConfigWithCommentCmd)
|
||||
id, err := b.probeAndCreate(ctx, dispatchState, runConfigWithCommentCmd)
|
||||
if err != nil || id == "" {
|
||||
return err
|
||||
}
|
||||
|
@ -107,7 +108,7 @@ func (b *Builder) exportImage(state *dispatchState, layer builder.RWLayer, paren
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
|
||||
func (b *Builder) performCopy(ctx context.Context, req dispatchRequest, inst copyInstruction) error {
|
||||
state := req.state
|
||||
srcHash := getSourceHashFromInfos(inst.infos)
|
||||
|
||||
|
@ -126,7 +127,7 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
|
|||
return err
|
||||
}
|
||||
|
||||
imageMount, err := b.imageSources.Get(state.imageID, true, req.builder.platform)
|
||||
imageMount, err := b.imageSources.Get(ctx, state.imageID, true, req.builder.platform)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get destination image %q", state.imageID)
|
||||
}
|
||||
|
@ -147,7 +148,7 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
|
|||
// translated (if necessary because of user namespaces), and replace
|
||||
// the root pair with the chown pair for copy operations
|
||||
if inst.chownStr != "" {
|
||||
identity, err = parseChownFlag(b, state, inst.chownStr, destInfo.root, b.idMapping)
|
||||
identity, err = parseChownFlag(ctx, b, state, inst.chownStr, destInfo.root, b.idMapping)
|
||||
if err != nil {
|
||||
if b.options.Platform != "windows" {
|
||||
return errors.Wrapf(err, "unable to convert uid/gid chown string to host mapping")
|
||||
|
@ -331,18 +332,18 @@ func (b *Builder) probeCache(dispatchState *dispatchState, runConfig *container.
|
|||
|
||||
var defaultLogConfig = container.LogConfig{Type: "none"}
|
||||
|
||||
func (b *Builder) probeAndCreate(dispatchState *dispatchState, runConfig *container.Config) (string, error) {
|
||||
func (b *Builder) probeAndCreate(ctx context.Context, dispatchState *dispatchState, runConfig *container.Config) (string, error) {
|
||||
if hit, err := b.probeCache(dispatchState, runConfig); err != nil || hit {
|
||||
return "", err
|
||||
}
|
||||
return b.create(runConfig)
|
||||
return b.create(ctx, runConfig)
|
||||
}
|
||||
|
||||
func (b *Builder) create(runConfig *container.Config) (string, error) {
|
||||
func (b *Builder) create(ctx context.Context, runConfig *container.Config) (string, error) {
|
||||
logrus.Debugf("[BUILDER] Command to be executed: %v", runConfig.Cmd)
|
||||
|
||||
hostConfig := hostConfigFromOptions(b.options)
|
||||
container, err := b.containerManager.Create(runConfig, hostConfig)
|
||||
container, err := b.containerManager.Create(ctx, runConfig, hostConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
|
||||
func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
|
||||
var userStr, grpStr string
|
||||
parts := strings.Split(chown, ":")
|
||||
if len(parts) > 2 {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -115,7 +116,7 @@ othergrp:x:6666:
|
|||
},
|
||||
} {
|
||||
t.Run(testcase.name, func(t *testing.T) {
|
||||
idPair, err := parseChownFlag(testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
|
||||
idPair, err := parseChownFlag(context.TODO(), testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
|
||||
assert.NilError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
|
||||
assert.Check(t, is.DeepEqual(testcase.expected, idPair), "chown flag mapping failure")
|
||||
})
|
||||
|
@ -156,7 +157,7 @@ othergrp:x:6666:
|
|||
},
|
||||
} {
|
||||
t.Run(testcase.name, func(t *testing.T) {
|
||||
_, err := parseChownFlag(testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
|
||||
_, err := parseChownFlag(context.TODO(), testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
|
||||
assert.Check(t, is.Error(err, testcase.descr), "Expected error string doesn't match")
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -14,15 +15,15 @@ import (
|
|||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
|
||||
func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
|
||||
if builder.options.Platform == "windows" {
|
||||
return getAccountIdentity(builder, chown, ctrRootPath, state)
|
||||
return getAccountIdentity(ctx, builder, chown, ctrRootPath, state)
|
||||
}
|
||||
|
||||
return identityMapping.RootPair(), nil
|
||||
}
|
||||
|
||||
func getAccountIdentity(builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (idtools.Identity, error) {
|
||||
func getAccountIdentity(ctx context.Context, builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (idtools.Identity, error) {
|
||||
// If this is potentially a string SID then attempt to convert it to verify
|
||||
// this, otherwise continue looking for the account.
|
||||
if strings.HasPrefix(accountName, "S-") || strings.HasPrefix(accountName, "s-") {
|
||||
|
@ -51,10 +52,10 @@ func getAccountIdentity(builder *Builder, accountName string, ctrRootPath string
|
|||
|
||||
// All other lookups failed, so therefore determine if the account in
|
||||
// question exists in the container and if so, obtain its SID.
|
||||
return lookupNTAccount(builder, accountName, state)
|
||||
return lookupNTAccount(ctx, builder, accountName, state)
|
||||
}
|
||||
|
||||
func lookupNTAccount(builder *Builder, accountName string, state *dispatchState) (idtools.Identity, error) {
|
||||
func lookupNTAccount(ctx context.Context, builder *Builder, accountName string, state *dispatchState) (idtools.Identity, error) {
|
||||
|
||||
source, _ := filepath.Split(os.Args[0])
|
||||
|
||||
|
@ -81,7 +82,7 @@ func lookupNTAccount(builder *Builder, accountName string, state *dispatchState)
|
|||
},
|
||||
}
|
||||
|
||||
container, err := builder.containerManager.Create(runConfig, hostConfig)
|
||||
container, err := builder.containerManager.Create(ctx, runConfig, hostConfig)
|
||||
if err != nil {
|
||||
return idtools.Identity{}, err
|
||||
}
|
||||
|
@ -89,7 +90,7 @@ func lookupNTAccount(builder *Builder, accountName string, state *dispatchState)
|
|||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
|
||||
if err := builder.containerManager.Run(builder.clientCtx, container.ID, stdout, stderr); err != nil {
|
||||
if err := builder.containerManager.Run(ctx, container.ID, stdout, stderr); err != nil {
|
||||
if err, ok := err.(*statusCodeError); ok {
|
||||
return idtools.Identity{}, &jsonmessage.JSONError{
|
||||
Message: stderr.String(),
|
||||
|
|
|
@ -27,7 +27,7 @@ func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *MockBackend) ContainerCreateIgnoreImagesArgsEscaped(config types.ContainerCreateConfig) (container.CreateResponse, error) {
|
||||
func (m *MockBackend) ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error) {
|
||||
if m.containerCreateFunc != nil {
|
||||
return m.containerCreateFunc(config)
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func (m *MockBackend) ContainerKill(containerID string, sig string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *MockBackend) ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error {
|
||||
func (m *MockBackend) ContainerStart(ctx context.Context, containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -73,11 +73,11 @@ func (m *MockBackend) GetImageAndReleasableLayer(ctx context.Context, refOrID st
|
|||
return &mockImage{id: "theid"}, &mockLayer{}, nil
|
||||
}
|
||||
|
||||
func (m *MockBackend) MakeImageCache(cacheFrom []string) builder.ImageCache {
|
||||
func (m *MockBackend) MakeImageCache(ctx context.Context, cacheFrom []string) (builder.ImageCache, error) {
|
||||
if m.makeImageCacheFunc != nil {
|
||||
return m.makeImageCacheFunc(cacheFrom)
|
||||
return m.makeImageCacheFunc(cacheFrom), nil
|
||||
}
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockBackend) CreateImage(config []byte, parent string) (builder.Image, error) {
|
||||
|
|
|
@ -252,7 +252,7 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
|
|||
|
||||
// notify systemd that we're shutting down
|
||||
notifyStopping()
|
||||
shutdownDaemon(d)
|
||||
shutdownDaemon(ctx, d)
|
||||
|
||||
// Stop notification processing and any background processes
|
||||
cancel()
|
||||
|
@ -359,27 +359,24 @@ func (cli *DaemonCli) stop() {
|
|||
// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
|
||||
// d.Shutdown() is waiting too long to kill container or worst it's
|
||||
// blocked there
|
||||
func shutdownDaemon(d *daemon.Daemon) {
|
||||
shutdownTimeout := d.ShutdownTimeout()
|
||||
ch := make(chan struct{})
|
||||
go func() {
|
||||
d.Shutdown()
|
||||
close(ch)
|
||||
}()
|
||||
if shutdownTimeout < 0 {
|
||||
<-ch
|
||||
logrus.Debug("Clean shutdown succeeded")
|
||||
return
|
||||
func shutdownDaemon(ctx context.Context, d *daemon.Daemon) {
|
||||
var cancel context.CancelFunc
|
||||
if timeout := d.ShutdownTimeout(); timeout >= 0 {
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
|
||||
} else {
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
}
|
||||
|
||||
timeout := time.NewTimer(time.Duration(shutdownTimeout) * time.Second)
|
||||
defer timeout.Stop()
|
||||
go func() {
|
||||
defer cancel()
|
||||
d.Shutdown(ctx)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ch:
|
||||
logrus.Debug("Clean shutdown succeeded")
|
||||
case <-timeout.C:
|
||||
<-ctx.Done()
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
logrus.Error("Force shutdown daemon")
|
||||
} else {
|
||||
logrus.Debug("Clean shutdown succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ type Backend interface {
|
|||
FindNetwork(idName string) (libnetwork.Network, error)
|
||||
SetupIngress(clustertypes.NetworkCreateRequest, string) (<-chan struct{}, error)
|
||||
ReleaseIngress() (<-chan struct{}, error)
|
||||
CreateManagedContainer(config types.ContainerCreateConfig) (container.CreateResponse, error)
|
||||
ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
CreateManagedContainer(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error)
|
||||
ContainerStart(ctx context.Context, name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
ContainerStop(ctx context.Context, name string, config container.StopOptions) error
|
||||
ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
|
||||
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||
|
@ -53,7 +53,7 @@ type Backend interface {
|
|||
SetContainerSecretReferences(name string, refs []*swarm.SecretReference) error
|
||||
SetContainerConfigReferences(name string, refs []*swarm.ConfigReference) error
|
||||
SystemInfo() *types.Info
|
||||
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
||||
Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error)
|
||||
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
||||
DaemonJoinsCluster(provider cluster.Provider)
|
||||
DaemonLeavesCluster()
|
||||
|
|
|
@ -290,7 +290,7 @@ func (c *containerAdapter) waitForDetach(ctx context.Context) error {
|
|||
func (c *containerAdapter) create(ctx context.Context) error {
|
||||
var cr containertypes.CreateResponse
|
||||
var err error
|
||||
if cr, err = c.backend.CreateManagedContainer(types.ContainerCreateConfig{
|
||||
if cr, err = c.backend.CreateManagedContainer(ctx, types.ContainerCreateConfig{
|
||||
Name: c.container.name(),
|
||||
Config: c.container.config(),
|
||||
HostConfig: c.container.hostConfig(c.dependencies.Volumes()),
|
||||
|
@ -357,7 +357,7 @@ func (c *containerAdapter) start(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return c.backend.ContainerStart(c.container.name(), nil, "", "")
|
||||
return c.backend.ContainerStart(ctx, c.container.name(), nil, "", "")
|
||||
}
|
||||
|
||||
func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {
|
||||
|
|
|
@ -356,7 +356,7 @@ func (c *Cluster) UnlockSwarm(req types.UnlockRequest) error {
|
|||
}
|
||||
|
||||
// Leave shuts down Cluster and removes current state.
|
||||
func (c *Cluster) Leave(force bool) error {
|
||||
func (c *Cluster) Leave(ctx context.Context, force bool) error {
|
||||
c.controlMutex.Lock()
|
||||
defer c.controlMutex.Unlock()
|
||||
|
||||
|
@ -408,7 +408,7 @@ func (c *Cluster) Leave(force bool) error {
|
|||
c.mu.Unlock()
|
||||
|
||||
if nodeID := state.NodeID(); nodeID != "" {
|
||||
nodeContainers, err := c.listContainerForNode(nodeID)
|
||||
nodeContainers, err := c.listContainerForNode(ctx, nodeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -604,11 +604,11 @@ func initClusterSpec(node *swarmnode.Node, spec types.Spec) error {
|
|||
return ctx.Err()
|
||||
}
|
||||
|
||||
func (c *Cluster) listContainerForNode(nodeID string) ([]string, error) {
|
||||
func (c *Cluster) listContainerForNode(ctx context.Context, nodeID string) ([]string, error) {
|
||||
var ids []string
|
||||
filters := filters.NewArgs()
|
||||
filters.Add("label", fmt.Sprintf("com.docker.swarm.node.id=%s", nodeID))
|
||||
containers, err := c.config.Backend.Containers(&apitypes.ContainerListOptions{
|
||||
containers, err := c.config.Backend.Containers(ctx, &apitypes.ContainerListOptions{
|
||||
Filters: filters,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
@ -116,7 +117,7 @@ func merge(userConf, imageConf *containertypes.Config) error {
|
|||
// CreateImageFromContainer creates a new image from a container. The container
|
||||
// config will be updated by applying the change set to the custom config, then
|
||||
// applying that config over the existing container config.
|
||||
func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateImageConfig) (string, error) {
|
||||
func (daemon *Daemon) CreateImageFromContainer(ctx context.Context, name string, c *backend.CreateImageConfig) (string, error) {
|
||||
start := time.Now()
|
||||
container, err := daemon.GetContainer(name)
|
||||
if err != nil {
|
||||
|
@ -146,7 +147,7 @@ func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateIma
|
|||
if c.Config == nil {
|
||||
c.Config = container.Config
|
||||
}
|
||||
newConfig, err := dockerfile.BuildFromConfig(c.Config, c.Changes, container.OS)
|
||||
newConfig, err := dockerfile.BuildFromConfig(ctx, c.Config, c.Changes, container.OS)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package containerd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/builder"
|
||||
)
|
||||
|
||||
// MakeImageCache creates a stateful image cache.
|
||||
func (i *ImageService) MakeImageCache(cacheFrom []string) builder.ImageCache {
|
||||
func (i *ImageService) MakeImageCache(ctx context.Context, cacheFrom []string) (builder.ImageCache, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package containerd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
|
@ -12,6 +13,6 @@ import (
|
|||
// inConfig (if src is "-"), or from a URI specified in src. Progress output is
|
||||
// written to outStream. Repository and tag names can optionally be given in
|
||||
// the repo and tag arguments, respectively.
|
||||
func (i *ImageService) ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
|
||||
func (i *ImageService) ImportImage(ctx context.Context, src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
|
||||
return errdefs.NotImplemented(errors.New("not implemented"))
|
||||
}
|
||||
|
|
|
@ -33,31 +33,30 @@ type createOpts struct {
|
|||
}
|
||||
|
||||
// CreateManagedContainer creates a container that is managed by a Service
|
||||
func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||
return daemon.containerCreate(createOpts{
|
||||
func (daemon *Daemon) CreateManagedContainer(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||
return daemon.containerCreate(ctx, createOpts{
|
||||
params: params,
|
||||
managed: true,
|
||||
})
|
||||
}
|
||||
|
||||
// ContainerCreate creates a regular container
|
||||
func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||
return daemon.containerCreate(createOpts{
|
||||
func (daemon *Daemon) ContainerCreate(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||
return daemon.containerCreate(ctx, createOpts{
|
||||
params: params,
|
||||
})
|
||||
}
|
||||
|
||||
// ContainerCreateIgnoreImagesArgsEscaped creates a regular container. This is called from the builder RUN case
|
||||
// and ensures that we do not take the images ArgsEscaped
|
||||
func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||
return daemon.containerCreate(createOpts{
|
||||
func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||
return daemon.containerCreate(ctx, createOpts{
|
||||
params: params,
|
||||
ignoreImagesArgsEscaped: true,
|
||||
})
|
||||
}
|
||||
|
||||
func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.CreateResponse, error) {
|
||||
ctx := context.TODO()
|
||||
func (daemon *Daemon) containerCreate(ctx context.Context, opts createOpts) (containertypes.CreateResponse, error) {
|
||||
start := time.Now()
|
||||
if opts.params.Config == nil {
|
||||
return containertypes.CreateResponse{}, errdefs.InvalidParameter(errors.New("Config cannot be empty in order to create a container"))
|
||||
|
@ -100,7 +99,7 @@ func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.CreateRes
|
|||
return containertypes.CreateResponse{Warnings: warnings}, errdefs.InvalidParameter(err)
|
||||
}
|
||||
|
||||
ctr, err := daemon.create(opts)
|
||||
ctr, err := daemon.create(ctx, opts)
|
||||
if err != nil {
|
||||
return containertypes.CreateResponse{Warnings: warnings}, err
|
||||
}
|
||||
|
@ -114,8 +113,7 @@ func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.CreateRes
|
|||
}
|
||||
|
||||
// Create creates a new container from the given configuration with a given name.
|
||||
func (daemon *Daemon) create(opts createOpts) (retC *container.Container, retErr error) {
|
||||
ctx := context.TODO()
|
||||
func (daemon *Daemon) create(ctx context.Context, opts createOpts) (retC *container.Container, retErr error) {
|
||||
var (
|
||||
ctr *container.Container
|
||||
img *image.Image
|
||||
|
|
|
@ -526,7 +526,7 @@ func (daemon *Daemon) restore() error {
|
|||
if err := daemon.prepareMountPoints(c); err != nil {
|
||||
log.WithError(err).Error("failed to prepare mount points for container")
|
||||
}
|
||||
if err := daemon.containerStart(c, "", "", true); err != nil {
|
||||
if err := daemon.containerStart(context.Background(), c, "", "", true); err != nil {
|
||||
log.WithError(err).Error("failed to start container")
|
||||
}
|
||||
close(chNotify)
|
||||
|
@ -617,7 +617,7 @@ func (daemon *Daemon) RestartSwarmContainers() {
|
|||
return
|
||||
}
|
||||
|
||||
if err := daemon.containerStart(c, "", "", true); err != nil {
|
||||
if err := daemon.containerStart(ctx, c, "", "", true); err != nil {
|
||||
logrus.WithField("container", c.ID).WithError(err).Error("failed to start swarm container")
|
||||
}
|
||||
|
||||
|
@ -775,7 +775,8 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
|
|||
// initialization
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := d.Shutdown(); err != nil {
|
||||
// Use a fresh context here. Passed context could be cancelled.
|
||||
if err := d.Shutdown(context.Background()); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -1193,17 +1194,17 @@ func (daemon *Daemon) ShutdownTimeout() int {
|
|||
}
|
||||
|
||||
// Shutdown stops the daemon.
|
||||
func (daemon *Daemon) Shutdown() error {
|
||||
func (daemon *Daemon) Shutdown(ctx context.Context) error {
|
||||
daemon.shutdown = true
|
||||
// Keep mounts and networking running on daemon shutdown if
|
||||
// we are to keep containers running and restore them.
|
||||
|
||||
if daemon.configStore.LiveRestoreEnabled && daemon.containers != nil {
|
||||
// check if there are any running containers, if none we should do some cleanup
|
||||
if ls, err := daemon.Containers(&types.ContainerListOptions{}); len(ls) != 0 || err != nil {
|
||||
if ls, err := daemon.Containers(ctx, &types.ContainerListOptions{}); len(ls) != 0 || err != nil {
|
||||
// metrics plugins still need some cleanup
|
||||
daemon.cleanupMetricsPlugins()
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
func (daemon *Daemon) ContainerDiskUsage(ctx context.Context) ([]*types.Container, error) {
|
||||
ch := daemon.usage.DoChan("ContainerDiskUsage", func() (interface{}, error) {
|
||||
// Retrieve container list
|
||||
containers, err := daemon.Containers(&types.ContainerListOptions{
|
||||
containers, err := daemon.Containers(context.TODO(), &types.ContainerListOptions{
|
||||
Size: true,
|
||||
All: true,
|
||||
})
|
||||
|
|
|
@ -37,7 +37,7 @@ type ImageService interface {
|
|||
CountImages() int
|
||||
ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error)
|
||||
ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error)
|
||||
ImportImage(src string, repository string, platform *v1.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
|
||||
ImportImage(ctx context.Context, src string, repository string, platform *v1.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
|
||||
TagImage(imageName, repository, tag string) (string, error)
|
||||
TagImageWithReference(imageID image.ID, newTag reference.Named) error
|
||||
GetImage(ctx context.Context, refOrID string, options imagetype.GetImageOpts) (*image.Image, error)
|
||||
|
@ -62,7 +62,7 @@ type ImageService interface {
|
|||
|
||||
// Build
|
||||
|
||||
MakeImageCache(sourceRefs []string) builder.ImageCache
|
||||
MakeImageCache(ctx context.Context, cacheFrom []string) (builder.ImageCache, error)
|
||||
CommitBuildStep(c backend.CommitConfig) (image.ID, error)
|
||||
|
||||
// Other
|
||||
|
|
|
@ -6,14 +6,14 @@ import (
|
|||
imagetypes "github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/builder"
|
||||
"github.com/docker/docker/image/cache"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// MakeImageCache creates a stateful image cache.
|
||||
func (i *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
|
||||
ctx := context.TODO()
|
||||
func (i *ImageService) MakeImageCache(ctx context.Context, sourceRefs []string) (builder.ImageCache, error) {
|
||||
if len(sourceRefs) == 0 {
|
||||
return cache.NewLocal(i.imageStore)
|
||||
return cache.NewLocal(i.imageStore), nil
|
||||
}
|
||||
|
||||
cache := cache.New(i.imageStore)
|
||||
|
@ -21,11 +21,14 @@ func (i *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
|
|||
for _, ref := range sourceRefs {
|
||||
img, err := i.GetImage(ctx, ref, imagetypes.GetImageOpts{})
|
||||
if err != nil {
|
||||
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Warnf("Could not look up %s for cache resolution, skipping: %+v", ref, err)
|
||||
continue
|
||||
}
|
||||
cache.Populate(img)
|
||||
}
|
||||
|
||||
return cache
|
||||
return cache, nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package images // import "github.com/docker/docker/daemon/images"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -29,7 +30,7 @@ import (
|
|||
// inConfig (if src is "-"), or from a URI specified in src. Progress output is
|
||||
// written to outStream. Repository and tag names can optionally be given in
|
||||
// the repo and tag arguments, respectively.
|
||||
func (i *ImageService) ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
|
||||
func (i *ImageService) ImportImage(ctx context.Context, src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
|
||||
var (
|
||||
rc io.ReadCloser
|
||||
resp *http.Response
|
||||
|
@ -62,7 +63,7 @@ func (i *ImageService) ImportImage(src string, repository string, platform *spec
|
|||
if !system.IsOSSupported(platform.OS) {
|
||||
return errdefs.InvalidParameter(system.ErrNotSupportedOperatingSystem)
|
||||
}
|
||||
config, err := dockerfile.BuildFromConfig(&container.Config{}, changes, platform.OS)
|
||||
config, err := dockerfile.BuildFromConfig(ctx, &container.Config{}, changes, platform.OS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ type iterationAction int
|
|||
|
||||
// containerReducer represents a reducer for a container.
|
||||
// Returns the object to serialize by the api.
|
||||
type containerReducer func(*container.Snapshot, *listContext) (*types.Container, error)
|
||||
type containerReducer func(context.Context, *container.Snapshot, *listContext) (*types.Container, error)
|
||||
|
||||
const (
|
||||
// includeContainer is the action to include a container in the reducer.
|
||||
|
@ -106,8 +106,8 @@ func (r byCreatedDescending) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
// Containers returns the list of containers to show given the user's filtering.
|
||||
func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*types.Container, error) {
|
||||
return daemon.reduceContainers(config, daemon.refreshImage)
|
||||
func (daemon *Daemon) Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error) {
|
||||
return daemon.reduceContainers(ctx, config, daemon.refreshImage)
|
||||
}
|
||||
|
||||
func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listContext) ([]container.Snapshot, error) {
|
||||
|
@ -177,7 +177,7 @@ func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listCo
|
|||
}
|
||||
|
||||
// reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer.
|
||||
func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
|
||||
func (daemon *Daemon) reduceContainers(ctx context.Context, config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
|
||||
if err := config.Filters.Validate(acceptedPsFilterTags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
|
|||
containers = []*types.Container{}
|
||||
)
|
||||
|
||||
filter, err := daemon.foldFilter(view, config)
|
||||
filter, err := daemon.foldFilter(ctx, view, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
|
|||
}
|
||||
|
||||
for i := range containerList {
|
||||
t, err := daemon.reducePsContainer(&containerList[i], filter, reducer)
|
||||
t, err := daemon.reducePsContainer(ctx, &containerList[i], filter, reducer)
|
||||
if err != nil {
|
||||
if err != errStopIteration {
|
||||
return nil, err
|
||||
|
@ -218,7 +218,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
|
|||
}
|
||||
|
||||
// reducePsContainer is the basic representation for a container as expected by the ps command.
|
||||
func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *listContext, reducer containerReducer) (*types.Container, error) {
|
||||
func (daemon *Daemon) reducePsContainer(ctx context.Context, container *container.Snapshot, filter *listContext, reducer containerReducer) (*types.Container, error) {
|
||||
// filter containers to return
|
||||
switch includeContainerInList(container, filter) {
|
||||
case excludeContainer:
|
||||
|
@ -228,7 +228,7 @@ func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *l
|
|||
}
|
||||
|
||||
// transform internal container struct into api structs
|
||||
newC, err := reducer(container, filter)
|
||||
newC, err := reducer(ctx, container, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -243,8 +243,7 @@ func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *l
|
|||
}
|
||||
|
||||
// foldFilter generates the container filter based on the user's filtering options.
|
||||
func (daemon *Daemon) foldFilter(view *container.View, config *types.ContainerListOptions) (*listContext, error) {
|
||||
ctx := context.TODO()
|
||||
func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, config *types.ContainerListOptions) (*listContext, error) {
|
||||
psFilters := config.Filters
|
||||
|
||||
var filtExited []int
|
||||
|
@ -580,8 +579,7 @@ func includeContainerInList(container *container.Snapshot, filter *listContext)
|
|||
}
|
||||
|
||||
// refreshImage checks if the Image ref still points to the correct ID, and updates the ref to the actual ID when it doesn't
|
||||
func (daemon *Daemon) refreshImage(s *container.Snapshot, filter *listContext) (*types.Container, error) {
|
||||
ctx := context.TODO()
|
||||
func (daemon *Daemon) refreshImage(ctx context.Context, s *container.Snapshot, filter *listContext) (*types.Container, error) {
|
||||
c := s.Container
|
||||
tmpImage := s.Image // keep the original ref if still valid (hasn't changed)
|
||||
if tmpImage != s.ImageID {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -88,7 +89,7 @@ func TestListInvalidFilter(t *testing.T) {
|
|||
|
||||
f := filters.NewArgs(filters.Arg("invalid", "foo"))
|
||||
|
||||
_, err = d.Containers(&types.ContainerListOptions{
|
||||
_, err = d.Containers(context.Background(), &types.ContainerListOptions{
|
||||
Filters: f,
|
||||
})
|
||||
assert.Assert(t, is.Error(err, "invalid filter 'invalid'"))
|
||||
|
@ -109,7 +110,7 @@ func TestNameFilter(t *testing.T) {
|
|||
|
||||
// moby/moby #37453 - ^ regex not working due to prefix slash
|
||||
// not being stripped
|
||||
containerList, err := d.Containers(&types.ContainerListOptions{
|
||||
containerList, err := d.Containers(context.Background(), &types.ContainerListOptions{
|
||||
Filters: filters.NewArgs(filters.Arg("name", "^a")),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
@ -118,7 +119,7 @@ func TestNameFilter(t *testing.T) {
|
|||
assert.Assert(t, containerListContainsName(containerList, two.Name))
|
||||
|
||||
// Same as above but with slash prefix should produce the same result
|
||||
containerListWithPrefix, err := d.Containers(&types.ContainerListOptions{
|
||||
containerListWithPrefix, err := d.Containers(context.Background(), &types.ContainerListOptions{
|
||||
Filters: filters.NewArgs(filters.Arg("name", "^/a")),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
@ -127,7 +128,7 @@ func TestNameFilter(t *testing.T) {
|
|||
assert.Assert(t, containerListContainsName(containerListWithPrefix, two.Name))
|
||||
|
||||
// Same as above but make sure it works for exact names
|
||||
containerList, err = d.Containers(&types.ContainerListOptions{
|
||||
containerList, err = d.Containers(context.Background(), &types.ContainerListOptions{
|
||||
Filters: filters.NewArgs(filters.Arg("name", "b1")),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
@ -135,7 +136,7 @@ func TestNameFilter(t *testing.T) {
|
|||
assert.Assert(t, containerListContainsName(containerList, three.Name))
|
||||
|
||||
// Same as above but with slash prefix should produce the same result
|
||||
containerListWithPrefix, err = d.Containers(&types.ContainerListOptions{
|
||||
containerListWithPrefix, err = d.Containers(context.Background(), &types.ContainerListOptions{
|
||||
Filters: filters.NewArgs(filters.Arg("name", "/b1")),
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
|
|
@ -111,7 +111,7 @@ func (daemon *Daemon) handleContainerExit(c *container.Container, e *libcontaine
|
|||
// But containerStart will use daemon.netController segment.
|
||||
// So to avoid panic at startup process, here must wait util daemon restore done.
|
||||
daemon.waitForStartupDone()
|
||||
if err = daemon.containerStart(c, "", "", false); err != nil {
|
||||
if err = daemon.containerStart(context.Background(), c, "", "", false); err != nil {
|
||||
logrus.Debugf("failed to restart container: %+v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1007,7 +1007,7 @@ func WithUser(c *container.Container) coci.SpecOpts {
|
|||
}
|
||||
}
|
||||
|
||||
func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
|
||||
func (daemon *Daemon) createSpec(ctx context.Context, c *container.Container) (retSpec *specs.Spec, err error) {
|
||||
var (
|
||||
opts []coci.SpecOpts
|
||||
s = oci.DefaultSpec()
|
||||
|
@ -1052,7 +1052,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
|
|||
snapshotKey = c.ID
|
||||
}
|
||||
|
||||
return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
|
||||
return &s, coci.ApplyOpts(ctx, nil, &containers.Container{
|
||||
ID: c.ID,
|
||||
Snapshotter: snapshotter,
|
||||
SnapshotKey: snapshotKey,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -73,7 +74,7 @@ func TestTmpfsDevShmNoDupMount(t *testing.T) {
|
|||
d := setupFakeDaemon(t, c)
|
||||
defer cleanupFakeContainer(c)
|
||||
|
||||
_, err := d.createSpec(c)
|
||||
_, err := d.createSpec(context.TODO(), c)
|
||||
assert.Check(t, err)
|
||||
}
|
||||
|
||||
|
@ -92,7 +93,7 @@ func TestIpcPrivateVsReadonly(t *testing.T) {
|
|||
d := setupFakeDaemon(t, c)
|
||||
defer cleanupFakeContainer(c)
|
||||
|
||||
s, err := d.createSpec(c)
|
||||
s, err := d.createSpec(context.TODO(), c)
|
||||
assert.Check(t, err)
|
||||
|
||||
// Find the /dev/shm mount in ms, check it does not have ro
|
||||
|
@ -122,7 +123,7 @@ func TestSysctlOverride(t *testing.T) {
|
|||
defer cleanupFakeContainer(c)
|
||||
|
||||
// Ensure that the implicit sysctl is set correctly.
|
||||
s, err := d.createSpec(c)
|
||||
s, err := d.createSpec(context.TODO(), c)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, s.Hostname, "foobar")
|
||||
assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.Config.Domainname)
|
||||
|
@ -138,7 +139,7 @@ func TestSysctlOverride(t *testing.T) {
|
|||
assert.Assert(t, c.HostConfig.Sysctls["kernel.domainname"] != c.Config.Domainname)
|
||||
c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
|
||||
|
||||
s, err = d.createSpec(c)
|
||||
s, err = d.createSpec(context.TODO(), c)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, s.Hostname, "foobar")
|
||||
assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.HostConfig.Sysctls["kernel.domainname"])
|
||||
|
@ -146,7 +147,7 @@ func TestSysctlOverride(t *testing.T) {
|
|||
|
||||
// Ensure the ping_group_range is not set on a daemon with user-namespaces enabled
|
||||
d.configStore.RemappedRoot = "dummy:dummy"
|
||||
s, err = d.createSpec(c)
|
||||
s, err = d.createSpec(context.TODO(), c)
|
||||
assert.NilError(t, err)
|
||||
_, ok := s.Linux.Sysctl["net.ipv4.ping_group_range"]
|
||||
assert.Assert(t, !ok)
|
||||
|
@ -154,7 +155,7 @@ func TestSysctlOverride(t *testing.T) {
|
|||
// Ensure the ping_group_range is set on a container in "host" userns mode
|
||||
// on a daemon with user-namespaces enabled
|
||||
c.HostConfig.UsernsMode = "host"
|
||||
s, err = d.createSpec(c)
|
||||
s, err = d.createSpec(context.TODO(), c)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "0 2147483647")
|
||||
}
|
||||
|
@ -174,7 +175,7 @@ func TestSysctlOverrideHost(t *testing.T) {
|
|||
defer cleanupFakeContainer(c)
|
||||
|
||||
// Ensure that the implicit sysctl is not set
|
||||
s, err := d.createSpec(c)
|
||||
s, err := d.createSpec(context.TODO(), c)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "")
|
||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "")
|
||||
|
@ -182,7 +183,7 @@ func TestSysctlOverrideHost(t *testing.T) {
|
|||
// Set an explicit sysctl.
|
||||
c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
|
||||
|
||||
s, err = d.createSpec(c)
|
||||
s, err = d.createSpec(context.TODO(), c)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"])
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ const (
|
|||
credentialSpecFileLocation = "CredentialSpecs"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
||||
ctx := context.TODO()
|
||||
func (daemon *Daemon) createSpec(ctx context.Context, c *container.Container) (*specs.Spec, error) {
|
||||
img, err := daemon.imageService.GetImage(ctx, string(c.ImageID), imagetypes.GetImageOpts{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -61,7 +61,7 @@ func (daemon *Daemon) containerRestart(ctx context.Context, container *container
|
|||
}
|
||||
}
|
||||
|
||||
if err := daemon.containerStart(container, "", "", true); err != nil {
|
||||
if err := daemon.containerStart(ctx, container, "", "", true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
)
|
||||
|
||||
// ContainerStart starts a container.
|
||||
func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error {
|
||||
func (daemon *Daemon) ContainerStart(ctx context.Context, name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error {
|
||||
if checkpoint != "" && !daemon.HasExperimental() {
|
||||
return errdefs.InvalidParameter(errors.New("checkpoint is only supported in experimental mode"))
|
||||
}
|
||||
|
@ -92,14 +92,14 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
|
|||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
}
|
||||
return daemon.containerStart(ctr, checkpoint, checkpointDir, true)
|
||||
return daemon.containerStart(ctx, ctr, checkpoint, checkpointDir, true)
|
||||
}
|
||||
|
||||
// containerStart prepares the container to run by setting up everything the
|
||||
// container needs, such as storage and networking, as well as links
|
||||
// between containers. The container is left waiting for a signal to
|
||||
// begin running.
|
||||
func (daemon *Daemon) containerStart(container *container.Container, checkpoint string, checkpointDir string, resetRestartManager bool) (err error) {
|
||||
func (daemon *Daemon) containerStart(ctx context.Context, container *container.Container, checkpoint string, checkpointDir string, resetRestartManager bool) (err error) {
|
||||
start := time.Now()
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
|
@ -151,7 +151,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
|
|||
return err
|
||||
}
|
||||
|
||||
spec, err := daemon.createSpec(container)
|
||||
spec, err := daemon.createSpec(ctx, container)
|
||||
if err != nil {
|
||||
return errdefs.System(err)
|
||||
}
|
||||
|
@ -177,16 +177,14 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
|
|||
return err
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
ctr, err := libcontainerd.ReplaceContainer(ctx, daemon.containerd, container.ID, spec, shim, createOptions)
|
||||
if err != nil {
|
||||
return translateContainerdStartErr(container.Path, container.SetExitCode, err)
|
||||
}
|
||||
|
||||
// TODO(mlaventure): we need to specify checkpoint options here
|
||||
tsk, err := ctr.Start(ctx, checkpointDir,
|
||||
container.StreamConfig.Stdin() != nil || container.Config.Tty,
|
||||
tsk, err := ctr.Start(context.TODO(), // Passing ctx to ctr.Start caused integration tests to be stuck in the cleanup phase
|
||||
checkpointDir, container.StreamConfig.Stdin() != nil || container.Config.Tty,
|
||||
container.InitializeStdio)
|
||||
if err != nil {
|
||||
if err := ctr.Delete(context.Background()); err != nil {
|
||||
|
|
Loading…
Add table
Reference in a new issue