From c4b6cd515a902f2a098974d7a02dbc498b7ffb54 Mon Sep 17 00:00:00 2001 From: Ilya Lesikov Date: Mon, 17 Oct 2022 20:15:28 +0300 Subject: [PATCH] fix(staged-dockerfile): fix docker ignore path matcher Signed-off-by: Ilya Lesikov --- pkg/build/image/build_context_archive.go | 72 ++--------------- pkg/build/image/dockerfile.go | 99 ++++++++++++++---------- 2 files changed, 64 insertions(+), 107 deletions(-) diff --git a/pkg/build/image/build_context_archive.go b/pkg/build/image/build_context_archive.go index d47b35419f..3a26aeb9d7 100644 --- a/pkg/build/image/build_context_archive.go +++ b/pkg/build/image/build_context_archive.go @@ -1,15 +1,12 @@ package image import ( - "bytes" "context" "fmt" "io/ioutil" "os" "path/filepath" - "github.com/docker/docker/builder/dockerignore" - "github.com/werf/logboek" "github.com/werf/werf/pkg/container_backend" "github.com/werf/werf/pkg/context_manager" @@ -36,17 +33,18 @@ type BuildContextArchive struct { func (a *BuildContextArchive) Create(ctx context.Context, opts container_backend.BuildContextArchiveCreateOptions) error { contextPathRelativeToGitWorkTree := filepath.Join(a.giterminismMgr.RelativeToGitProjectDir(), opts.ContextGitSubDir) - pathMatcher := path_matcher.NewPathMatcher(path_matcher.PathMatcherOptions{BasePath: contextPathRelativeToGitWorkTree}) - if dockerIgnorePathMatcher, err := createDockerIgnorePathMatcher(ctx, a.giterminismMgr, opts.ContextGitSubDir, opts.DockerfileRelToContextPath); err != nil { + dockerIgnorePathMatcher, err := createDockerIgnorePathMatcher(ctx, a.giterminismMgr, opts.ContextGitSubDir, opts.DockerfileRelToContextPath) + if err != nil { return fmt.Errorf("unable to create dockerignore path matcher: %w", err) - } else if dockerIgnorePathMatcher != nil { - pathMatcher = path_matcher.NewMultiPathMatcher(pathMatcher, dockerIgnorePathMatcher) } archive, err := a.giterminismMgr.LocalGitRepo().GetOrCreateArchive(ctx, git_repo.ArchiveOptions{ - PathScope: contextPathRelativeToGitWorkTree, - PathMatcher: pathMatcher, - Commit: a.giterminismMgr.HeadCommit(), + PathScope: contextPathRelativeToGitWorkTree, + PathMatcher: path_matcher.NewMultiPathMatcher(path_matcher.NewPathMatcher( + path_matcher.PathMatcherOptions{BasePath: contextPathRelativeToGitWorkTree}), + dockerIgnorePathMatcher, + ), + Commit: a.giterminismMgr.HeadCommit(), }) if err != nil { return fmt.Errorf("unable to get or create archive: %w", err) @@ -107,57 +105,3 @@ func (a *BuildContextArchive) CleanupExtractedDir(ctx context.Context) { logboek.Context(ctx).Warn().LogF("WARNING: unable to remove extracted context dir %q: %s", a.extractionDir, err) } } - -// Might return nil. -func createDockerIgnorePathMatcher(ctx context.Context, giterminismMgr giterminism_manager.Interface, contextGitSubDir, dockerfileRelToContextPath string) (path_matcher.PathMatcher, error) { - dockerfileRelToGitPath := filepath.Join(contextGitSubDir, dockerfileRelToContextPath) - - var dockerIgnorePatterns []string - for _, dockerIgnoreRelToContextPath := range []string{ - dockerfileRelToContextPath + ".dockerignore", - ".dockerignore", - } { - dockerIgnoreRelToGitPath := filepath.Join(contextGitSubDir, dockerIgnoreRelToContextPath) - if exist, err := giterminismMgr.FileReader().IsDockerignoreExistAnywhere(ctx, dockerIgnoreRelToGitPath); err != nil { - return nil, err - } else if !exist { - continue - } - - dockerIgnore, err := giterminismMgr.FileReader().ReadDockerignore(ctx, dockerIgnoreRelToGitPath) - if err != nil { - return nil, err - } - - r := bytes.NewReader(dockerIgnore) - dockerIgnorePatterns, err = dockerignore.ReadAll(r) - if err != nil { - return nil, fmt.Errorf("unable to read %q file: %w", dockerIgnoreRelToContextPath, err) - } - - break - } - - if dockerIgnorePatterns == nil { - return nil, nil - } - - dockerIgnorePathMatcher := path_matcher.NewPathMatcher(path_matcher.PathMatcherOptions{ - BasePath: filepath.Join(giterminismMgr.RelativeToGitProjectDir(), contextGitSubDir), - DockerignorePatterns: dockerIgnorePatterns, - }) - - if !dockerIgnorePathMatcher.IsPathMatched(dockerfileRelToGitPath) { - logboek.Context(ctx).Warn().LogLn("WARNING: There is no way to ignore the Dockerfile due to docker limitation when building an image for a compressed context that reads from STDIN.") - logboek.Context(ctx).Warn().LogF("WARNING: To hide this message, remove the Dockerfile ignore rule or add an exception rule.\n") - - exceptionRule := "!" + dockerfileRelToContextPath - dockerIgnorePatterns = append(dockerIgnorePatterns, exceptionRule) - dockerIgnorePathMatcher = path_matcher.NewPathMatcher(path_matcher.PathMatcherOptions{ - BasePath: filepath.Join(giterminismMgr.RelativeToGitProjectDir(), contextGitSubDir), - DockerignorePatterns: dockerIgnorePatterns, - }) - } - - return dockerIgnorePathMatcher, nil -} diff --git a/pkg/build/image/dockerfile.go b/pkg/build/image/dockerfile.go index b465188344..a59047d14e 100644 --- a/pkg/build/image/dockerfile.go +++ b/pkg/build/image/dockerfile.go @@ -18,6 +18,7 @@ import ( "github.com/werf/werf/pkg/dockerfile" "github.com/werf/werf/pkg/dockerfile/frontend" dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction" + "github.com/werf/werf/pkg/giterminism_manager" "github.com/werf/werf/pkg/path_matcher" "github.com/werf/werf/pkg/util" ) @@ -121,54 +122,17 @@ func mapLegacyDockerfileToImage(ctx context.Context, dockerfileImageConfig *conf } } + dockerIgnorePathMatcher, err := createDockerIgnorePathMatcher(ctx, opts.GiterminismManager, dockerfileImageConfig.Context, dockerfileImageConfig.Dockerfile) + if err != nil { + return nil, fmt.Errorf("unable to create dockerignore path matcher: %w", err) + } + relDockerfilePath := filepath.Join(dockerfileImageConfig.Context, dockerfileImageConfig.Dockerfile) dockerfileData, err := opts.GiterminismManager.FileReader().ReadDockerfile(ctx, relDockerfilePath) if err != nil { return nil, err } - var relDockerignorePath string - var dockerignorePatterns []string - for _, relContextDockerignorePath := range []string{ - dockerfileImageConfig.Dockerfile + ".dockerignore", - ".dockerignore", - } { - relDockerignorePath = filepath.Join(dockerfileImageConfig.Context, relContextDockerignorePath) - if exist, err := opts.GiterminismManager.FileReader().IsDockerignoreExistAnywhere(ctx, relDockerignorePath); err != nil { - return nil, err - } else if exist { - dockerignoreData, err := opts.GiterminismManager.FileReader().ReadDockerignore(ctx, relDockerignorePath) - if err != nil { - return nil, err - } - - r := bytes.NewReader(dockerignoreData) - dockerignorePatterns, err = dockerignore.ReadAll(r) - if err != nil { - return nil, fmt.Errorf("unable to read %q file: %w", relContextDockerignorePath, err) - } - - break - } - } - - dockerignorePathMatcher := path_matcher.NewPathMatcher(path_matcher.PathMatcherOptions{ - BasePath: filepath.Join(opts.GiterminismManager.RelativeToGitProjectDir(), dockerfileImageConfig.Context), - DockerignorePatterns: dockerignorePatterns, - }) - - if !dockerignorePathMatcher.IsPathMatched(relDockerfilePath) { - exceptionRule := "!" + dockerfileImageConfig.Dockerfile - logboek.Context(ctx).Warn().LogLn("WARNING: There is no way to ignore the Dockerfile due to docker limitation when building an image for a compressed context that reads from STDIN.") - logboek.Context(ctx).Warn().LogF("WARNING: To hide this message, remove the Dockerfile ignore rule from the %q or add an exception rule %q.\n", relDockerignorePath, exceptionRule) - - dockerignorePatterns = append(dockerignorePatterns, exceptionRule) - dockerignorePathMatcher = path_matcher.NewPathMatcher(path_matcher.PathMatcherOptions{ - BasePath: filepath.Join(opts.GiterminismManager.RelativeToGitProjectDir(), dockerfileImageConfig.Context), - DockerignorePatterns: dockerignorePatterns, - }) - } - p, err := parser.Parse(bytes.NewReader(dockerfileData)) if err != nil { return nil, err @@ -211,7 +175,7 @@ func mapLegacyDockerfileToImage(ctx context.Context, dockerfileImageConfig *conf dockerfileImageConfig.SSH, ), ds, - stage.NewContextChecksum(dockerignorePathMatcher), + stage.NewContextChecksum(dockerIgnorePathMatcher), baseStageOptions, dockerfileImageConfig.Dependencies, ) @@ -222,3 +186,52 @@ func mapLegacyDockerfileToImage(ctx context.Context, dockerfileImageConfig *conf return img, nil } + +func createDockerIgnorePathMatcher(ctx context.Context, giterminismMgr giterminism_manager.Interface, contextGitSubDir, dockerfileRelToContextPath string) (path_matcher.PathMatcher, error) { + dockerfileRelToGitPath := filepath.Join(contextGitSubDir, dockerfileRelToContextPath) + + var dockerIgnorePatterns []string + for _, dockerIgnoreRelToContextPath := range []string{ + dockerfileRelToContextPath + ".dockerignore", + ".dockerignore", + } { + dockerIgnoreRelToGitPath := filepath.Join(contextGitSubDir, dockerIgnoreRelToContextPath) + if exist, err := giterminismMgr.FileReader().IsDockerignoreExistAnywhere(ctx, dockerIgnoreRelToGitPath); err != nil { + return nil, err + } else if !exist { + continue + } + + dockerIgnore, err := giterminismMgr.FileReader().ReadDockerignore(ctx, dockerIgnoreRelToGitPath) + if err != nil { + return nil, err + } + + r := bytes.NewReader(dockerIgnore) + dockerIgnorePatterns, err = dockerignore.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("unable to read %q file: %w", dockerIgnoreRelToContextPath, err) + } + + break + } + + dockerIgnorePathMatcher := path_matcher.NewPathMatcher(path_matcher.PathMatcherOptions{ + BasePath: filepath.Join(giterminismMgr.RelativeToGitProjectDir(), contextGitSubDir), + DockerignorePatterns: dockerIgnorePatterns, + }) + + if !dockerIgnorePathMatcher.IsPathMatched(dockerfileRelToGitPath) { + logboek.Context(ctx).Warn().LogLn("WARNING: There is no way to ignore the Dockerfile due to docker limitation when building an image for a compressed context that reads from STDIN.") + logboek.Context(ctx).Warn().LogF("WARNING: To hide this message, remove the Dockerfile ignore rule or add an exception rule.\n") + + exceptionRule := "!" + dockerfileRelToContextPath + dockerIgnorePatterns = append(dockerIgnorePatterns, exceptionRule) + dockerIgnorePathMatcher = path_matcher.NewPathMatcher(path_matcher.PathMatcherOptions{ + BasePath: filepath.Join(giterminismMgr.RelativeToGitProjectDir(), contextGitSubDir), + DockerignorePatterns: dockerIgnorePatterns, + }) + } + + return dockerIgnorePathMatcher, nil +}