mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add named context support
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
parent
fe4d7db1ec
commit
87512bbc84
4 changed files with 74 additions and 19 deletions
|
@ -189,15 +189,20 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, origina
|
|||
|
||||
var contextID *int
|
||||
if flFrom.IsUsed() {
|
||||
var err error
|
||||
context, err := strconv.Atoi(flFrom.Value)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "from expects an integer value corresponding to the context number")
|
||||
flFrom.Value = strings.ToLower(flFrom.Value)
|
||||
if context, ok := b.imageContexts.byName[flFrom.Value]; ok {
|
||||
contextID = &context
|
||||
} else {
|
||||
var err error
|
||||
context, err := strconv.Atoi(flFrom.Value)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "from expects an integer value corresponding to the context number")
|
||||
}
|
||||
if err := b.imageContexts.validate(context); err != nil {
|
||||
return err
|
||||
}
|
||||
contextID = &context
|
||||
}
|
||||
if err := b.imageContexts.validate(context); err != nil {
|
||||
return err
|
||||
}
|
||||
contextID = &context
|
||||
}
|
||||
|
||||
return b.runContextCommand(args, false, false, "COPY", contextID)
|
||||
|
@ -208,7 +213,13 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, origina
|
|||
// This sets the image the dockerfile will build on top of.
|
||||
//
|
||||
func from(b *Builder, args []string, attributes map[string]bool, original string) error {
|
||||
if len(args) != 1 {
|
||||
ctxName := ""
|
||||
if len(args) == 3 && strings.EqualFold(args[1], "as") {
|
||||
ctxName = strings.ToLower(args[2])
|
||||
if ok, _ := regexp.MatchString("^[a-z][a-z0-9-_\\.]*$", ctxName); !ok {
|
||||
return errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", ctxName)
|
||||
}
|
||||
} else if len(args) != 1 {
|
||||
return errExactlyOneArgument("FROM")
|
||||
}
|
||||
|
||||
|
@ -221,7 +232,9 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
|
|||
var image builder.Image
|
||||
|
||||
b.resetImageCache()
|
||||
b.imageContexts.new()
|
||||
if err := b.imageContexts.new(ctxName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Windows cannot support a container with no base image.
|
||||
if name == api.NoBaseImageSpecifier {
|
||||
|
|
|
@ -12,9 +12,10 @@ import (
|
|||
// imageContexts is a helper for stacking up built image rootfs and reusing
|
||||
// them as contexts
|
||||
type imageContexts struct {
|
||||
b *Builder
|
||||
list []*imageMount
|
||||
cache *pathCache
|
||||
b *Builder
|
||||
list []*imageMount
|
||||
byName map[string]int
|
||||
cache *pathCache
|
||||
}
|
||||
|
||||
type imageMount struct {
|
||||
|
@ -23,8 +24,18 @@ type imageMount struct {
|
|||
release func() error
|
||||
}
|
||||
|
||||
func (ic *imageContexts) new() {
|
||||
func (ic *imageContexts) new(name string) error {
|
||||
if len(name) > 0 {
|
||||
if ic.byName == nil {
|
||||
ic.byName = make(map[string]int)
|
||||
}
|
||||
if _, ok := ic.byName[name]; ok {
|
||||
return errors.Errorf("duplicate name %s", name)
|
||||
}
|
||||
ic.byName[name] = len(ic.list)
|
||||
}
|
||||
ic.list = append(ic.list, &imageMount{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ic *imageContexts) update(imageID string) {
|
||||
|
|
|
@ -80,7 +80,7 @@ func init() {
|
|||
command.Entrypoint: parseMaybeJSON,
|
||||
command.Env: parseEnv,
|
||||
command.Expose: parseStringsWhitespaceDelimited,
|
||||
command.From: parseString,
|
||||
command.From: parseStringsWhitespaceDelimited,
|
||||
command.Healthcheck: parseHealthConfig,
|
||||
command.Label: parseLabel,
|
||||
command.Maintainer: parseString,
|
||||
|
|
|
@ -5752,7 +5752,7 @@ func (s *DockerSuite) TestBuildContChar(c *check.C) {
|
|||
|
||||
func (s *DockerSuite) TestBuildCopyFromPreviousRootFS(c *check.C) {
|
||||
dockerfile := `
|
||||
FROM busybox
|
||||
FROM busybox AS first
|
||||
COPY foo bar
|
||||
FROM busybox
|
||||
%s
|
||||
|
@ -5762,7 +5762,8 @@ func (s *DockerSuite) TestBuildCopyFromPreviousRootFS(c *check.C) {
|
|||
COPY bar /
|
||||
COPY --from=1 baz sub/
|
||||
COPY --from=0 bar baz
|
||||
COPY --from=0 bar bay`
|
||||
COPY --from=first bar bay`
|
||||
|
||||
ctx := fakeContext(c, fmt.Sprintf(dockerfile, ""), map[string]string{
|
||||
"Dockerfile": dockerfile,
|
||||
"foo": "abc",
|
||||
|
@ -5847,6 +5848,36 @@ func (s *DockerSuite) TestBuildCopyFromPreviousRootFSErrors(c *check.C) {
|
|||
ExitCode: 1,
|
||||
Err: "invalid from flag value 0 refers current build block",
|
||||
})
|
||||
|
||||
dockerfile = `
|
||||
FROM busybox AS foo
|
||||
COPY --from=bar foo bar`
|
||||
|
||||
ctx = fakeContext(c, dockerfile, map[string]string{
|
||||
"Dockerfile": dockerfile,
|
||||
"foo": "abc",
|
||||
})
|
||||
defer ctx.Close()
|
||||
|
||||
buildImage("build1", withExternalBuildContext(ctx)).Assert(c, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "invalid context value bar",
|
||||
})
|
||||
|
||||
dockerfile = `
|
||||
FROM busybox AS 1
|
||||
COPY --from=1 foo bar`
|
||||
|
||||
ctx = fakeContext(c, dockerfile, map[string]string{
|
||||
"Dockerfile": dockerfile,
|
||||
"foo": "abc",
|
||||
})
|
||||
defer ctx.Close()
|
||||
|
||||
buildImage("build1", withExternalBuildContext(ctx)).Assert(c, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "invalid name for build stage",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildCopyFromPreviousFrom(c *check.C) {
|
||||
|
@ -5863,9 +5894,9 @@ func (s *DockerSuite) TestBuildCopyFromPreviousFrom(c *check.C) {
|
|||
result.Assert(c, icmd.Success)
|
||||
|
||||
dockerfile = `
|
||||
FROM build1:latest
|
||||
FROM build1:latest AS foo
|
||||
FROM busybox
|
||||
COPY --from=0 bar /
|
||||
COPY --from=foo bar /
|
||||
COPY foo /`
|
||||
ctx = fakeContext(c, dockerfile, map[string]string{
|
||||
"Dockerfile": dockerfile,
|
||||
|
|
Loading…
Reference in a new issue