Skip to content

Commit

Permalink
Fixed an issue where subdirectories were not added to the Dockerfile …
Browse files Browse the repository at this point in the history
…archive, closes #64 #66.
  • Loading branch information
HofmeisterAn committed Jun 9, 2019
1 parent 5cbe737 commit 1816910
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
<PackageReference Include="xunit" Version="2.4.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DotNet.Testcontainers\DotNet.Testcontainers.csproj" />
<ProjectReference Include="../DotNet.Testcontainers/DotNet.Testcontainers.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="..\xunit.runner.json">
<None Include="../xunit.runner.json">
<Link>xunit.runner.json</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="Assets\Dockerfile">
<None Include="Assets/**/*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Expand Down
19 changes: 19 additions & 0 deletions src/DotNet.Testcontainers.Tests/Unit/ImageFromDockerfileTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,49 @@ namespace DotNet.Testcontainers.Tests.Unit
using System;
using System.IO;
using System.Threading.Tasks;
using DotNet.Testcontainers.Core;
using DotNet.Testcontainers.Core.Builder;
using Xunit;

public class ImageFromDockerfileTest
{
[Fact]
public void DockerfileArchiveTar()
{
// Given
var dockerFileArchive = new DockerfileArchive("./Assets");

using (var file = new FileInfo(dockerFileArchive.Tar()).OpenRead())
{
Assert.Equal("34BDCA7AB58F0BBDB64AA0178D69CD6E14586838", BitConverter.ToString(System.Security.Cryptography.SHA1.Create().ComputeHash(file)).Replace("-", string.Empty));
}
}

[Fact]
public async Task DockerfileDoesNotExist()
{
// Given
var exception = await Assert.ThrowsAsync<ArgumentException>(() =>
new ImageFromDockerfileBuilder()
.WithDockerfileDirectory(".")
.Build());

// When
// Then
Assert.Equal($"Dockerfile does not exist in '{new DirectoryInfo(".").FullName}'.", exception.Message);
}

[Fact]
public async Task DockerfileDirectoryDoesNotExist()
{
// Given
var exception = await Assert.ThrowsAsync<ArgumentException>(() =>
new ImageFromDockerfileBuilder()
.WithDockerfileDirectory("DoesNotExist")
.Build());

// When
// Then
Assert.Equal($"Directory '{new DirectoryInfo("DoesNotExist").FullName}' does not exist.", exception.Message);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ await Assert.ThrowsAsync<TimeoutException>(async () =>
});
}

public Task<bool> Until(string id)
public async Task<bool> Until(string id)
{
Task.Delay(TimeSpan.FromSeconds(1));
return Task.Run(() => true);
await Task.Delay(TimeSpan.FromSeconds(1));
return true;
}

public Task<bool> While(string id)
public async Task<bool> While(string id)
{
Task.Delay(TimeSpan.FromSeconds(1));
return Task.Run(() => false);
await Task.Delay(TimeSpan.FromSeconds(1));
return false;
}
}
}
Expand Down
76 changes: 11 additions & 65 deletions src/DotNet.Testcontainers/Clients/TestcontainersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ namespace DotNet.Testcontainers.Clients
{
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet.Models;
using DotNet.Testcontainers.Core;
using DotNet.Testcontainers.Core.Mapper;
using DotNet.Testcontainers.Core.Models;
using DotNet.Testcontainers.Core.Wait;
using DotNet.Testcontainers.Diagnostics;
using ICSharpCode.SharpZipLib.Tar;

internal class TestcontainersClient : DockerApiClient, ITestcontainersClient
{
Expand Down Expand Up @@ -77,19 +76,22 @@ public async Task ExecAsync(string id, params string[] command)

public async Task<string> BuildAsync(ImageFromDockerfileConfiguration config)
{
var dockerfileDirectory = new DirectoryInfo(config.DockerfileDirectory);
var dockerFileArchive = new DockerfileArchive(config.DockerfileDirectory);

if (!dockerfileDirectory.Exists)
await MetaDataClientImages.Instance.ExistsWithNameAsync(config.Image).ContinueWith(async imageExists =>
{
throw new ArgumentException($"Directory '{dockerfileDirectory.FullName}' does not exist.");
}
if (!await imageExists && config.DeleteIfExists)
{
await Docker.Images.DeleteImageAsync(config.Image, new ImageDeleteParameters { Force = true });
}
});

if (!dockerfileDirectory.GetFiles().Any(file => "Dockerfile".Equals(file.Name)))
using (var stream = new FileStream(dockerFileArchive.Tar(), FileMode.Open))
{
throw new ArgumentException($"Dockerfile does not exist in '{dockerfileDirectory.FullName}'.");
await Docker.Images.BuildImageFromDockerfileAsync(stream, new ImageBuildParameters { Dockerfile = "Dockerfile", Tags = new[] { config.Image } });
}

return await this.BuildInternalAsync(config);
return config.Image;
}

public async Task<string> RunAsync(TestcontainersConfiguration config)
Expand Down Expand Up @@ -148,61 +150,5 @@ public async Task<string> RunAsync(TestcontainersConfiguration config)

return (await Docker.Containers.CreateContainerAsync(createParameters)).ID;
}

