Merge pull request #38487 from LinuxMercedes/error-on-empty-dockerfile

Error on empty dockerfile
This commit is contained in:
Sebastiaan van Stijn 2019-01-15 21:41:12 +01:00 committed by GitHub
commit bba833928c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 158 additions and 58 deletions

View file

@ -12,6 +12,7 @@ import (
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/dockerignore"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/urlutil"
"github.com/moby/buildkit/frontend/dockerfile/parser"
@ -34,8 +35,9 @@ func Detect(config backend.BuildConfig) (remote builder.Source, dockerfile *pars
case remoteURL == ClientSessionRemote:
res, err := parser.Parse(config.Source)
if err != nil {
return nil, nil, err
return nil, nil, errdefs.InvalidParameter(err)
}
return nil, res, nil
case urlutil.IsGitURL(remoteURL):
remote, dockerfile, err = newGitRemote(remoteURL, dockerfilePath)
@ -106,7 +108,7 @@ func newURLRemote(url string, dockerfilePath string, progressReader func(in io.R
switch contentType {
case mimeTypes.TextPlain:
res, err := parser.Parse(progressReader(content))
return nil, res, err
return nil, res, errdefs.InvalidParameter(err)
default:
source, err := FromArchive(progressReader(content))
if err != nil {
@ -146,11 +148,17 @@ func readAndParseDockerfile(name string, rc io.Reader) (*parser.Result, error) {
br := bufio.NewReader(rc)
if _, err := br.Peek(1); err != nil {
if err == io.EOF {
return nil, errors.Errorf("the Dockerfile (%s) cannot be empty", name)
return nil, errdefs.InvalidParameter(errors.Errorf("the Dockerfile (%s) cannot be empty", name))
}
return nil, errors.Wrap(err, "unexpected error reading Dockerfile")
}
return parser.Parse(br)
dockerfile, err := parser.Parse(br)
if err != nil {
return nil, errdefs.InvalidParameter(errors.Wrapf(err, "failed to parse %s", name))
}
return dockerfile, nil
}
func openAt(remote builder.Source, path string) (driver.File, error) {

View file

@ -467,6 +467,61 @@ RUN for g in $(seq 0 8); do dd if=/dev/urandom of=rnd bs=1K count=1 seek=$((1024
assert.Check(t, is.Contains(out.String(), "Successfully built"))
}
func TestBuildWithEmptyDockerfile(t *testing.T) {
ctx := context.TODO()
defer setupTest(t)()
tests := []struct {
name string
dockerfile string
expectedErr string
}{
{
name: "empty-dockerfile",
dockerfile: "",
expectedErr: "cannot be empty",
},
{
name: "empty-lines-dockerfile",
dockerfile: `
`,
expectedErr: "file with no instructions",
},
{
name: "comment-only-dockerfile",
dockerfile: `# this is a comment`,
expectedErr: "file with no instructions",
},
}
apiclient := testEnv.APIClient()
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
buf := bytes.NewBuffer(nil)
w := tar.NewWriter(buf)
writeTarRecord(t, w, "Dockerfile", tc.dockerfile)
err := w.Close()
assert.NilError(t, err)
_, err = apiclient.ImageBuild(ctx,
buf,
types.ImageBuildOptions{
Remove: true,
ForceRemove: true,
})
assert.Check(t, is.Contains(err.Error(), tc.expectedErr))
})
}
}
func writeTarRecord(t *testing.T, w *tar.Writer, fn, contents string) {
err := w.WriteHeader(&tar.Header{
Name: fn,

View file

@ -26,7 +26,7 @@ github.com/imdario/mergo v0.3.6
golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
# buildkit
github.com/moby/buildkit d9f75920678e35090025bb89344c5370e2efc8e7
github.com/moby/buildkit 34ff9c2366a878ada7938d2f9ede71741b0a220c
github.com/tonistiigi/fsutil 2862f6bc5ac9b97124e552a5c108230b38a1b0ca
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7

View file

@ -31,19 +31,15 @@ Introductory blog post https://blog.mobyproject.org/introducing-buildkit-17e056c
### Used by
[Moby & Docker](https://github.com/moby/moby/pull/37151)
BuildKit is used by the following projects:
[img](https://github.com/genuinetools/img)
[OpenFaaS Cloud](https://github.com/openfaas/openfaas-cloud)
[container build interface](https://github.com/containerbuilding/cbi)
[Knative Build Templates](https://github.com/knative/build-templates)
[boss](https://github.com/crosbymichael/boss)
[Rio](https://github.com/rancher/rio) (on roadmap)
- [Moby & Docker](https://github.com/moby/moby/pull/37151)
- [img](https://github.com/genuinetools/img)
- [OpenFaaS Cloud](https://github.com/openfaas/openfaas-cloud)
- [container build interface](https://github.com/containerbuilding/cbi)
- [Knative Build Templates](https://github.com/knative/build-templates)
- [boss](https://github.com/crosbymichael/boss)
- [Rio](https://github.com/rancher/rio) (on roadmap)
### Quick start
@ -252,7 +248,7 @@ export JAEGER_TRACE=0.0.0.0:6831
### Supported runc version
During development, BuildKit is tested with the version of runc that is being used by the containerd repository. Please refer to [runc.md](https://github.com/containerd/containerd/blob/v1.2.0-rc.1/RUNC.md) for more information.
During development, BuildKit is tested with the version of runc that is being used by the containerd repository. Please refer to [runc.md](https://github.com/containerd/containerd/blob/v1.2.1/RUNC.md) for more information.
### Running BuildKit without root privileges
@ -260,35 +256,5 @@ Please refer to [`docs/rootless.md`](docs/rootless.md).
### Contributing
Running tests:
```bash
make test
```
This runs all unit and integration tests in a containerized environment. Locally, every package can be tested separately with standard Go tools, but integration tests are skipped if local user doesn't have enough permissions or worker binaries are not installed.
```
# test a specific package only
make test TESTPKGS=./client
# run a specific test with all worker combinations
make test TESTPKGS=./client TESTFLAGS="--run /TestCallDiskUsage -v"
# run all integration tests with a specific worker
# supported workers: oci, oci-rootless, containerd, containerd-1.0
make test TESTPKGS=./client TESTFLAGS="--run //worker=containerd -v"
```
Updating vendored dependencies:
```bash
# update vendor.conf
make vendor
```
Validating your updates before submission:
```bash
make validate-all
```
Want to contribute to BuildKit? Awesome! You can find information about
contributing to this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md)

View file

@ -34,5 +34,21 @@ func dispatchSecret(m *instructions.Mount) (llb.RunOption, error) {
opts = append(opts, llb.SecretOptional)
}
if m.UID != nil || m.GID != nil || m.Mode != nil {
var uid, gid, mode int
if m.UID != nil {
uid = int(*m.UID)
}
if m.GID != nil {
gid = int(*m.GID)
}
if m.Mode != nil {
mode = int(*m.Mode)
} else {
mode = 0400
}
opts = append(opts, llb.SecretFileOpt(uid, gid, mode))
}
return llb.AddSecret(target, opts...), nil
}

View file

@ -15,7 +15,6 @@ func dispatchSSH(m *instructions.Mount) (llb.RunOption, error) {
opts := []llb.SSHOption{llb.SSHID(m.CacheID)}
if m.Target != "" {
// TODO(AkihiroSuda): support specifying permission bits
opts = append(opts, llb.SSHSocketTarget(m.Target))
}
@ -23,5 +22,21 @@ func dispatchSSH(m *instructions.Mount) (llb.RunOption, error) {
opts = append(opts, llb.SSHOptional)
}
if m.UID != nil || m.GID != nil || m.Mode != nil {
var uid, gid, mode int
if m.UID != nil {
uid = int(*m.UID)
}
if m.GID != nil {
gid = int(*m.GID)
}
if m.Mode != nil {
mode = int(*m.Mode)
} else {
mode = 0600
}
opts = append(opts, llb.SSHSocketOpt(m.Target, uid, gid, mode))
}
return llb.AddSSHSocket(opts...), nil
}

View file

@ -108,6 +108,9 @@ type Mount struct {
CacheID string
CacheSharing string
Required bool
Mode *uint64
UID *uint64
GID *uint64
}
func parseMount(value string) (*Mount, error) {
@ -180,11 +183,43 @@ func parseMount(value string) (*Mount, error) {
return nil, errors.Errorf("unsupported sharing value %q", value)
}
m.CacheSharing = strings.ToLower(value)
case "mode":
mode, err := strconv.ParseUint(value, 8, 32)
if err != nil {
return nil, errors.Errorf("invalid value %s for mode", value)
}
m.Mode = &mode
case "uid":
uid, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return nil, errors.Errorf("invalid value %s for uid", value)
}
m.UID = &uid
case "gid":
gid, err := strconv.ParseUint(value, 10, 32)
if err != nil {
return nil, errors.Errorf("invalid value %s for gid", value)
}
m.GID = &gid
default:
return nil, errors.Errorf("unexpected key '%s' in '%s'", key, field)
}
}
fileInfoAllowed := m.Type == MountTypeSecret || m.Type == MountTypeSSH
if m.Mode != nil && !fileInfoAllowed {
return nil, errors.Errorf("mode not allowed for %q type mounts")
}
if m.UID != nil && !fileInfoAllowed {
return nil, errors.Errorf("uid not allowed for %q type mounts")
}
if m.GID != nil && !fileInfoAllowed {
return nil, errors.Errorf("gid not allowed for %q type mounts")
}
if roAuto {
if m.Type == MountTypeCache {
m.ReadOnly = false

View file

@ -275,6 +275,11 @@ func Parse(rwc io.Reader) (*Result, error) {
if len(warnings) > 0 {
warnings = append(warnings, "[WARNING]: Empty continuation lines will become errors in a future release.")
}
if root.StartLine < 0 {
return nil, errors.New("file with no instructions.")
}
return &Result{
AST: root,
Warnings: warnings,

View file

@ -96,7 +96,7 @@ func (cs *containerdSnapshotter) release() error {
defer cs.mu.Unlock()
var err error
for _, f := range cs.releasers {
if err1 := f(); err != nil && err == nil {
if err1 := f(); err1 != nil && err == nil {
err = err1
}
}

View file

@ -331,7 +331,7 @@ func (sm *sshMountInstance) Mount() ([]mount.Mount, error) {
ID: sm.sm.mount.SSHOpt.ID,
UID: int(sm.sm.mount.SSHOpt.Uid),
GID: int(sm.sm.mount.SSHOpt.Gid),
Mode: int(sm.sm.mount.SSHOpt.Mode),
Mode: int(sm.sm.mount.SSHOpt.Mode & 0777),
})
if err != nil {
cancel()
@ -447,7 +447,7 @@ func (sm *secretMountInstance) Mount() ([]mount.Mount, error) {
return nil, err
}
if err := os.Chmod(fp, os.FileMode(sm.sm.mount.SecretOpt.Mode)); err != nil {
if err := os.Chmod(fp, os.FileMode(sm.sm.mount.SecretOpt.Mode&0777)); err != nil {
return nil, err
}

View file

@ -6,10 +6,10 @@ github.com/davecgh/go-spew v1.1.0
github.com/pmezard/go-difflib v1.0.0
golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2
github.com/containerd/containerd 1a5f9a3434ac53c0e9d27093ecc588e0c281c333
github.com/containerd/containerd 47b328aab79146a9e81e37704db60e7e04a09256
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
github.com/sirupsen/logrus v1.0.0
github.com/sirupsen/logrus v1.0.3
google.golang.org/grpc v1.12.0
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
golang.org/x/net 0ed95abb35c445290478a5348a7b38bb154135fd
@ -18,7 +18,7 @@ github.com/gogo/googleapis b23578765ee54ff6bceff57f397d833bf4ca6869
github.com/golang/protobuf v1.1.0
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
github.com/opencontainers/image-spec v1.0.1
github.com/opencontainers/runc a00bf0190895aa465a5fbed0268888e2c8ddfe85
github.com/opencontainers/runc 96ec2177ae841256168fcf76954f7177af9446eb
github.com/Microsoft/go-winio v0.4.11
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
@ -30,7 +30,7 @@ github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
github.com/Microsoft/hcsshim v0.7.9
golang.org/x/crypto 0709b304e793a5edb4a2c0145f281ecdc20838a4
github.com/containerd/cri 8506fe836677cc3bb23a16b68145128243d843b5 # release/1.2 branch
github.com/containerd/cri f913714917d2456d7e65a0be84962b1ce8acb487 # release/1.2 branch
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b