imageservice: Add context to various methods
Co-authored-by: Paweł Gronowski <pawel.gronowski@docker.com> Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
parent
4c07d58592
commit
def549c8f6
|
@ -32,14 +32,14 @@ type copyBackend interface {
|
||||||
|
|
||||||
// stateBackend includes functions to implement to provide container state lifecycle functionality.
|
// stateBackend includes functions to implement to provide container state lifecycle functionality.
|
||||||
type stateBackend interface {
|
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
|
ContainerKill(name string, signal string) error
|
||||||
ContainerPause(name string) error
|
ContainerPause(name string) error
|
||||||
ContainerRename(oldName, newName string) error
|
ContainerRename(oldName, newName string) error
|
||||||
ContainerResize(name string, height, width int) error
|
ContainerResize(name string, height, width int) error
|
||||||
ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
|
ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
|
||||||
ContainerRm(name string, config *types.ContainerRmConfig) 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
|
ContainerStop(ctx context.Context, name string, options container.StopOptions) error
|
||||||
ContainerUnpause(name string) error
|
ContainerUnpause(name string) error
|
||||||
ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, 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
|
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
|
||||||
ContainerTop(name string, psArgs string) (*container.ContainerTopOKBody, 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.
|
// attachBackend includes function to implement to provide container attaching functionality.
|
||||||
|
@ -68,7 +68,7 @@ type systemBackend interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type commitBackend 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.
|
// 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"],
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response
|
||||||
config.Limit = limit
|
config.Limit = limit
|
||||||
}
|
}
|
||||||
|
|
||||||
containers, err := s.backend.Containers(config)
|
containers, err := s.backend.Containers(ctx, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
|
||||||
|
|
||||||
checkpoint := r.Form.Get("checkpoint")
|
checkpoint := r.Form.Get("checkpoint")
|
||||||
checkpointDir := r.Form.Get("checkpoint-dir")
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,7 +578,7 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
|
||||||
hostConfig.PidsLimit = nil
|
hostConfig.PidsLimit = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
|
ccr, err := s.backend.ContainerCreate(ctx, types.ContainerCreateConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
Config: config,
|
Config: config,
|
||||||
HostConfig: hostConfig,
|
HostConfig: hostConfig,
|
||||||
|
|
|
@ -31,7 +31,7 @@ type imageBackend interface {
|
||||||
|
|
||||||
type importExportBackend interface {
|
type importExportBackend interface {
|
||||||
LoadImage(ctx context.Context, inTar io.ReadCloser, outStream io.Writer, quiet bool) error
|
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
|
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)
|
progressErr = ir.backend.PullImage(ctx, img, tag, platform, metaHeaders, authConfig, output)
|
||||||
} else { // import
|
} else { // import
|
||||||
src := r.Form.Get("fromSrc")
|
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 progressErr != nil {
|
||||||
if !output.Flushed() {
|
if !output.Flushed() {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
Init(req types.InitRequest) (string, error)
|
Init(req types.InitRequest) (string, error)
|
||||||
Join(req types.JoinRequest) error
|
Join(req types.JoinRequest) error
|
||||||
Leave(force bool) error
|
Leave(ctx context.Context, force bool) error
|
||||||
Inspect() (types.Swarm, error)
|
Inspect() (types.Swarm, error)
|
||||||
Update(uint64, types.Spec, types.UpdateFlags) error
|
Update(uint64, types.Spec, types.UpdateFlags) error
|
||||||
GetUnlockKey() (string, error)
|
GetUnlockKey() (string, error)
|
||||||
|
|
|
@ -56,7 +56,7 @@ func (sr *swarmRouter) leaveCluster(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
force := httputils.BoolValue(r, "force")
|
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 {
|
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 attaches to container.
|
||||||
ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error
|
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 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 removes a container specified by `id`.
|
||||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
ContainerRm(name string, config *types.ContainerRmConfig) error
|
||||||
// ContainerKill stops the container execution abruptly.
|
// ContainerKill stops the container execution abruptly.
|
||||||
ContainerKill(containerID string, sig string) error
|
ContainerKill(containerID string, sig string) error
|
||||||
// ContainerStart starts a new container
|
// 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 stops processing until the given container is stopped.
|
||||||
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
|
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.
|
// ImageCacheBuilder represents a generator for stateful image cache.
|
||||||
type ImageCacheBuilder interface {
|
type ImageCacheBuilder interface {
|
||||||
// MakeImageCache creates a stateful image cache.
|
// MakeImageCache creates a stateful image cache.
|
||||||
MakeImageCache(cacheFrom []string) ImageCache
|
MakeImageCache(ctx context.Context, cacheFrom []string) (ImageCache, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageCache abstracts an image cache.
|
// ImageCache abstracts an image cache.
|
||||||
|
|
|
@ -95,7 +95,7 @@ func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return b.build(source, dockerfile)
|
return b.build(ctx, source, dockerfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// builderOptions are the dependencies required by the builder
|
// builderOptions are the dependencies required by the builder
|
||||||
|
@ -136,6 +136,11 @@ func newBuilder(clientCtx context.Context, options builderOptions) (*Builder, er
|
||||||
config = new(types.ImageBuildOptions)
|
config = new(types.ImageBuildOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imageProber, err := newImageProber(clientCtx, options.Backend, config.CacheFrom, config.NoCache)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
b := &Builder{
|
b := &Builder{
|
||||||
clientCtx: clientCtx,
|
clientCtx: clientCtx,
|
||||||
options: config,
|
options: config,
|
||||||
|
@ -147,7 +152,7 @@ func newBuilder(clientCtx context.Context, options builderOptions) (*Builder, er
|
||||||
idMapping: options.IDMapping,
|
idMapping: options.IDMapping,
|
||||||
imageSources: newImageSources(clientCtx, options),
|
imageSources: newImageSources(clientCtx, options),
|
||||||
pathCache: options.PathCache,
|
pathCache: options.PathCache,
|
||||||
imageProber: newImageProber(options.Backend, config.CacheFrom, config.NoCache),
|
imageProber: imageProber,
|
||||||
containerManager: newContainerManager(options.Backend),
|
containerManager: newContainerManager(options.Backend),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +186,7 @@ func buildLabelOptions(labels map[string]string, stages []instructions.Stage) {
|
||||||
|
|
||||||
// Build runs the Dockerfile builder by parsing the Dockerfile and executing
|
// Build runs the Dockerfile builder by parsing the Dockerfile and executing
|
||||||
// the instructions from the file.
|
// 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()
|
defer b.imageSources.Unmount()
|
||||||
|
|
||||||
stages, metaArgs, err := instructions.Parse(dockerfile.AST)
|
stages, metaArgs, err := instructions.Parse(dockerfile.AST)
|
||||||
|
@ -205,7 +210,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil
|
||||||
buildLabelOptions(b.options.Labels, stages)
|
buildLabelOptions(b.options.Labels, stages)
|
||||||
|
|
||||||
dockerfile.PrintWarnings(b.Stderr)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -244,7 +249,7 @@ func printCommand(out io.Writer, currentCommandIndex int, totalCommands int, cmd
|
||||||
return currentCommandIndex + 1
|
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{}
|
dispatchRequest := dispatchRequest{}
|
||||||
buildArgs := NewBuildArgs(b.options.BuildArgs)
|
buildArgs := NewBuildArgs(b.options.BuildArgs)
|
||||||
totalCommands := len(metaArgs) + len(parseResult)
|
totalCommands := len(metaArgs) + len(parseResult)
|
||||||
|
@ -272,7 +277,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
|
||||||
dispatchRequest = newDispatchRequest(b, escapeToken, source, buildArgs, stagesResults)
|
dispatchRequest = newDispatchRequest(b, escapeToken, source, buildArgs, stagesResults)
|
||||||
|
|
||||||
currentCommandIndex = printCommand(b.Stdout, currentCommandIndex, totalCommands, stage.SourceCode)
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
dispatchRequest.state.updateRunConfig()
|
dispatchRequest.state.updateRunConfig()
|
||||||
|
@ -290,7 +295,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
|
||||||
|
|
||||||
currentCommandIndex = printCommand(b.Stdout, currentCommandIndex, totalCommands, cmd)
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
dispatchRequest.state.updateRunConfig()
|
dispatchRequest.state.updateRunConfig()
|
||||||
|
@ -317,7 +322,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
|
||||||
// coming from the query parameter of the same name.
|
// coming from the query parameter of the same name.
|
||||||
//
|
//
|
||||||
// TODO: Remove?
|
// 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 {
|
if len(changes) == 0 {
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
@ -327,7 +332,7 @@ func BuildFromConfig(config *container.Config, changes []string, os string) (*co
|
||||||
return nil, errdefs.InvalidParameter(err)
|
return nil, errdefs.InvalidParameter(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := newBuilder(context.Background(), builderOptions{
|
b, err := newBuilder(ctx, builderOptions{
|
||||||
Options: &types.ImageBuildOptions{NoCache: true},
|
Options: &types.ImageBuildOptions{NoCache: true},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -360,7 +365,7 @@ func BuildFromConfig(config *container.Config, changes []string, os string) (*co
|
||||||
dispatchRequest.state.imageID = config.Image
|
dispatchRequest.state.imageID = config.Image
|
||||||
dispatchRequest.state.operatingSystem = os
|
dispatchRequest.state.operatingSystem = os
|
||||||
for _, cmd := range commands {
|
for _, cmd := range commands {
|
||||||
err := dispatch(dispatchRequest, cmd)
|
err := dispatch(ctx, dispatchRequest, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errdefs.InvalidParameter(err)
|
return nil, errdefs.InvalidParameter(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ func newContainerManager(docker builder.ExecBackend) *containerManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a container
|
// Create a container
|
||||||
func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig) (container.CreateResponse, error) {
|
func (c *containerManager) Create(ctx context.Context, runConfig *container.Config, hostConfig *container.HostConfig) (container.CreateResponse, error) {
|
||||||
container, err := c.backend.ContainerCreateIgnoreImagesArgsEscaped(types.ContainerCreateConfig{
|
container, err := c.backend.ContainerCreateIgnoreImagesArgsEscaped(ctx, types.ContainerCreateConfig{
|
||||||
Config: runConfig,
|
Config: runConfig,
|
||||||
HostConfig: hostConfig,
|
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)
|
close(finished)
|
||||||
logCancellationError(cancelErrCh, "error from ContainerStart: "+err.Error())
|
logCancellationError(cancelErrCh, "error from ContainerStart: "+err.Error())
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -9,6 +9,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -35,7 +36,7 @@ import (
|
||||||
//
|
//
|
||||||
// Sets the environment variable foo to bar, also makes interpolation
|
// Sets the environment variable foo to bar, also makes interpolation
|
||||||
// in the dockerfile available from the next statement on via ${foo}.
|
// 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
|
runConfig := d.state.runConfig
|
||||||
commitMessage := bytes.NewBufferString("ENV")
|
commitMessage := bytes.NewBufferString("ENV")
|
||||||
for _, e := range c.Env {
|
for _, e := range c.Env {
|
||||||
|
@ -57,21 +58,21 @@ func dispatchEnv(d dispatchRequest, c *instructions.EnvCommand) error {
|
||||||
runConfig.Env = append(runConfig.Env, newVar)
|
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>
|
// MAINTAINER some text <maybe@an.email.address>
|
||||||
//
|
//
|
||||||
// Sets the maintainer metadata.
|
// 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
|
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
|
// LABEL some json data describing the image
|
||||||
//
|
//
|
||||||
// Sets the Label variable foo to bar,
|
// 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 {
|
if d.state.runConfig.Labels == nil {
|
||||||
d.state.runConfig.Labels = make(map[string]string)
|
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
|
d.state.runConfig.Labels[v.Key] = v.Value
|
||||||
commitStr += " " + v.String()
|
commitStr += " " + v.String()
|
||||||
}
|
}
|
||||||
return d.builder.commit(d.state, commitStr)
|
return d.builder.commit(ctx, d.state, commitStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADD foo /path
|
// ADD foo /path
|
||||||
//
|
//
|
||||||
// Add the file 'foo' to '/path'. Tarball and Remote URL (http, https) handling
|
// 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.
|
// 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 != "" {
|
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")
|
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,13 +103,13 @@ func dispatchAdd(d dispatchRequest, c *instructions.AddCommand) error {
|
||||||
copyInstruction.chownStr = c.Chown
|
copyInstruction.chownStr = c.Chown
|
||||||
copyInstruction.allowLocalDecompression = true
|
copyInstruction.allowLocalDecompression = true
|
||||||
|
|
||||||
return d.builder.performCopy(d, copyInstruction)
|
return d.builder.performCopy(ctx, d, copyInstruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// COPY foo /path
|
// COPY foo /path
|
||||||
//
|
//
|
||||||
// Same as 'ADD' but without the tar and remote url handling.
|
// 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 != "" {
|
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")
|
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")
|
||||||
}
|
}
|
||||||
|
@ -130,7 +131,7 @@ func dispatchCopy(d dispatchRequest, c *instructions.CopyCommand) error {
|
||||||
if c.From != "" && copyInstruction.chownStr == "" {
|
if c.From != "" && copyInstruction.chownStr == "" {
|
||||||
copyInstruction.preserveOwnership = true
|
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(imageRefOrID string) (*imageMount, error) {
|
||||||
|
@ -152,8 +153,11 @@ func (d *dispatchRequest) getImageMount(imageRefOrID string) (*imageMount, error
|
||||||
}
|
}
|
||||||
|
|
||||||
// FROM [--platform=platform] imagename[:tag | @digest] [AS build-stage-name]
|
// FROM [--platform=platform] imagename[:tag | @digest] [AS build-stage-name]
|
||||||
func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
|
func initializeStage(ctx context.Context, d dispatchRequest, cmd *instructions.Stage) error {
|
||||||
d.builder.imageProber.Reset()
|
err := d.builder.imageProber.Reset(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var platform *specs.Platform
|
var platform *specs.Platform
|
||||||
if v := cmd.Platform; v != "" {
|
if v := cmd.Platform; v != "" {
|
||||||
|
@ -180,12 +184,12 @@ func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
|
||||||
if len(state.runConfig.OnBuild) > 0 {
|
if len(state.runConfig.OnBuild) > 0 {
|
||||||
triggers := state.runConfig.OnBuild
|
triggers := state.runConfig.OnBuild
|
||||||
state.runConfig.OnBuild = nil
|
state.runConfig.OnBuild = nil
|
||||||
return dispatchTriggeredOnBuild(d, triggers)
|
return dispatchTriggeredOnBuild(ctx, d, triggers)
|
||||||
}
|
}
|
||||||
return nil
|
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))
|
fmt.Fprintf(d.builder.Stdout, "# Executing %d build trigger", len(triggers))
|
||||||
if len(triggers) > 1 {
|
if len(triggers) > 1 {
|
||||||
fmt.Fprint(d.builder.Stdout, "s")
|
fmt.Fprint(d.builder.Stdout, "s")
|
||||||
|
@ -208,7 +212,7 @@ func dispatchTriggeredOnBuild(d dispatchRequest, triggers []string) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = dispatch(d, cmd)
|
err = dispatch(ctx, d, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -276,15 +280,15 @@ func (d *dispatchRequest) getFromImage(shlex *shell.Lex, basename string, platfo
|
||||||
return d.getImageOrStage(name, platform)
|
return d.getImageOrStage(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)
|
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
|
// WORKDIR /tmp
|
||||||
//
|
//
|
||||||
// Set the working directory for future RUN/CMD/etc statements.
|
// 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
|
runConfig := d.state.runConfig
|
||||||
var err error
|
var err error
|
||||||
runConfig.WorkingDir, err = normalizeWorkdir(d.state.operatingSystem, runConfig.WorkingDir, c.Path)
|
runConfig.WorkingDir, err = normalizeWorkdir(d.state.operatingSystem, runConfig.WorkingDir, c.Path)
|
||||||
|
@ -305,7 +309,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
|
||||||
comment := "WORKDIR " + runConfig.WorkingDir
|
comment := "WORKDIR " + runConfig.WorkingDir
|
||||||
runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment, d.state.operatingSystem))
|
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 == "" {
|
if err != nil || containerID == "" {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -326,7 +330,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
|
||||||
// RUN echo hi # sh -c echo hi (Linux and LCOW)
|
// RUN echo hi # sh -c echo hi (Linux and LCOW)
|
||||||
// RUN echo hi # cmd /S /C echo hi (Windows)
|
// RUN echo hi # cmd /S /C echo hi (Windows)
|
||||||
// RUN [ "echo", "hi" ] # echo hi
|
// 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) {
|
if !system.IsOSSupported(d.state.operatingSystem) {
|
||||||
return system.ErrNotSupportedOperatingSystem
|
return system.ErrNotSupportedOperatingSystem
|
||||||
}
|
}
|
||||||
|
@ -360,7 +364,7 @@ func dispatchRun(d dispatchRequest, c *instructions.RunCommand) error {
|
||||||
withEntrypointOverride(saveCmd, strslice.StrSlice{""}),
|
withEntrypointOverride(saveCmd, strslice.StrSlice{""}),
|
||||||
withoutHealthcheck())
|
withoutHealthcheck())
|
||||||
|
|
||||||
cID, err := d.builder.create(runConfig)
|
cID, err := d.builder.create(ctx, runConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -420,7 +424,7 @@ func prependEnvOnCmd(buildArgs *BuildArgs, buildArgVars []string, cmd strslice.S
|
||||||
//
|
//
|
||||||
// Set the default command to run in the container (which may be empty).
|
// Set the default command to run in the container (which may be empty).
|
||||||
// Argument handling is the same as RUN.
|
// 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
|
runConfig := d.state.runConfig
|
||||||
cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
|
cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
|
||||||
|
|
||||||
|
@ -436,7 +440,7 @@ func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
|
||||||
runConfig.Cmd = cmd
|
runConfig.Cmd = cmd
|
||||||
runConfig.ArgsEscaped = argsEscaped
|
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
|
return err
|
||||||
}
|
}
|
||||||
if len(c.ShellDependantCmdLine.CmdLine) != 0 {
|
if len(c.ShellDependantCmdLine.CmdLine) != 0 {
|
||||||
|
@ -450,7 +454,7 @@ func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
|
||||||
//
|
//
|
||||||
// Set the default healthcheck command to run in the container (which may be empty).
|
// Set the default healthcheck command to run in the container (which may be empty).
|
||||||
// Argument handling is the same as RUN.
|
// 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
|
runConfig := d.state.runConfig
|
||||||
if runConfig.Healthcheck != nil {
|
if runConfig.Healthcheck != nil {
|
||||||
oldCmd := runConfig.Healthcheck.Test
|
oldCmd := runConfig.Healthcheck.Test
|
||||||
|
@ -459,7 +463,7 @@ func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runConfig.Healthcheck = c.Health
|
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
|
// ENTRYPOINT /usr/sbin/nginx
|
||||||
|
@ -469,7 +473,7 @@ func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand)
|
||||||
//
|
//
|
||||||
// Handles command processing similar to CMD and RUN, only req.runConfig.Entrypoint
|
// Handles command processing similar to CMD and RUN, only req.runConfig.Entrypoint
|
||||||
// is initialized at newBuilder time instead of through argument parsing.
|
// 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
|
runConfig := d.state.runConfig
|
||||||
cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
|
cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
|
||||||
|
|
||||||
|
@ -491,14 +495,14 @@ func dispatchEntrypoint(d dispatchRequest, c *instructions.EntrypointCommand) er
|
||||||
runConfig.Cmd = nil
|
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 6667/tcp 7000/tcp
|
||||||
//
|
//
|
||||||
// Expose ports for links and port mappings. This all ends up in
|
// Expose ports for links and port mappings. This all ends up in
|
||||||
// req.runConfig.ExposedPorts for runconfig.
|
// 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
|
// 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
|
// 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
|
// so the word processing has been de-generalized
|
||||||
|
@ -524,22 +528,22 @@ func dispatchExpose(d dispatchRequest, c *instructions.ExposeCommand, envs []str
|
||||||
d.state.runConfig.ExposedPorts[p] = struct{}{}
|
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
|
// USER foo
|
||||||
//
|
//
|
||||||
// Set the user to 'foo' for future commands and when running the
|
// Set the user to 'foo' for future commands and when running the
|
||||||
// ENTRYPOINT/CMD at container run time.
|
// 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
|
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
|
// VOLUME /foo
|
||||||
//
|
//
|
||||||
// Expose the volume /foo for use. Will also accept the JSON array form.
|
// 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 {
|
if d.state.runConfig.Volumes == nil {
|
||||||
d.state.runConfig.Volumes = map[string]struct{}{}
|
d.state.runConfig.Volumes = map[string]struct{}{}
|
||||||
}
|
}
|
||||||
|
@ -549,19 +553,19 @@ func dispatchVolume(d dispatchRequest, c *instructions.VolumeCommand) error {
|
||||||
}
|
}
|
||||||
d.state.runConfig.Volumes[v] = struct{}{}
|
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
|
// STOPSIGNAL signal
|
||||||
//
|
//
|
||||||
// Set the signal that will be used to kill the container.
|
// 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)
|
_, err := signal.ParseSignal(c.Signal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errdefs.InvalidParameter(err)
|
return errdefs.InvalidParameter(err)
|
||||||
}
|
}
|
||||||
d.state.runConfig.StopSignal = c.Signal
|
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]
|
// ARG name[=value]
|
||||||
|
@ -569,7 +573,7 @@ func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) er
|
||||||
// Adds the variable foo to the trusted list of variables that can be passed
|
// 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'.
|
// 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.
|
// 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
|
var commitStr strings.Builder
|
||||||
commitStr.WriteString("ARG ")
|
commitStr.WriteString("ARG ")
|
||||||
for i, arg := range c.Args {
|
for i, arg := range c.Args {
|
||||||
|
@ -584,13 +588,13 @@ func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
|
||||||
d.state.buildArgs.AddArg(arg.Key, arg.Value)
|
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
|
// SHELL powershell -command
|
||||||
//
|
//
|
||||||
// Set the non-default shell to use.
|
// 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
|
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,10 +23,15 @@ import (
|
||||||
is "gotest.tools/v3/assert/cmp"
|
is "gotest.tools/v3/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newBuilderWithMockBackend() *Builder {
|
func newBuilderWithMockBackend(t *testing.T) *Builder {
|
||||||
|
t.Helper()
|
||||||
mockBackend := &MockBackend{}
|
mockBackend := &MockBackend{}
|
||||||
opts := &types.ImageBuildOptions{}
|
opts := &types.ImageBuildOptions{}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
imageProber, err := newImageProber(ctx, mockBackend, nil, false)
|
||||||
|
assert.NilError(t, err, "Could not create image prober")
|
||||||
|
|
||||||
b := &Builder{
|
b := &Builder{
|
||||||
options: opts,
|
options: opts,
|
||||||
docker: mockBackend,
|
docker: mockBackend,
|
||||||
|
@ -37,14 +42,14 @@ func newBuilderWithMockBackend() *Builder {
|
||||||
Options: opts,
|
Options: opts,
|
||||||
Backend: mockBackend,
|
Backend: mockBackend,
|
||||||
}),
|
}),
|
||||||
imageProber: newImageProber(mockBackend, nil, false),
|
imageProber: imageProber,
|
||||||
containerManager: newContainerManager(mockBackend),
|
containerManager: newContainerManager(mockBackend),
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnv2Variables(t *testing.T) {
|
func TestEnv2Variables(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
envCommand := &instructions.EnvCommand{
|
envCommand := &instructions.EnvCommand{
|
||||||
Env: instructions.KeyValuePairs{
|
Env: instructions.KeyValuePairs{
|
||||||
|
@ -52,7 +57,7 @@ func TestEnv2Variables(t *testing.T) {
|
||||||
instructions.KeyValuePair{Key: "var2", Value: "val2"},
|
instructions.KeyValuePair{Key: "var2", Value: "val2"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, envCommand)
|
err := dispatch(context.TODO(), sb, envCommand)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
expected := []string{
|
expected := []string{
|
||||||
|
@ -63,7 +68,7 @@ func TestEnv2Variables(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
|
func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
sb.state.runConfig.Env = []string{"var1=old", "var2=fromenv"}
|
sb.state.runConfig.Env = []string{"var1=old", "var2=fromenv"}
|
||||||
envCommand := &instructions.EnvCommand{
|
envCommand := &instructions.EnvCommand{
|
||||||
|
@ -71,7 +76,7 @@ func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
|
||||||
instructions.KeyValuePair{Key: "var1", Value: "val1"},
|
instructions.KeyValuePair{Key: "var1", Value: "val1"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, envCommand)
|
err := dispatch(context.TODO(), sb, envCommand)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
expected := []string{
|
expected := []string{
|
||||||
"var1=val1",
|
"var1=val1",
|
||||||
|
@ -82,10 +87,10 @@ func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
|
||||||
|
|
||||||
func TestMaintainer(t *testing.T) {
|
func TestMaintainer(t *testing.T) {
|
||||||
maintainerEntry := "Some Maintainer <maintainer@example.com>"
|
maintainerEntry := "Some Maintainer <maintainer@example.com>"
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
cmd := &instructions.MaintainerCommand{Maintainer: maintainerEntry}
|
cmd := &instructions.MaintainerCommand{Maintainer: maintainerEntry}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Check(t, is.Equal(maintainerEntry, sb.state.maintainer))
|
assert.Check(t, is.Equal(maintainerEntry, sb.state.maintainer))
|
||||||
}
|
}
|
||||||
|
@ -94,14 +99,14 @@ func TestLabel(t *testing.T) {
|
||||||
labelName := "label"
|
labelName := "label"
|
||||||
labelValue := "value"
|
labelValue := "value"
|
||||||
|
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
cmd := &instructions.LabelCommand{
|
cmd := &instructions.LabelCommand{
|
||||||
Labels: instructions.KeyValuePairs{
|
Labels: instructions.KeyValuePairs{
|
||||||
instructions.KeyValuePair{Key: labelName, Value: labelValue},
|
instructions.KeyValuePair{Key: labelName, Value: labelValue},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Assert(t, is.Contains(sb.state.runConfig.Labels, labelName))
|
assert.Assert(t, is.Contains(sb.state.runConfig.Labels, labelName))
|
||||||
|
@ -109,12 +114,12 @@ func TestLabel(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromScratch(t *testing.T) {
|
func TestFromScratch(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
cmd := &instructions.Stage{
|
cmd := &instructions.Stage{
|
||||||
BaseName: "scratch",
|
BaseName: "scratch",
|
||||||
}
|
}
|
||||||
err := initializeStage(sb, cmd)
|
err := initializeStage(context.TODO(), sb, cmd)
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
assert.Check(t, is.Error(err, "Windows does not support FROM scratch"))
|
assert.Check(t, is.Error(err, "Windows does not support FROM scratch"))
|
||||||
|
@ -135,7 +140,7 @@ func TestFromWithArg(t *testing.T) {
|
||||||
assert.Check(t, is.Equal("alpine"+tag, name))
|
assert.Check(t, is.Equal("alpine"+tag, name))
|
||||||
return &mockImage{id: "expectedthisid"}, nil, nil
|
return &mockImage{id: "expectedthisid"}, nil, nil
|
||||||
}
|
}
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
b.docker.(*MockBackend).getImageFunc = getImage
|
b.docker.(*MockBackend).getImageFunc = getImage
|
||||||
args := NewBuildArgs(make(map[string]*string))
|
args := NewBuildArgs(make(map[string]*string))
|
||||||
|
|
||||||
|
@ -151,7 +156,7 @@ func TestFromWithArg(t *testing.T) {
|
||||||
|
|
||||||
sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
err = initializeStage(sb, cmd)
|
err = initializeStage(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Check(t, is.Equal(expected, sb.state.imageID))
|
assert.Check(t, is.Equal(expected, sb.state.imageID))
|
||||||
|
@ -161,7 +166,7 @@ func TestFromWithArg(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
|
func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
args := NewBuildArgs(make(map[string]*string))
|
args := NewBuildArgs(make(map[string]*string))
|
||||||
|
|
||||||
metaArg := instructions.ArgCommand{}
|
metaArg := instructions.ArgCommand{}
|
||||||
|
@ -172,7 +177,7 @@ func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
|
||||||
|
|
||||||
sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
|
||||||
assert.NilError(t, err)
|
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")
|
assert.Error(t, err, "base name (${THETAG}) should not be blank")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +188,7 @@ func TestFromWithUndefinedArg(t *testing.T) {
|
||||||
assert.Check(t, is.Equal("alpine", name))
|
assert.Check(t, is.Equal("alpine", name))
|
||||||
return &mockImage{id: "expectedthisid"}, nil, nil
|
return &mockImage{id: "expectedthisid"}, nil, nil
|
||||||
}
|
}
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
b.docker.(*MockBackend).getImageFunc = getImage
|
b.docker.(*MockBackend).getImageFunc = getImage
|
||||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
|
|
||||||
|
@ -192,41 +197,41 @@ func TestFromWithUndefinedArg(t *testing.T) {
|
||||||
cmd := &instructions.Stage{
|
cmd := &instructions.Stage{
|
||||||
BaseName: "alpine${THETAG}",
|
BaseName: "alpine${THETAG}",
|
||||||
}
|
}
|
||||||
err := initializeStage(sb, cmd)
|
err := initializeStage(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Check(t, is.Equal(expected, sb.state.imageID))
|
assert.Check(t, is.Equal(expected, sb.state.imageID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromMultiStageWithNamedStage(t *testing.T) {
|
func TestFromMultiStageWithNamedStage(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
firstFrom := &instructions.Stage{BaseName: "someimg", Name: "base"}
|
firstFrom := &instructions.Stage{BaseName: "someimg", Name: "base"}
|
||||||
secondFrom := &instructions.Stage{BaseName: "base"}
|
secondFrom := &instructions.Stage{BaseName: "base"}
|
||||||
previousResults := newStagesBuildResults()
|
previousResults := newStagesBuildResults()
|
||||||
firstSB := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), previousResults)
|
firstSB := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), previousResults)
|
||||||
secondSB := 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.NilError(t, err)
|
||||||
assert.Check(t, firstSB.state.hasFromImage())
|
assert.Check(t, firstSB.state.hasFromImage())
|
||||||
previousResults.indexed["base"] = firstSB.state.runConfig
|
previousResults.indexed["base"] = firstSB.state.runConfig
|
||||||
previousResults.flat = append(previousResults.flat, 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.NilError(t, err)
|
||||||
assert.Check(t, secondSB.state.hasFromImage())
|
assert.Check(t, secondSB.state.hasFromImage())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOnbuild(t *testing.T) {
|
func TestOnbuild(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
cmd := &instructions.OnbuildCommand{
|
cmd := &instructions.OnbuildCommand{
|
||||||
Expression: "ADD . /app/src",
|
Expression: "ADD . /app/src",
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Check(t, is.Equal("ADD . /app/src", sb.state.runConfig.OnBuild[0]))
|
assert.Check(t, is.Equal("ADD . /app/src", sb.state.runConfig.OnBuild[0]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWorkdir(t *testing.T) {
|
func TestWorkdir(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
sb.state.baseImage = &mockImage{}
|
sb.state.baseImage = &mockImage{}
|
||||||
workingDir := "/app"
|
workingDir := "/app"
|
||||||
|
@ -237,13 +242,13 @@ func TestWorkdir(t *testing.T) {
|
||||||
Path: workingDir,
|
Path: workingDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Check(t, is.Equal(workingDir, sb.state.runConfig.WorkingDir))
|
assert.Check(t, is.Equal(workingDir, sb.state.runConfig.WorkingDir))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCmd(t *testing.T) {
|
func TestCmd(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
sb.state.baseImage = &mockImage{}
|
sb.state.baseImage = &mockImage{}
|
||||||
command := "./executable"
|
command := "./executable"
|
||||||
|
@ -254,7 +259,7 @@ func TestCmd(t *testing.T) {
|
||||||
PrependShell: true,
|
PrependShell: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
var expectedCommand strslice.StrSlice
|
var expectedCommand strslice.StrSlice
|
||||||
|
@ -269,14 +274,14 @@ func TestCmd(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHealthcheckNone(t *testing.T) {
|
func TestHealthcheckNone(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
cmd := &instructions.HealthCheckCommand{
|
cmd := &instructions.HealthCheckCommand{
|
||||||
Health: &container.HealthConfig{
|
Health: &container.HealthConfig{
|
||||||
Test: []string{"NONE"},
|
Test: []string{"NONE"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
||||||
|
@ -284,7 +289,7 @@ func TestHealthcheckNone(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHealthcheckCmd(t *testing.T) {
|
func TestHealthcheckCmd(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
|
expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
|
||||||
cmd := &instructions.HealthCheckCommand{
|
cmd := &instructions.HealthCheckCommand{
|
||||||
|
@ -292,7 +297,7 @@ func TestHealthcheckCmd(t *testing.T) {
|
||||||
Test: expectedTest,
|
Test: expectedTest,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
||||||
|
@ -300,7 +305,7 @@ func TestHealthcheckCmd(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEntrypoint(t *testing.T) {
|
func TestEntrypoint(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
sb.state.baseImage = &mockImage{}
|
sb.state.baseImage = &mockImage{}
|
||||||
entrypointCmd := "/usr/sbin/nginx"
|
entrypointCmd := "/usr/sbin/nginx"
|
||||||
|
@ -311,7 +316,7 @@ func TestEntrypoint(t *testing.T) {
|
||||||
PrependShell: true,
|
PrependShell: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, sb.state.runConfig.Entrypoint != nil)
|
assert.Assert(t, sb.state.runConfig.Entrypoint != nil)
|
||||||
|
|
||||||
|
@ -325,14 +330,14 @@ func TestEntrypoint(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpose(t *testing.T) {
|
func TestExpose(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
|
|
||||||
exposedPort := "80"
|
exposedPort := "80"
|
||||||
cmd := &instructions.ExposeCommand{
|
cmd := &instructions.ExposeCommand{
|
||||||
Ports: []string{exposedPort},
|
Ports: []string{exposedPort},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Assert(t, sb.state.runConfig.ExposedPorts != nil)
|
assert.Assert(t, sb.state.runConfig.ExposedPorts != nil)
|
||||||
|
@ -344,19 +349,19 @@ func TestExpose(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUser(t *testing.T) {
|
func TestUser(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
|
|
||||||
cmd := &instructions.UserCommand{
|
cmd := &instructions.UserCommand{
|
||||||
User: "test",
|
User: "test",
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Check(t, is.Equal("test", sb.state.runConfig.User))
|
assert.Check(t, is.Equal("test", sb.state.runConfig.User))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVolume(t *testing.T) {
|
func TestVolume(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
|
|
||||||
exposedVolume := "/foo"
|
exposedVolume := "/foo"
|
||||||
|
@ -364,7 +369,7 @@ func TestVolume(t *testing.T) {
|
||||||
cmd := &instructions.VolumeCommand{
|
cmd := &instructions.VolumeCommand{
|
||||||
Volumes: []string{exposedVolume},
|
Volumes: []string{exposedVolume},
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, sb.state.runConfig.Volumes != nil)
|
assert.Assert(t, sb.state.runConfig.Volumes != nil)
|
||||||
assert.Check(t, is.Len(sb.state.runConfig.Volumes, 1))
|
assert.Check(t, is.Len(sb.state.runConfig.Volumes, 1))
|
||||||
|
@ -376,7 +381,7 @@ func TestStopSignal(t *testing.T) {
|
||||||
t.Skip("Windows does not support stopsignal")
|
t.Skip("Windows does not support stopsignal")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
sb.state.baseImage = &mockImage{}
|
sb.state.baseImage = &mockImage{}
|
||||||
signal := "SIGKILL"
|
signal := "SIGKILL"
|
||||||
|
@ -384,19 +389,19 @@ func TestStopSignal(t *testing.T) {
|
||||||
cmd := &instructions.StopSignalCommand{
|
cmd := &instructions.StopSignalCommand{
|
||||||
Signal: signal,
|
Signal: signal,
|
||||||
}
|
}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Check(t, is.Equal(signal, sb.state.runConfig.StopSignal))
|
assert.Check(t, is.Equal(signal, sb.state.runConfig.StopSignal))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArg(t *testing.T) {
|
func TestArg(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
|
|
||||||
argName := "foo"
|
argName := "foo"
|
||||||
argVal := "bar"
|
argVal := "bar"
|
||||||
cmd := &instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{Key: argName, Value: &argVal}}}
|
cmd := &instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{Key: argName, Value: &argVal}}}
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
expected := map[string]string{argName: argVal}
|
expected := map[string]string{argName: argVal}
|
||||||
|
@ -404,13 +409,13 @@ func TestArg(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShell(t *testing.T) {
|
func TestShell(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
|
|
||||||
shellCmd := "powershell"
|
shellCmd := "powershell"
|
||||||
cmd := &instructions.ShellCommand{Shell: strslice.StrSlice{shellCmd}}
|
cmd := &instructions.ShellCommand{Shell: strslice.StrSlice{shellCmd}}
|
||||||
|
|
||||||
err := dispatch(sb, cmd)
|
err := dispatch(context.TODO(), sb, cmd)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
expectedShell := strslice.StrSlice([]string{shellCmd})
|
expectedShell := strslice.StrSlice([]string{shellCmd})
|
||||||
|
@ -430,7 +435,7 @@ func TestPrependEnvOnCmd(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunWithBuildArgs(t *testing.T) {
|
func TestRunWithBuildArgs(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
args := NewBuildArgs(make(map[string]*string))
|
args := NewBuildArgs(make(map[string]*string))
|
||||||
args.argsFromOptions["HTTP_PROXY"] = strPtr("FOO")
|
args.argsFromOptions["HTTP_PROXY"] = strPtr("FOO")
|
||||||
b.disableCommit = false
|
b.disableCommit = false
|
||||||
|
@ -462,7 +467,11 @@ func TestRunWithBuildArgs(t *testing.T) {
|
||||||
mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
|
mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
|
||||||
return 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) {
|
mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ROLayer, error) {
|
||||||
return &mockImage{
|
return &mockImage{
|
||||||
id: "abcdef",
|
id: "abcdef",
|
||||||
|
@ -484,7 +493,7 @@ func TestRunWithBuildArgs(t *testing.T) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
from := &instructions.Stage{BaseName: "abcdef"}
|
from := &instructions.Stage{BaseName: "abcdef"}
|
||||||
err := initializeStage(sb, from)
|
err = initializeStage(context.TODO(), sb, from)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
sb.state.buildArgs.AddArg("one", strPtr("two"))
|
sb.state.buildArgs.AddArg("one", strPtr("two"))
|
||||||
|
|
||||||
|
@ -504,14 +513,14 @@ func TestRunWithBuildArgs(t *testing.T) {
|
||||||
runinst.CmdLine = strslice.StrSlice{"echo foo"}
|
runinst.CmdLine = strslice.StrSlice{"echo foo"}
|
||||||
runinst.PrependShell = true
|
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
|
// Check that runConfig.Cmd has not been modified by run
|
||||||
assert.Check(t, is.DeepEqual(origCmd, sb.state.runConfig.Cmd))
|
assert.Check(t, is.DeepEqual(origCmd, sb.state.runConfig.Cmd))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunIgnoresHealthcheck(t *testing.T) {
|
func TestRunIgnoresHealthcheck(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
args := NewBuildArgs(make(map[string]*string))
|
args := NewBuildArgs(make(map[string]*string))
|
||||||
sb := newDispatchRequest(b, '`', nil, args, newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, args, newStagesBuildResults())
|
||||||
b.disableCommit = false
|
b.disableCommit = false
|
||||||
|
@ -528,7 +537,10 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
||||||
mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
|
mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
|
||||||
return 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) {
|
mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ROLayer, error) {
|
||||||
return &mockImage{
|
return &mockImage{
|
||||||
id: "abcdef",
|
id: "abcdef",
|
||||||
|
@ -542,7 +554,7 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
from := &instructions.Stage{BaseName: "abcdef"}
|
from := &instructions.Stage{BaseName: "abcdef"}
|
||||||
err := initializeStage(sb, from)
|
err = initializeStage(context.TODO(), sb, from)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
|
expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
|
||||||
|
@ -559,7 +571,7 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
cmd := healthint.(*instructions.HealthCheckCommand)
|
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)
|
assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
|
||||||
|
|
||||||
mockBackend.containerCreateFunc = func(config types.ContainerCreateConfig) (container.CreateResponse, error) {
|
mockBackend.containerCreateFunc = func(config types.ContainerCreateConfig) (container.CreateResponse, error) {
|
||||||
|
@ -574,12 +586,12 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
|
||||||
run := runint.(*instructions.RunCommand)
|
run := runint.(*instructions.RunCommand)
|
||||||
run.PrependShell = true
|
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))
|
assert.Check(t, is.DeepEqual(expectedTest, sb.state.runConfig.Healthcheck.Test))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDispatchUnsupportedOptions(t *testing.T) {
|
func TestDispatchUnsupportedOptions(t *testing.T) {
|
||||||
b := newBuilderWithMockBackend()
|
b := newBuilderWithMockBackend(t)
|
||||||
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
|
||||||
sb.state.baseImage = &mockImage{}
|
sb.state.baseImage = &mockImage{}
|
||||||
sb.state.operatingSystem = runtime.GOOS
|
sb.state.operatingSystem = runtime.GOOS
|
||||||
|
@ -592,7 +604,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
Chmod: "0655",
|
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")
|
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 +616,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
Chmod: "0655",
|
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")
|
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 +630,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
|
||||||
// one or more of these flags will be supported in future
|
// one or more of these flags will be supported in future
|
||||||
for _, f := range []string{"mount", "network", "security", "any-flag"} {
|
for _, f := range []string{"mount", "network", "security", "any-flag"} {
|
||||||
cmd.FlagsUsed = []string{f}
|
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))
|
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"
|
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -34,7 +35,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"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 {
|
if c, ok := cmd.(instructions.PlatformSpecific); ok {
|
||||||
err := c.CheckPlatform(d.state.operatingSystem)
|
err := c.CheckPlatform(d.state.operatingSystem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -65,39 +66,39 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
|
||||||
}()
|
}()
|
||||||
switch c := cmd.(type) {
|
switch c := cmd.(type) {
|
||||||
case *instructions.EnvCommand:
|
case *instructions.EnvCommand:
|
||||||
return dispatchEnv(d, c)
|
return dispatchEnv(ctx, d, c)
|
||||||
case *instructions.MaintainerCommand:
|
case *instructions.MaintainerCommand:
|
||||||
return dispatchMaintainer(d, c)
|
return dispatchMaintainer(ctx, d, c)
|
||||||
case *instructions.LabelCommand:
|
case *instructions.LabelCommand:
|
||||||
return dispatchLabel(d, c)
|
return dispatchLabel(ctx, d, c)
|
||||||
case *instructions.AddCommand:
|
case *instructions.AddCommand:
|
||||||
return dispatchAdd(d, c)
|
return dispatchAdd(ctx, d, c)
|
||||||
case *instructions.CopyCommand:
|
case *instructions.CopyCommand:
|
||||||
return dispatchCopy(d, c)
|
return dispatchCopy(ctx, d, c)
|
||||||
case *instructions.OnbuildCommand:
|
case *instructions.OnbuildCommand:
|
||||||
return dispatchOnbuild(d, c)
|
return dispatchOnbuild(ctx, d, c)
|
||||||
case *instructions.WorkdirCommand:
|
case *instructions.WorkdirCommand:
|
||||||
return dispatchWorkdir(d, c)
|
return dispatchWorkdir(ctx, d, c)
|
||||||
case *instructions.RunCommand:
|
case *instructions.RunCommand:
|
||||||
return dispatchRun(d, c)
|
return dispatchRun(ctx, d, c)
|
||||||
case *instructions.CmdCommand:
|
case *instructions.CmdCommand:
|
||||||
return dispatchCmd(d, c)
|
return dispatchCmd(ctx, d, c)
|
||||||
case *instructions.HealthCheckCommand:
|
case *instructions.HealthCheckCommand:
|
||||||
return dispatchHealthcheck(d, c)
|
return dispatchHealthcheck(ctx, d, c)
|
||||||
case *instructions.EntrypointCommand:
|
case *instructions.EntrypointCommand:
|
||||||
return dispatchEntrypoint(d, c)
|
return dispatchEntrypoint(ctx, d, c)
|
||||||
case *instructions.ExposeCommand:
|
case *instructions.ExposeCommand:
|
||||||
return dispatchExpose(d, c, envs)
|
return dispatchExpose(ctx, d, c, envs)
|
||||||
case *instructions.UserCommand:
|
case *instructions.UserCommand:
|
||||||
return dispatchUser(d, c)
|
return dispatchUser(ctx, d, c)
|
||||||
case *instructions.VolumeCommand:
|
case *instructions.VolumeCommand:
|
||||||
return dispatchVolume(d, c)
|
return dispatchVolume(ctx, d, c)
|
||||||
case *instructions.StopSignalCommand:
|
case *instructions.StopSignalCommand:
|
||||||
return dispatchStopSignal(d, c)
|
return dispatchStopSignal(ctx, d, c)
|
||||||
case *instructions.ArgCommand:
|
case *instructions.ArgCommand:
|
||||||
return dispatchArg(d, c)
|
return dispatchArg(ctx, d, c)
|
||||||
case *instructions.ShellCommand:
|
case *instructions.ShellCommand:
|
||||||
return dispatchShell(d, c)
|
return dispatchShell(ctx, d, c)
|
||||||
}
|
}
|
||||||
return errors.Errorf("unsupported command type: %v", reflect.TypeOf(cmd))
|
return errors.Errorf("unsupported command type: %v", reflect.TypeOf(cmd))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"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())
|
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))
|
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/builder"
|
"github.com/docker/docker/builder"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -9,30 +11,42 @@ import (
|
||||||
// ImageProber exposes an Image cache to the Builder. It supports resetting a
|
// ImageProber exposes an Image cache to the Builder. It supports resetting a
|
||||||
// cache.
|
// cache.
|
||||||
type ImageProber interface {
|
type ImageProber interface {
|
||||||
Reset()
|
Reset(ctx context.Context) error
|
||||||
Probe(parentID string, runConfig *container.Config) (string, error)
|
Probe(parentID string, runConfig *container.Config) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type resetFunc func(context.Context) (builder.ImageCache, error)
|
||||||
|
|
||||||
type imageProber struct {
|
type imageProber struct {
|
||||||
cache builder.ImageCache
|
cache builder.ImageCache
|
||||||
reset func() builder.ImageCache
|
reset resetFunc
|
||||||
cacheBusted bool
|
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 {
|
if noCache {
|
||||||
return &nopProber{}
|
return &nopProber{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
reset := func() builder.ImageCache {
|
reset := func(ctx context.Context) (builder.ImageCache, error) {
|
||||||
return cacheBuilder.MakeImageCache(cacheFrom)
|
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() {
|
func (c *imageProber) Reset(ctx context.Context) error {
|
||||||
c.cache = c.reset()
|
newCache, err := c.reset(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.cache = newCache
|
||||||
c.cacheBusted = false
|
c.cacheBusted = false
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Probe checks if cache match can be found for current build instruction.
|
// 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{}
|
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) {
|
func (c *nopProber) Probe(_ string, _ *container.Config) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
|
|
|
@ -4,6 +4,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||||
// non-contiguous functionality. Please read the comments.
|
// non-contiguous functionality. Please read the comments.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -27,7 +28,7 @@ func (b *Builder) getArchiver() *archive.Archiver {
|
||||||
return chrootarchive.NewArchiver(b.idMapping)
|
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 {
|
if b.disableCommit {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -36,7 +37,7 @@ func (b *Builder) commit(dispatchState *dispatchState, comment string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
runConfigWithCommentCmd := copyRunConfig(dispatchState.runConfig, withCmdComment(comment, dispatchState.operatingSystem))
|
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 == "" {
|
if err != nil || id == "" {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -107,7 +108,7 @@ func (b *Builder) exportImage(state *dispatchState, layer builder.RWLayer, paren
|
||||||
return nil
|
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
|
state := req.state
|
||||||
srcHash := getSourceHashFromInfos(inst.infos)
|
srcHash := getSourceHashFromInfos(inst.infos)
|
||||||
|
|
||||||
|
@ -147,7 +148,7 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
|
||||||
// translated (if necessary because of user namespaces), and replace
|
// translated (if necessary because of user namespaces), and replace
|
||||||
// the root pair with the chown pair for copy operations
|
// the root pair with the chown pair for copy operations
|
||||||
if inst.chownStr != "" {
|
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 err != nil {
|
||||||
if b.options.Platform != "windows" {
|
if b.options.Platform != "windows" {
|
||||||
return errors.Wrapf(err, "unable to convert uid/gid chown string to host mapping")
|
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"}
|
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 {
|
if hit, err := b.probeCache(dispatchState, runConfig); err != nil || hit {
|
||||||
return "", err
|
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)
|
logrus.Debugf("[BUILDER] Command to be executed: %v", runConfig.Cmd)
|
||||||
|
|
||||||
hostConfig := hostConfigFromOptions(b.options)
|
hostConfig := hostConfigFromOptions(b.options)
|
||||||
container, err := b.containerManager.Create(runConfig, hostConfig)
|
container, err := b.containerManager.Create(ctx, runConfig, hostConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -11,7 +12,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"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
|
var userStr, grpStr string
|
||||||
parts := strings.Split(chown, ":")
|
parts := strings.Split(chown, ":")
|
||||||
if len(parts) > 2 {
|
if len(parts) > 2 {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -115,7 +116,7 @@ othergrp:x:6666:
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
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.NilError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
|
||||||
assert.Check(t, is.DeepEqual(testcase.expected, idPair), "chown flag mapping failure")
|
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) {
|
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")
|
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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -14,15 +15,15 @@ import (
|
||||||
"golang.org/x/sys/windows"
|
"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" {
|
if builder.options.Platform == "windows" {
|
||||||
return getAccountIdentity(builder, chown, ctrRootPath, state)
|
return getAccountIdentity(ctx, builder, chown, ctrRootPath, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
return identityMapping.RootPair(), nil
|
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
|
// If this is potentially a string SID then attempt to convert it to verify
|
||||||
// this, otherwise continue looking for the account.
|
// this, otherwise continue looking for the account.
|
||||||
if strings.HasPrefix(accountName, "S-") || strings.HasPrefix(accountName, "s-") {
|
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
|
// All other lookups failed, so therefore determine if the account in
|
||||||
// question exists in the container and if so, obtain its SID.
|
// 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])
|
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 {
|
if err != nil {
|
||||||
return idtools.Identity{}, err
|
return idtools.Identity{}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout
|
||||||
return nil
|
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 {
|
if m.containerCreateFunc != nil {
|
||||||
return m.containerCreateFunc(config)
|
return m.containerCreateFunc(config)
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func (m *MockBackend) ContainerKill(containerID string, sig string) error {
|
||||||
return nil
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +73,11 @@ func (m *MockBackend) GetImageAndReleasableLayer(ctx context.Context, refOrID st
|
||||||
return &mockImage{id: "theid"}, &mockLayer{}, nil
|
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 {
|
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) {
|
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
|
// notify systemd that we're shutting down
|
||||||
notifyStopping()
|
notifyStopping()
|
||||||
shutdownDaemon(d)
|
shutdownDaemon(ctx, d)
|
||||||
|
|
||||||
// Stop notification processing and any background processes
|
// Stop notification processing and any background processes
|
||||||
cancel()
|
cancel()
|
||||||
|
@ -359,11 +359,11 @@ func (cli *DaemonCli) stop() {
|
||||||
// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
|
// shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
|
||||||
// d.Shutdown() is waiting too long to kill container or worst it's
|
// d.Shutdown() is waiting too long to kill container or worst it's
|
||||||
// blocked there
|
// blocked there
|
||||||
func shutdownDaemon(d *daemon.Daemon) {
|
func shutdownDaemon(ctx context.Context, d *daemon.Daemon) {
|
||||||
shutdownTimeout := d.ShutdownTimeout()
|
shutdownTimeout := d.ShutdownTimeout()
|
||||||
ch := make(chan struct{})
|
ch := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
d.Shutdown()
|
d.Shutdown(ctx)
|
||||||
close(ch)
|
close(ch)
|
||||||
}()
|
}()
|
||||||
if shutdownTimeout < 0 {
|
if shutdownTimeout < 0 {
|
||||||
|
|
|
@ -37,8 +37,8 @@ type Backend interface {
|
||||||
FindNetwork(idName string) (libnetwork.Network, error)
|
FindNetwork(idName string) (libnetwork.Network, error)
|
||||||
SetupIngress(clustertypes.NetworkCreateRequest, string) (<-chan struct{}, error)
|
SetupIngress(clustertypes.NetworkCreateRequest, string) (<-chan struct{}, error)
|
||||||
ReleaseIngress() (<-chan struct{}, error)
|
ReleaseIngress() (<-chan struct{}, error)
|
||||||
CreateManagedContainer(config types.ContainerCreateConfig) (container.CreateResponse, error)
|
CreateManagedContainer(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, 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, config container.StopOptions) 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)
|
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
|
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||||
|
@ -53,7 +53,7 @@ type Backend interface {
|
||||||
SetContainerSecretReferences(name string, refs []*swarm.SecretReference) error
|
SetContainerSecretReferences(name string, refs []*swarm.SecretReference) error
|
||||||
SetContainerConfigReferences(name string, refs []*swarm.ConfigReference) error
|
SetContainerConfigReferences(name string, refs []*swarm.ConfigReference) error
|
||||||
SystemInfo() *types.Info
|
SystemInfo() *types.Info
|
||||||
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error)
|
||||||
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
||||||
DaemonJoinsCluster(provider cluster.Provider)
|
DaemonJoinsCluster(provider cluster.Provider)
|
||||||
DaemonLeavesCluster()
|
DaemonLeavesCluster()
|
||||||
|
|
|
@ -290,7 +290,7 @@ func (c *containerAdapter) waitForDetach(ctx context.Context) error {
|
||||||
func (c *containerAdapter) create(ctx context.Context) error {
|
func (c *containerAdapter) create(ctx context.Context) error {
|
||||||
var cr containertypes.CreateResponse
|
var cr containertypes.CreateResponse
|
||||||
var err error
|
var err error
|
||||||
if cr, err = c.backend.CreateManagedContainer(types.ContainerCreateConfig{
|
if cr, err = c.backend.CreateManagedContainer(ctx, types.ContainerCreateConfig{
|
||||||
Name: c.container.name(),
|
Name: c.container.name(),
|
||||||
Config: c.container.config(),
|
Config: c.container.config(),
|
||||||
HostConfig: c.container.hostConfig(c.dependencies.Volumes()),
|
HostConfig: c.container.hostConfig(c.dependencies.Volumes()),
|
||||||
|
@ -357,7 +357,7 @@ func (c *containerAdapter) start(ctx context.Context) error {
|
||||||
return err
|
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) {
|
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.
|
// 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()
|
c.controlMutex.Lock()
|
||||||
defer c.controlMutex.Unlock()
|
defer c.controlMutex.Unlock()
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ func (c *Cluster) Leave(force bool) error {
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
|
||||||
if nodeID := state.NodeID(); nodeID != "" {
|
if nodeID := state.NodeID(); nodeID != "" {
|
||||||
nodeContainers, err := c.listContainerForNode(nodeID)
|
nodeContainers, err := c.listContainerForNode(ctx, nodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -604,11 +604,11 @@ func initClusterSpec(node *swarmnode.Node, spec types.Spec) error {
|
||||||
return ctx.Err()
|
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
|
var ids []string
|
||||||
filters := filters.NewArgs()
|
filters := filters.NewArgs()
|
||||||
filters.Add("label", fmt.Sprintf("com.docker.swarm.node.id=%s", nodeID))
|
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,
|
Filters: filters,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package daemon // import "github.com/docker/docker/daemon"
|
package daemon // import "github.com/docker/docker/daemon"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -116,7 +117,7 @@ func merge(userConf, imageConf *containertypes.Config) error {
|
||||||
// CreateImageFromContainer creates a new image from a container. The container
|
// CreateImageFromContainer creates a new image from a container. The container
|
||||||
// config will be updated by applying the change set to the custom config, then
|
// config will be updated by applying the change set to the custom config, then
|
||||||
// applying that config over the existing container config.
|
// 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()
|
start := time.Now()
|
||||||
container, err := daemon.GetContainer(name)
|
container, err := daemon.GetContainer(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -146,7 +147,7 @@ func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateIma
|
||||||
if c.Config == nil {
|
if c.Config == nil {
|
||||||
c.Config = container.Config
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/docker/docker/builder"
|
"github.com/docker/docker/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeImageCache creates a stateful image cache.
|
// 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")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package containerd
|
package containerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
@ -12,6 +13,6 @@ import (
|
||||||
// inConfig (if src is "-"), or from a URI specified in src. Progress output is
|
// 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
|
// written to outStream. Repository and tag names can optionally be given in
|
||||||
// the repo and tag arguments, respectively.
|
// 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"))
|
return errdefs.NotImplemented(errors.New("not implemented"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,31 +33,30 @@ type createOpts struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateManagedContainer creates a container that is managed by a Service
|
// CreateManagedContainer creates a container that is managed by a Service
|
||||||
func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
func (daemon *Daemon) CreateManagedContainer(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||||
return daemon.containerCreate(createOpts{
|
return daemon.containerCreate(ctx, createOpts{
|
||||||
params: params,
|
params: params,
|
||||||
managed: true,
|
managed: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerCreate creates a regular container
|
// ContainerCreate creates a regular container
|
||||||
func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
func (daemon *Daemon) ContainerCreate(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||||
return daemon.containerCreate(createOpts{
|
return daemon.containerCreate(ctx, createOpts{
|
||||||
params: params,
|
params: params,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerCreateIgnoreImagesArgsEscaped creates a regular container. This is called from the builder RUN case
|
// ContainerCreateIgnoreImagesArgsEscaped creates a regular container. This is called from the builder RUN case
|
||||||
// and ensures that we do not take the images ArgsEscaped
|
// and ensures that we do not take the images ArgsEscaped
|
||||||
func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
|
||||||
return daemon.containerCreate(createOpts{
|
return daemon.containerCreate(ctx, createOpts{
|
||||||
params: params,
|
params: params,
|
||||||
ignoreImagesArgsEscaped: true,
|
ignoreImagesArgsEscaped: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.CreateResponse, error) {
|
func (daemon *Daemon) containerCreate(ctx context.Context, opts createOpts) (containertypes.CreateResponse, error) {
|
||||||
ctx := context.TODO()
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if opts.params.Config == nil {
|
if opts.params.Config == nil {
|
||||||
return containertypes.CreateResponse{}, errdefs.InvalidParameter(errors.New("Config cannot be empty in order to create a container"))
|
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)
|
return containertypes.CreateResponse{Warnings: warnings}, errdefs.InvalidParameter(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctr, err := daemon.create(opts)
|
ctr, err := daemon.create(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return containertypes.CreateResponse{Warnings: warnings}, err
|
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.
|
// Create creates a new container from the given configuration with a given name.
|
||||||
func (daemon *Daemon) create(opts createOpts) (retC *container.Container, retErr error) {
|
func (daemon *Daemon) create(ctx context.Context, opts createOpts) (retC *container.Container, retErr error) {
|
||||||
ctx := context.TODO()
|
|
||||||
var (
|
var (
|
||||||
ctr *container.Container
|
ctr *container.Container
|
||||||
img *image.Image
|
img *image.Image
|
||||||
|
|
|
@ -526,7 +526,7 @@ func (daemon *Daemon) restore() error {
|
||||||
if err := daemon.prepareMountPoints(c); err != nil {
|
if err := daemon.prepareMountPoints(c); err != nil {
|
||||||
log.WithError(err).Error("failed to prepare mount points for container")
|
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")
|
log.WithError(err).Error("failed to start container")
|
||||||
}
|
}
|
||||||
close(chNotify)
|
close(chNotify)
|
||||||
|
@ -617,7 +617,7 @@ func (daemon *Daemon) RestartSwarmContainers() {
|
||||||
return
|
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")
|
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
|
// initialization
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
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)
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1193,17 +1194,17 @@ func (daemon *Daemon) ShutdownTimeout() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown stops the daemon.
|
// Shutdown stops the daemon.
|
||||||
func (daemon *Daemon) Shutdown() error {
|
func (daemon *Daemon) Shutdown(ctx context.Context) error {
|
||||||
daemon.shutdown = true
|
daemon.shutdown = true
|
||||||
// Keep mounts and networking running on daemon shutdown if
|
// Keep mounts and networking running on daemon shutdown if
|
||||||
// we are to keep containers running and restore them.
|
// we are to keep containers running and restore them.
|
||||||
|
|
||||||
if daemon.configStore.LiveRestoreEnabled && daemon.containers != nil {
|
if daemon.configStore.LiveRestoreEnabled && daemon.containers != nil {
|
||||||
// check if there are any running containers, if none we should do some cleanup
|
// 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
|
// metrics plugins still need some cleanup
|
||||||
daemon.cleanupMetricsPlugins()
|
daemon.cleanupMetricsPlugins()
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
func (daemon *Daemon) ContainerDiskUsage(ctx context.Context) ([]*types.Container, error) {
|
func (daemon *Daemon) ContainerDiskUsage(ctx context.Context) ([]*types.Container, error) {
|
||||||
ch := daemon.usage.DoChan("ContainerDiskUsage", func() (interface{}, error) {
|
ch := daemon.usage.DoChan("ContainerDiskUsage", func() (interface{}, error) {
|
||||||
// Retrieve container list
|
// Retrieve container list
|
||||||
containers, err := daemon.Containers(&types.ContainerListOptions{
|
containers, err := daemon.Containers(context.TODO(), &types.ContainerListOptions{
|
||||||
Size: true,
|
Size: true,
|
||||||
All: true,
|
All: true,
|
||||||
})
|
})
|
||||||
|
|
|
@ -37,7 +37,7 @@ type ImageService interface {
|
||||||
CountImages() int
|
CountImages() int
|
||||||
ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error)
|
ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error)
|
||||||
ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, 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)
|
TagImage(imageName, repository, tag string) (string, error)
|
||||||
TagImageWithReference(imageID image.ID, newTag reference.Named) error
|
TagImageWithReference(imageID image.ID, newTag reference.Named) error
|
||||||
GetImage(ctx context.Context, refOrID string, options imagetype.GetImageOpts) (*image.Image, error)
|
GetImage(ctx context.Context, refOrID string, options imagetype.GetImageOpts) (*image.Image, error)
|
||||||
|
@ -62,7 +62,7 @@ type ImageService interface {
|
||||||
|
|
||||||
// Build
|
// Build
|
||||||
|
|
||||||
MakeImageCache(sourceRefs []string) builder.ImageCache
|
MakeImageCache(ctx context.Context, cacheFrom []string) (builder.ImageCache, error)
|
||||||
CommitBuildStep(c backend.CommitConfig) (image.ID, error)
|
CommitBuildStep(c backend.CommitConfig) (image.ID, error)
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
|
@ -6,14 +6,14 @@ import (
|
||||||
imagetypes "github.com/docker/docker/api/types/image"
|
imagetypes "github.com/docker/docker/api/types/image"
|
||||||
"github.com/docker/docker/builder"
|
"github.com/docker/docker/builder"
|
||||||
"github.com/docker/docker/image/cache"
|
"github.com/docker/docker/image/cache"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeImageCache creates a stateful image cache.
|
// MakeImageCache creates a stateful image cache.
|
||||||
func (i *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
|
func (i *ImageService) MakeImageCache(ctx context.Context, sourceRefs []string) (builder.ImageCache, error) {
|
||||||
ctx := context.TODO()
|
|
||||||
if len(sourceRefs) == 0 {
|
if len(sourceRefs) == 0 {
|
||||||
return cache.NewLocal(i.imageStore)
|
return cache.NewLocal(i.imageStore), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cache := cache.New(i.imageStore)
|
cache := cache.New(i.imageStore)
|
||||||
|
@ -21,11 +21,14 @@ func (i *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
|
||||||
for _, ref := range sourceRefs {
|
for _, ref := range sourceRefs {
|
||||||
img, err := i.GetImage(ctx, ref, imagetypes.GetImageOpts{})
|
img, err := i.GetImage(ctx, ref, imagetypes.GetImageOpts{})
|
||||||
if err != nil {
|
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)
|
logrus.Warnf("Could not look up %s for cache resolution, skipping: %+v", ref, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cache.Populate(img)
|
cache.Populate(img)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache
|
return cache, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package images // import "github.com/docker/docker/daemon/images"
|
package images // import "github.com/docker/docker/daemon/images"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -29,7 +30,7 @@ import (
|
||||||
// inConfig (if src is "-"), or from a URI specified in src. Progress output is
|
// 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
|
// written to outStream. Repository and tag names can optionally be given in
|
||||||
// the repo and tag arguments, respectively.
|
// 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 (
|
var (
|
||||||
rc io.ReadCloser
|
rc io.ReadCloser
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
|
@ -62,7 +63,7 @@ func (i *ImageService) ImportImage(src string, repository string, platform *spec
|
||||||
if !system.IsOSSupported(platform.OS) {
|
if !system.IsOSSupported(platform.OS) {
|
||||||
return errdefs.InvalidParameter(system.ErrNotSupportedOperatingSystem)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ type iterationAction int
|
||||||
|
|
||||||
// containerReducer represents a reducer for a container.
|
// containerReducer represents a reducer for a container.
|
||||||
// Returns the object to serialize by the api.
|
// 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 (
|
const (
|
||||||
// includeContainer is the action to include a container in the reducer.
|
// 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.
|
// Containers returns the list of containers to show given the user's filtering.
|
||||||
func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*types.Container, error) {
|
func (daemon *Daemon) Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error) {
|
||||||
return daemon.reduceContainers(config, daemon.refreshImage)
|
return daemon.reduceContainers(ctx, config, daemon.refreshImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listContext) ([]container.Snapshot, error) {
|
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.
|
// 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 {
|
if err := config.Filters.Validate(acceptedPsFilterTags); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
|
||||||
containers = []*types.Container{}
|
containers = []*types.Container{}
|
||||||
)
|
)
|
||||||
|
|
||||||
filter, err := daemon.foldFilter(view, config)
|
filter, err := daemon.foldFilter(ctx, view, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range containerList {
|
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 != nil {
|
||||||
if err != errStopIteration {
|
if err != errStopIteration {
|
||||||
return nil, err
|
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.
|
// 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
|
// filter containers to return
|
||||||
switch includeContainerInList(container, filter) {
|
switch includeContainerInList(container, filter) {
|
||||||
case excludeContainer:
|
case excludeContainer:
|
||||||
|
@ -228,7 +228,7 @@ func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *l
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform internal container struct into api structs
|
// transform internal container struct into api structs
|
||||||
newC, err := reducer(container, filter)
|
newC, err := reducer(ctx, container, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// foldFilter generates the container filter based on the user's filtering options.
|
||||||
func (daemon *Daemon) foldFilter(view *container.View, config *types.ContainerListOptions) (*listContext, error) {
|
func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, config *types.ContainerListOptions) (*listContext, error) {
|
||||||
ctx := context.TODO()
|
|
||||||
psFilters := config.Filters
|
psFilters := config.Filters
|
||||||
|
|
||||||
var filtExited []int
|
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
|
// 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) {
|
func (daemon *Daemon) refreshImage(ctx context.Context, s *container.Snapshot, filter *listContext) (*types.Container, error) {
|
||||||
ctx := context.TODO()
|
|
||||||
c := s.Container
|
c := s.Container
|
||||||
tmpImage := s.Image // keep the original ref if still valid (hasn't changed)
|
tmpImage := s.Image // keep the original ref if still valid (hasn't changed)
|
||||||
if tmpImage != s.ImageID {
|
if tmpImage != s.ImageID {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -88,7 +89,7 @@ func TestListInvalidFilter(t *testing.T) {
|
||||||
|
|
||||||
f := filters.NewArgs(filters.Arg("invalid", "foo"))
|
f := filters.NewArgs(filters.Arg("invalid", "foo"))
|
||||||
|
|
||||||
_, err = d.Containers(&types.ContainerListOptions{
|
_, err = d.Containers(context.Background(), &types.ContainerListOptions{
|
||||||
Filters: f,
|
Filters: f,
|
||||||
})
|
})
|
||||||
assert.Assert(t, is.Error(err, "invalid filter 'invalid'"))
|
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
|
// moby/moby #37453 - ^ regex not working due to prefix slash
|
||||||
// not being stripped
|
// not being stripped
|
||||||
containerList, err := d.Containers(&types.ContainerListOptions{
|
containerList, err := d.Containers(context.Background(), &types.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(filters.Arg("name", "^a")),
|
Filters: filters.NewArgs(filters.Arg("name", "^a")),
|
||||||
})
|
})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -118,7 +119,7 @@ func TestNameFilter(t *testing.T) {
|
||||||
assert.Assert(t, containerListContainsName(containerList, two.Name))
|
assert.Assert(t, containerListContainsName(containerList, two.Name))
|
||||||
|
|
||||||
// Same as above but with slash prefix should produce the same result
|
// 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")),
|
Filters: filters.NewArgs(filters.Arg("name", "^/a")),
|
||||||
})
|
})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -127,7 +128,7 @@ func TestNameFilter(t *testing.T) {
|
||||||
assert.Assert(t, containerListContainsName(containerListWithPrefix, two.Name))
|
assert.Assert(t, containerListContainsName(containerListWithPrefix, two.Name))
|
||||||
|
|
||||||
// Same as above but make sure it works for exact names
|
// 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")),
|
Filters: filters.NewArgs(filters.Arg("name", "b1")),
|
||||||
})
|
})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -135,7 +136,7 @@ func TestNameFilter(t *testing.T) {
|
||||||
assert.Assert(t, containerListContainsName(containerList, three.Name))
|
assert.Assert(t, containerListContainsName(containerList, three.Name))
|
||||||
|
|
||||||
// Same as above but with slash prefix should produce the same result
|
// 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")),
|
Filters: filters.NewArgs(filters.Arg("name", "/b1")),
|
||||||
})
|
})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
|
@ -111,7 +111,7 @@ func (daemon *Daemon) handleContainerExit(c *container.Container, e *libcontaine
|
||||||
// But containerStart will use daemon.netController segment.
|
// But containerStart will use daemon.netController segment.
|
||||||
// So to avoid panic at startup process, here must wait util daemon restore done.
|
// So to avoid panic at startup process, here must wait util daemon restore done.
|
||||||
daemon.waitForStartupDone()
|
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)
|
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 (
|
var (
|
||||||
opts []coci.SpecOpts
|
opts []coci.SpecOpts
|
||||||
s = oci.DefaultSpec()
|
s = oci.DefaultSpec()
|
||||||
|
@ -1052,7 +1052,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
|
||||||
snapshotKey = c.ID
|
snapshotKey = c.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
|
return &s, coci.ApplyOpts(ctx, nil, &containers.Container{
|
||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
Snapshotter: snapshotter,
|
Snapshotter: snapshotter,
|
||||||
SnapshotKey: snapshotKey,
|
SnapshotKey: snapshotKey,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package daemon // import "github.com/docker/docker/daemon"
|
package daemon // import "github.com/docker/docker/daemon"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -73,7 +74,7 @@ func TestTmpfsDevShmNoDupMount(t *testing.T) {
|
||||||
d := setupFakeDaemon(t, c)
|
d := setupFakeDaemon(t, c)
|
||||||
defer cleanupFakeContainer(c)
|
defer cleanupFakeContainer(c)
|
||||||
|
|
||||||
_, err := d.createSpec(c)
|
_, err := d.createSpec(context.TODO(), c)
|
||||||
assert.Check(t, err)
|
assert.Check(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ func TestIpcPrivateVsReadonly(t *testing.T) {
|
||||||
d := setupFakeDaemon(t, c)
|
d := setupFakeDaemon(t, c)
|
||||||
defer cleanupFakeContainer(c)
|
defer cleanupFakeContainer(c)
|
||||||
|
|
||||||
s, err := d.createSpec(c)
|
s, err := d.createSpec(context.TODO(), c)
|
||||||
assert.Check(t, err)
|
assert.Check(t, err)
|
||||||
|
|
||||||
// Find the /dev/shm mount in ms, check it does not have ro
|
// 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)
|
defer cleanupFakeContainer(c)
|
||||||
|
|
||||||
// Ensure that the implicit sysctl is set correctly.
|
// 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.NilError(t, err)
|
||||||
assert.Equal(t, s.Hostname, "foobar")
|
assert.Equal(t, s.Hostname, "foobar")
|
||||||
assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.Config.Domainname)
|
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)
|
assert.Assert(t, c.HostConfig.Sysctls["kernel.domainname"] != c.Config.Domainname)
|
||||||
c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
|
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.NilError(t, err)
|
||||||
assert.Equal(t, s.Hostname, "foobar")
|
assert.Equal(t, s.Hostname, "foobar")
|
||||||
assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.HostConfig.Sysctls["kernel.domainname"])
|
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
|
// Ensure the ping_group_range is not set on a daemon with user-namespaces enabled
|
||||||
d.configStore.RemappedRoot = "dummy:dummy"
|
d.configStore.RemappedRoot = "dummy:dummy"
|
||||||
s, err = d.createSpec(c)
|
s, err = d.createSpec(context.TODO(), c)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
_, ok := s.Linux.Sysctl["net.ipv4.ping_group_range"]
|
_, ok := s.Linux.Sysctl["net.ipv4.ping_group_range"]
|
||||||
assert.Assert(t, !ok)
|
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
|
// Ensure the ping_group_range is set on a container in "host" userns mode
|
||||||
// on a daemon with user-namespaces enabled
|
// on a daemon with user-namespaces enabled
|
||||||
c.HostConfig.UsernsMode = "host"
|
c.HostConfig.UsernsMode = "host"
|
||||||
s, err = d.createSpec(c)
|
s, err = d.createSpec(context.TODO(), c)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "0 2147483647")
|
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)
|
defer cleanupFakeContainer(c)
|
||||||
|
|
||||||
// Ensure that the implicit sysctl is not set
|
// 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.NilError(t, err)
|
||||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "")
|
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "")
|
||||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "")
|
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "")
|
||||||
|
@ -182,7 +183,7 @@ func TestSysctlOverrideHost(t *testing.T) {
|
||||||
// Set an explicit sysctl.
|
// Set an explicit sysctl.
|
||||||
c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
|
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.NilError(t, err)
|
||||||
assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"])
|
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"
|
credentialSpecFileLocation = "CredentialSpecs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
func (daemon *Daemon) createSpec(ctx context.Context, c *container.Container) (*specs.Spec, error) {
|
||||||
ctx := context.TODO()
|
|
||||||
img, err := daemon.imageService.GetImage(ctx, string(c.ImageID), imagetypes.GetImageOpts{})
|
img, err := daemon.imageService.GetImage(ctx, string(c.ImageID), imagetypes.GetImageOpts{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContainerStart starts a container.
|
// 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() {
|
if checkpoint != "" && !daemon.HasExperimental() {
|
||||||
return errdefs.InvalidParameter(errors.New("checkpoint is only supported in experimental mode"))
|
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 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
|
// containerStart prepares the container to run by setting up everything the
|
||||||
// container needs, such as storage and networking, as well as links
|
// container needs, such as storage and networking, as well as links
|
||||||
// between containers. The container is left waiting for a signal to
|
// between containers. The container is left waiting for a signal to
|
||||||
// begin running.
|
// 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()
|
start := time.Now()
|
||||||
container.Lock()
|
container.Lock()
|
||||||
defer container.Unlock()
|
defer container.Unlock()
|
||||||
|
@ -151,7 +151,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := daemon.createSpec(container)
|
spec, err := daemon.createSpec(ctx, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errdefs.System(err)
|
return errdefs.System(err)
|
||||||
}
|
}
|
||||||
|
@ -177,8 +177,6 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
ctr, err := libcontainerd.ReplaceContainer(ctx, daemon.containerd, container.ID, spec, shim, createOptions)
|
ctr, err := libcontainerd.ReplaceContainer(ctx, daemon.containerd, container.ID, spec, shim, createOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return translateContainerdStartErr(container.Path, container.SetExitCode, err)
|
return translateContainerdStartErr(container.Path, container.SetExitCode, err)
|
||||||
|
|
Loading…
Reference in New Issue