private static string CreateDockerfileArchive(string dockerfileRootDirectory)
{
var dockerfileArchiveFile = $"{Path.GetTempPath()}/Dockerfile.tar";

using (var dockerfileArchiveStream = File.Create(dockerfileArchiveFile))
{
using (var dockerfileArchive = TarArchive.CreateOutputTarArchive(dockerfileArchiveStream))
{
dockerfileArchive.RootPath = dockerfileRootDirectory;

void Tar(string baseDirectory)
{
void WriteEntry(string entry)
{
var tarEntry = TarEntry.CreateEntryFromFile(entry);
tarEntry.Name = entry.Replace(dockerfileRootDirectory, string.Empty);
dockerfileArchive.WriteEntry(tarEntry, File.Exists(entry));
}

if (!dockerfileRootDirectory.Equals(baseDirectory))
{
WriteEntry(baseDirectory);
}

Directory.GetFiles(baseDirectory).ToList().ForEach(WriteEntry);

Directory.GetDirectories(baseDirectory).ToList().ForEach(Tar);
}

Tar(dockerfileRootDirectory);
}
}

return dockerfileArchiveFile;
}

private async Task<string> BuildInternalAsync(ImageFromDockerfileConfiguration config)
{
var dockerfileArchive = CreateDockerfileArchive(config.DockerfileDirectory);

await MetaDataClientImages.Instance.ExistsWithNameAsync(config.Image).ContinueWith(async imageExists =>
{
if (!await imageExists && config.DeleteIfExists)
{
await Docker.Images.DeleteImageAsync(config.Image, new ImageDeleteParameters { Force = true });
}
});

using (var stream = new FileStream(dockerfileArchive, FileMode.Open))
{
await Docker.Images.BuildImageFromDockerfileAsync(stream, new ImageBuildParameters { Dockerfile = "Dockerfile", Tags = new[] { config.Image } });
}

return config.Image;
}
}
}
72 changes: 72 additions & 0 deletions src/DotNet.Testcontainers/Core/DockerfileArchive.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
namespace DotNet.Testcontainers.Core
{
using System;
using System.IO;
using System.Linq;
using ICSharpCode.SharpZipLib.Tar;

public class DockerfileArchive : ITarArchive
{
private static readonly DateTime DisableModTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);

public DockerfileArchive(string baseDirectory) : this(new DirectoryInfo(baseDirectory))
{
}

public DockerfileArchive(DirectoryInfo baseDirectory)
{
this.BaseDirectory = baseDirectory;

this.DockerfileArchiveFile = new FileInfo($"{Path.GetTempPath()}/Dockerfile.tar");

if (!this.BaseDirectory.Exists)
{
throw new ArgumentException($"Directory '{this.BaseDirectory.FullName}' does not exist.");
}

if (!this.BaseDirectory.GetFiles().Any(file => "Dockerfile".Equals(file.Name)))
{
throw new ArgumentException($"Dockerfile does not exist in '{this.BaseDirectory.FullName}'.");
}
}

public DirectoryInfo BaseDirectory { get; }

public FileInfo DockerfileArchiveFile { get; }

public string Tar()
{
using (var dockerfileArchiveStream = File.Create(this.DockerfileArchiveFile.FullName))
{
using (var dockerfileArchive = TarArchive.CreateOutputTarArchive(dockerfileArchiveStream))
{
dockerfileArchive.RootPath = this.BaseDirectory.FullName;

void Tar(string baseDirectory)
{
void WriteEntry(string entry)
{
var tarEntry = TarEntry.CreateEntryFromFile(entry);
tarEntry.Name = entry.Replace(dockerfileArchive.RootPath, string.Empty);
tarEntry.ModTime = DisableModTime;
dockerfileArchive.WriteEntry(tarEntry, File.Exists(entry));
}

if (!dockerfileArchive.RootPath.Equals(baseDirectory))
{
WriteEntry(baseDirectory);
}

Directory.GetFiles(baseDirectory).ToList().ForEach(WriteEntry);

Directory.GetDirectories(baseDirectory).ToList().ForEach(Tar);
}

Tar(this.BaseDirectory.FullName);
}
}

return this.DockerfileArchiveFile.FullName;
}
}
}
7 changes: 7 additions & 0 deletions src/DotNet.Testcontainers/Core/ITarArchive.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace DotNet.Testcontainers.Core
{
public interface ITarArchive
{
string Tar();
}
}

0 comments on commit 1816910

Please sign in to comment.