-
-
Notifications
You must be signed in to change notification settings - Fork 294
/
Copy pathDockerfileArchive.cs
111 lines (94 loc) · 4.3 KB
/
DockerfileArchive.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
namespace DotNet.Testcontainers.Images
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using DotNet.Testcontainers.Configurations;
using ICSharpCode.SharpZipLib.Tar;
using Microsoft.Extensions.Logging;
/// <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 IOperatingSystem OS = new Unix();
private readonly DirectoryInfo dockerfileDirectory;
private readonly IDockerImage image;
private readonly ILogger logger;
/// <summary>
/// Initializes a new instance of the <see cref="DockerfileArchive" /> class.
/// </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>
/// <param name="logger">The logger.</param>
public DockerfileArchive(string dockerfileDirectory, string dockerfile, IDockerImage image, ILogger logger)
: this(new DirectoryInfo(dockerfileDirectory), dockerfile, image, logger)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DockerfileArchive" /> class.
/// </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>
/// <param name="logger">The logger.</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, ILogger logger)
{
if (!dockerfileDirectory.Exists)
{
throw new ArgumentException($"Directory '{dockerfileDirectory.FullName}' does not exist.");
}
if (!dockerfileDirectory.GetFiles(dockerfile, SearchOption.TopDirectoryOnly).Any())
{
throw new ArgumentException($"{dockerfile} does not exist in '{dockerfileDirectory.FullName}'.");
}
this.dockerfileDirectory = dockerfileDirectory;
this.image = image;
this.logger = logger;
}
/// <inheritdoc />
public string Tar()
{
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", this.logger);
using (var stream = new FileStream(dockerfileArchivePath, FileMode.Create))
{
using (var tarArchive = TarArchive.CreateOutputTarArchive(stream))
{
tarArchive.RootPath = OS.NormalizePath(this.dockerfileDirectory.FullName);
foreach (var file in GetFiles(this.dockerfileDirectory.FullName))
{
// SharpZipLib drops the root path: https://github.com/icsharpcode/SharpZipLib/pull/582.
var relativePath = file.Substring(this.dockerfileDirectory.FullName.Length + 1);
if (dockerIgnoreFile.Denies(relativePath))
{
continue;
}
var tarEntry = TarEntry.CreateEntryFromFile(file);
tarEntry.Name = relativePath;
tarArchive.WriteEntry(tarEntry, true);
}
}
}
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();
}
}
}