-
-
Notifications
You must be signed in to change notification settings - Fork 256
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#218] #IMPLEMENT 'assemblyName: DotNet.Testcontainers; function: Doc…
…kerIgnoreFile' {Add .dockerignore support.}
- Loading branch information
1 parent
87ca21e
commit f6689ca
Showing
24 changed files
with
499 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
**/*.md |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
src/DotNet.Testcontainers.Tests/Fixtures/IgnoreFileTestFixture.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
namespace DotNet.Testcontainers.Tests.Fixtures | ||
{ | ||
using DotNet.Testcontainers.Images.Archives; | ||
using Xunit; | ||
|
||
internal class IgnoreFileTestFixture : TheoryData<IgnoreFile, string, bool> | ||
{ | ||
private static readonly IgnoreFile IgnoreNonRecursiveFiles = new IgnoreFile("*/temp*"); | ||
|
||
private static readonly IgnoreFile IgnoreNonRecursiveNestedFiles = new IgnoreFile("*/*/temp*"); | ||
|
||
private static readonly IgnoreFile IgnoreRecursiveFiles = new IgnoreFile("**/*.txt"); | ||
|
||
private static readonly IgnoreFile IgnoreSingleCharacterFiles = new IgnoreFile("temp?"); | ||
|
||
private static readonly IgnoreFile IgnoreExceptionFiles = new IgnoreFile("*.md", "!README*.md", "README-secret.md"); | ||
|
||
public IgnoreFileTestFixture() | ||
{ | ||
this.Add(IgnoreNonRecursiveFiles, "lipsum/temp", false); | ||
this.Add(IgnoreNonRecursiveFiles, "lipsum/temp.txt", false); | ||
this.Add(IgnoreNonRecursiveFiles, "lipsum/lorem/temp", true); | ||
this.Add(IgnoreNonRecursiveNestedFiles, "lipsum/lorem/temp", false); | ||
this.Add(IgnoreNonRecursiveNestedFiles, "lipsum/lorem/temp.txt", false); | ||
this.Add(IgnoreNonRecursiveNestedFiles, "lipsum/temp", true); | ||
this.Add(IgnoreNonRecursiveNestedFiles, "lipsum/lorem/lipsum/temp", true); | ||
this.Add(IgnoreRecursiveFiles, "lipsum.txt", false); | ||
this.Add(IgnoreRecursiveFiles, "lorem/lipsum/lorem/lipsum.txt", false); | ||
this.Add(IgnoreRecursiveFiles, "lorem/lipsum/lorem.txt", false); | ||
this.Add(IgnoreRecursiveFiles, "lorem/lipsum.txt", false); | ||
this.Add(IgnoreRecursiveFiles, "lorem/lipsum/lipsum.config", true); | ||
this.Add(IgnoreRecursiveFiles, "lorem/lipsum.config", true); | ||
this.Add(IgnoreSingleCharacterFiles, "temp", false); | ||
this.Add(IgnoreSingleCharacterFiles, "temp1", false); | ||
this.Add(IgnoreSingleCharacterFiles, "temp12", true); | ||
this.Add(IgnoreSingleCharacterFiles, "lipsum/temp", true); | ||
this.Add(IgnoreExceptionFiles, "CODE_OF_CONDUCT.md", false); | ||
this.Add(IgnoreExceptionFiles, "README-secret.md", false); | ||
this.Add(IgnoreExceptionFiles, "README.md", true); | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/DotNet.Testcontainers.Tests/Unit/Images/IgnoreFileTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace DotNet.Testcontainers.Tests.Unit.Images | ||
{ | ||
using DotNet.Testcontainers.Images.Archives; | ||
using DotNet.Testcontainers.Tests.Fixtures; | ||
using Xunit; | ||
|
||
public class IgnoreFileTest | ||
{ | ||
[Theory] | ||
[ClassData(typeof(IgnoreFileTestFixture))] | ||
internal void AcceptOrDenyNonRecursivePatterns(IgnoreFile ignoreFile, string path, bool expected) | ||
{ | ||
Assert.Equal(expected, ignoreFile.Accepts(path)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,10 @@ | ||
namespace DotNet.Testcontainers.Clients | ||
{ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
using DotNet.Testcontainers.Services; | ||
|
||
internal static class DockerApiEndpoint | ||
{ | ||
#pragma warning disable S1075 | ||
|
||
private static readonly Uri Unix = new Uri("unix:/var/run/docker.sock"); | ||
|
||
private static readonly Uri Windows = new Uri("npipe://./pipe/docker_engine"); | ||
|
||
#pragma warning restore S1075 | ||
|
||
public static readonly Uri Local = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Windows : Unix; | ||
public static Uri Local => TestcontainersHostService.GetService<IOperatingSystem>().DockerApiEndpoint; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/DotNet.Testcontainers/Images/Archives/DockerIgnoreFile.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
namespace DotNet.Testcontainers.Images.Archives | ||
{ | ||
using System.IO; | ||
using System.Linq; | ||
|
||
/// <summary> | ||
/// A implementation of <see cref="IgnoreFile" /> that uses the patterns of the .dockerignore file. | ||
/// </summary> | ||
internal sealed class DockerIgnoreFile : IgnoreFile | ||
{ | ||
/// <summary> | ||
/// Creates an instance of <see cref="DockerIgnoreFile" /> from the specified directory and ignore files. | ||
/// </summary> | ||
/// <param name="dockerIgnoreFileDirectory">Directory that contains all docker configuration files.</param> | ||
/// <param name="dockerIgnoreFile">.dockerignore file name.</param> | ||
public DockerIgnoreFile(string dockerIgnoreFileDirectory, string dockerIgnoreFile) | ||
: this(new DirectoryInfo(dockerIgnoreFileDirectory), dockerIgnoreFile) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Creates an instance of <see cref="DockerIgnoreFile" /> from the specified directory and ignore files. | ||
/// </summary> | ||
/// <param name="dockerIgnoreFileDirectory">Directory that contains all docker configuration files.</param> | ||
/// <param name="dockerIgnoreFile">.dockerignore file name.</param> | ||
public DockerIgnoreFile(DirectoryInfo dockerIgnoreFileDirectory, string dockerIgnoreFile) | ||
: base(dockerIgnoreFileDirectory.GetFiles(dockerIgnoreFile, SearchOption.TopDirectoryOnly).Any() | ||
? File.ReadLines(Path.Combine(dockerIgnoreFileDirectory.FullName, dockerIgnoreFile)).Concat(new[] { dockerIgnoreFile }).ToArray() | ||
: new[] { dockerIgnoreFile }) | ||
{ | ||
} | ||
} | ||
} |
108 changes: 71 additions & 37 deletions
108
src/DotNet.Testcontainers/Images/Archives/DockerfileArchive.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,109 @@ | ||
namespace DotNet.Testcontainers.Images.Archives | ||
namespace DotNet.Testcontainers.Images.Archives | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using DotNet.Testcontainers.Services; | ||
using ICSharpCode.SharpZipLib.Tar; | ||
|
||
/// <summary> | ||
/// Generates a tar archive with docker configuration files. The generated tar archive can be used to build a docker image. | ||
/// </summary> | ||
internal sealed class DockerfileArchive : ITarArchive | ||
{ | ||
private static readonly char[] TrimLeadingChars = { '/' }; | ||
private static readonly IOperatingSystem os; | ||
|
||
public DockerfileArchive(string baseDirectory) : this(new DirectoryInfo(baseDirectory)) | ||
private readonly DirectoryInfo dockerfileDirectory; | ||
|
||
private readonly IDockerImage image; | ||
|
||
static DockerfileArchive() | ||
{ | ||
os = new Unix(); | ||
} | ||
|
||
public DockerfileArchive(DirectoryInfo baseDirectory) | ||
/// <summary> | ||
/// Creates an instance of <see cref="DockerfileArchive" /> for the specified parameters. | ||
/// </summary> | ||
/// <param name="dockerfileDirectory">Directory to docker configuration files.</param> | ||
/// <param name="dockerfile">Name of the dockerfile, which is necessary to start the docker build.</param> | ||
/// <param name="image">Docker image information to create the tar archive for.</param> | ||
public DockerfileArchive(string dockerfileDirectory, string dockerfile, IDockerImage image) | ||
: this(new DirectoryInfo(dockerfileDirectory), dockerfile, image) | ||
{ | ||
this.BaseDirectory = baseDirectory; | ||
|
||
this.DockerfileArchiveFile = new FileInfo($"{Path.GetTempPath()}/Dockerfile.tar"); | ||
} | ||
|
||
if (!this.BaseDirectory.Exists) | ||
/// <summary> | ||
/// Creates an instance of <see cref="DockerfileArchive" /> for the specified parameters. | ||
/// </summary> | ||
/// <param name="dockerfileDirectory">Directory to docker configuration files.</param> | ||
/// <param name="dockerfile">Name of the dockerfile, which is necessary to start the docker build.</param> | ||
/// <param name="image">Docker image information to create the tar archive for.</param> | ||
/// <exception cref="ArgumentException">Will be thrown if the dockerfile directory does not exist or the directory does not contain a dockerfile.</exception> | ||
public DockerfileArchive(DirectoryInfo dockerfileDirectory, string dockerfile, IDockerImage image) | ||
{ | ||
if (!dockerfileDirectory.Exists) | ||
{ | ||
throw new ArgumentException($"Directory '{this.BaseDirectory.FullName}' does not exist."); | ||
throw new ArgumentException($"Directory '{dockerfileDirectory.FullName}' does not exist."); | ||
} | ||
|
||
if (!this.BaseDirectory.GetFiles().Any(file => "Dockerfile".Equals(file.Name))) | ||
if (!dockerfileDirectory.GetFiles(dockerfile, SearchOption.TopDirectoryOnly).Any()) | ||
{ | ||
throw new ArgumentException($"Dockerfile does not exist in '{this.BaseDirectory.FullName}'."); | ||
throw new ArgumentException($"{dockerfile} does not exist in '{dockerfileDirectory.FullName}'."); | ||
} | ||
} | ||
|
||
public DirectoryInfo BaseDirectory { get; } | ||
|
||
public FileInfo DockerfileArchiveFile { get; } | ||
this.dockerfileDirectory = dockerfileDirectory; | ||
this.image = image; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public string Tar() | ||
{ | ||
using (var dockerfileArchiveStream = File.Create(this.DockerfileArchiveFile.FullName)) | ||
var dockerfileArchiveName = Regex.Replace(this.image.FullName, "[^a-zA-Z0-9]", "-").ToLowerInvariant(); | ||
|
||
var dockerfileArchivePath = Path.Combine(Path.GetTempPath(), $"{dockerfileArchiveName}.tar"); | ||
|
||
var dockerIgnoreFile = new DockerIgnoreFile(this.dockerfileDirectory.FullName, ".dockerignore"); | ||
|
||
using (var stream = new FileStream(dockerfileArchivePath, FileMode.Create)) | ||
{ | ||
using (var dockerfileArchive = TarArchive.CreateOutputTarArchive(dockerfileArchiveStream)) | ||
using (var tarArchive = TarArchive.CreateOutputTarArchive(stream)) | ||
{ | ||
dockerfileArchive.RootPath = this.BaseDirectory.FullName; | ||
tarArchive.RootPath = os.NormalizePath(this.dockerfileDirectory.FullName); | ||
|
||
void Tar(string baseDirectory) | ||
foreach (var file in GetFiles(this.dockerfileDirectory.FullName)) | ||
{ | ||
baseDirectory = baseDirectory.Replace('\\', '/'); | ||
|
||
void WriteEntry(string entry) | ||
{ | ||
entry = entry.Replace('\\', '/'); | ||
|
||
var tarEntry = TarEntry.CreateEntryFromFile(entry); | ||
tarEntry.Name = entry.Replace(dockerfileArchive.RootPath, string.Empty).TrimStart(TrimLeadingChars); | ||
dockerfileArchive.WriteEntry(tarEntry, File.Exists(entry)); | ||
} | ||
var relativePath = file.Substring(tarArchive.RootPath.Length + 1); | ||
|
||
if (!dockerfileArchive.RootPath.Equals(baseDirectory)) | ||
if (dockerIgnoreFile.Denies(relativePath)) | ||
{ | ||
WriteEntry(baseDirectory); | ||
continue; | ||
} | ||
|
||
Directory.GetFiles(baseDirectory).ToList().ForEach(WriteEntry); | ||
|
||
Directory.GetDirectories(baseDirectory).ToList().ForEach(Tar); | ||
var tarEntry = TarEntry.CreateEntryFromFile(file); | ||
tarEntry.Name = relativePath; | ||
tarArchive.WriteEntry(tarEntry, true); | ||
} | ||
|
||
Tar(this.BaseDirectory.FullName); | ||
} | ||
} | ||
|
||
return this.DockerfileArchiveFile.FullName; | ||
return dockerfileArchivePath; | ||
} | ||
|
||
/// <summary> | ||
/// Gets all accepted docker archive files. | ||
/// </summary> | ||
/// <param name="directory">Directory to docker configuration files.</param> | ||
/// <returns>Returns a list with all accepted docker archive files.</returns> | ||
private static IEnumerable<string> GetFiles(string directory) | ||
{ | ||
return Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories) | ||
.AsParallel() | ||
.Select(Path.GetFullPath) | ||
.Select(os.NormalizePath) | ||
.ToArray(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,14 @@ | ||
namespace DotNet.Testcontainers.Images.Archives | ||
{ | ||
/// <summary> | ||
/// Collects files into one tar archive file. | ||
/// </summary> | ||
internal interface ITarArchive | ||
{ | ||
/// <summary> | ||
/// Creates a tar archive file. | ||
/// </summary> | ||
/// <returns>Path to the created archive file.</returns> | ||
string Tar(); | ||
} | ||
} |
Oops, something went wrong.