mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
1b6abe6f43
Downgrade go-dockerclient to before it used the docker packages. Remove new docker packages from vendor. Remove gotty client from vendor, which can't build on solaris at all.
118 lines
3.3 KiB
Go
118 lines
3.3 KiB
Go
// Copyright 2015 go-dockerclient authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package docker
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/archive"
|
|
"github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/fileutils"
|
|
)
|
|
|
|
func createTarStream(srcPath, dockerfilePath string) (io.ReadCloser, error) {
|
|
excludes, err := parseDockerignore(srcPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
includes := []string{"."}
|
|
|
|
// If .dockerignore mentions .dockerignore or the Dockerfile
|
|
// then make sure we send both files over to the daemon
|
|
// because Dockerfile is, obviously, needed no matter what, and
|
|
// .dockerignore is needed to know if either one needs to be
|
|
// removed. The deamon will remove them for us, if needed, after it
|
|
// parses the Dockerfile.
|
|
//
|
|
// https://github.com/docker/docker/issues/8330
|
|
//
|
|
forceIncludeFiles := []string{".dockerignore", dockerfilePath}
|
|
|
|
for _, includeFile := range forceIncludeFiles {
|
|
if includeFile == "" {
|
|
continue
|
|
}
|
|
keepThem, err := fileutils.Matches(includeFile, excludes)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot match .dockerfile: '%s', error: %s", includeFile, err)
|
|
}
|
|
if keepThem {
|
|
includes = append(includes, includeFile)
|
|
}
|
|
}
|
|
|
|
if err := validateContextDirectory(srcPath, excludes); err != nil {
|
|
return nil, err
|
|
}
|
|
tarOpts := &archive.TarOptions{
|
|
ExcludePatterns: excludes,
|
|
IncludeFiles: includes,
|
|
Compression: archive.Uncompressed,
|
|
NoLchown: true,
|
|
}
|
|
return archive.TarWithOptions(srcPath, tarOpts)
|
|
}
|
|
|
|
// validateContextDirectory checks if all the contents of the directory
|
|
// can be read and returns an error if some files can't be read.
|
|
// Symlinks which point to non-existing files don't trigger an error
|
|
func validateContextDirectory(srcPath string, excludes []string) error {
|
|
return filepath.Walk(filepath.Join(srcPath, "."), func(filePath string, f os.FileInfo, err error) error {
|
|
// skip this directory/file if it's not in the path, it won't get added to the context
|
|
if relFilePath, err := filepath.Rel(srcPath, filePath); err != nil {
|
|
return err
|
|
} else if skip, err := fileutils.Matches(relFilePath, excludes); err != nil {
|
|
return err
|
|
} else if skip {
|
|
if f.IsDir() {
|
|
return filepath.SkipDir
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if err != nil {
|
|
if os.IsPermission(err) {
|
|
return fmt.Errorf("can't stat '%s'", filePath)
|
|
}
|
|
if os.IsNotExist(err) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
// skip checking if symlinks point to non-existing files, such symlinks can be useful
|
|
// also skip named pipes, because they hanging on open
|
|
if f.Mode()&(os.ModeSymlink|os.ModeNamedPipe) != 0 {
|
|
return nil
|
|
}
|
|
|
|
if !f.IsDir() {
|
|
currentFile, err := os.Open(filePath)
|
|
if err != nil && os.IsPermission(err) {
|
|
return fmt.Errorf("no permission to read from '%s'", filePath)
|
|
}
|
|
currentFile.Close()
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func parseDockerignore(root string) ([]string, error) {
|
|
var excludes []string
|
|
ignore, err := ioutil.ReadFile(path.Join(root, ".dockerignore"))
|
|
if err != nil && !os.IsNotExist(err) {
|
|
return excludes, fmt.Errorf("error reading .dockerignore: '%s'", err)
|
|
}
|
|
excludes = strings.Split(string(ignore), "\n")
|
|
|
|
return excludes, nil
|
|
}
|