/// <inheritdoc /> protected override async Task ContainerStarting() { await base.ContainerStarting(); _logger.LogDebug("Starting reaper ..."); await ResourceReaper.StartAsync(DockerClient); }
public async Task ShouldReapContainersWhenReaperStops() { // act ResourceReaper.Dispose(); // assert var ryukStopped = false; while (!ryukStopped) { try { await _dockerClient.Containers.InspectContainerAsync(ResourceReaper.GetRyukContainerId()); } catch (DockerContainerNotFoundException) { ryukStopped = true; } } var exception = await Record.ExceptionAsync(async() => await _dockerClient.Containers.InspectContainerAsync(_container.ContainerId)); Assert.IsType <DockerContainerNotFoundException>(exception); }
/// <inheritdoc /> public async Task <string> RunAsync(ITestcontainersConfiguration configuration, CancellationToken ct = default) { // TODO: Workaround until we have a Windows Docker image of Ryuk var isWindowsEngineEnabled = await this.GetIsWindowsEngineEnabled(ct) .ConfigureAwait(false); if (!isWindowsEngineEnabled && ResourceReaper.DefaultSessionId.ToString("D").Equals(configuration.Labels[ResourceReaper.ResourceReaperSessionLabel], StringComparison.OrdinalIgnoreCase)) { _ = await ResourceReaper.GetAndStartDefaultAsync(configuration.DockerEndpointAuthConfig, ct) .ConfigureAwait(false); } if (!await this.images.ExistsWithNameAsync(configuration.Image.FullName, ct) .ConfigureAwait(false)) { var authConfig = default(DockerRegistryAuthenticationConfiguration).Equals(configuration.DockerRegistryAuthConfig) ? this.registryAuthenticationProvider.GetAuthConfig(configuration.Image.GetHostname()) : configuration.DockerRegistryAuthConfig; await this.images.CreateAsync(configuration.Image, authConfig, ct) .ConfigureAwait(false); } var id = await this.containers.RunAsync(configuration, ct) .ConfigureAwait(false); return(id); }
public async Task ResourceReaperShouldTimeoutIfInitializationFails() { var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, null, "nginx"); _ = await Assert.ThrowsAsync <ResourceReaperException>(() => resourceReaperTask); Assert.Equal(new[] { ResourceReaperState.Created, ResourceReaperState.InitializingConnection }, this.stateChanges); }
public async Task GetAndStartNewAsyncShouldBeCancellableDuringInitializingConnection() { ResourceReaper.StateChanged += this.CancelOnInitializingConnection; var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, null, "nginx", TimeSpan.FromSeconds(60), this.cts.Token); _ = await Assert.ThrowsAsync <ResourceReaperException>(() => resourceReaperTask); Assert.Equal(new[] { ResourceReaperState.Created, ResourceReaperState.InitializingConnection }, this.stateChanges); }
public async Task GetAndStartNewAsyncShouldBeCancellableDuringContainerStart() { ResourceReaper.StateChanged += this.CancelOnCreated; var resourceReaperTask = ResourceReaper.GetAndStartNewAsync(this.sessionId, null, "nginx", TimeSpan.FromSeconds(60), this.cts.Token); _ = await Assert.ThrowsAnyAsync <OperationCanceledException>(() => resourceReaperTask); Assert.Equal(new[] { ResourceReaperState.Created }, this.stateChanges); }
public async Task InitializeAsync() { if (Docker.Exists(DockerResource.Container, DefaultRyukContainerName)) { var resourceReaper = await ResourceReaper.GetAndStartDefaultAsync() .ConfigureAwait(false); await resourceReaper.DisposeAsync() .ConfigureAwait(false); } }
public async Task ShouldReconnectIfConnectionDrops() { // arrange ResourceReaper.KillTcpConnection(); // act ResourceReaper.RegisterFilterForCleanup(new LabelsFilter("key", "value")); // assert Assert.True(await ResourceReaper.IsConnected()); }
public async Task DisposeAsyncShouldAwaitConnectionTerminatedState() { // Given var resourceReaper = await ResourceReaper.GetAndStartNewAsync(this.sessionId) .ConfigureAwait(false); // When await resourceReaper.DisposeAsync() .ConfigureAwait(false); // Then Assert.Equal(Enum.GetValues(typeof(ResourceReaperState)).Cast <ResourceReaperState>(), this.stateChanges); }
private async Task CreateNetwork(CancellationToken ct) { _logger.LogInformation("Creating network: {}", NetworkName); _logger.LogDebug("Starting reaper ..."); await ResourceReaper.StartAsync(DockerClient, _loggerFactory); _logger.LogDebug("Adding session labels to network: {}", ResourceReaper.SessionId); foreach (var label in ResourceReaper.Labels) { Labels.Add(label.Key, label.Value); } var response = await DockerClient.Networks.CreateNetworkAsync( new NetworksCreateParameters { Name = NetworkName, CheckDuplicate = true, Labels = Labels }, ct); NetworkId = response.ID; }
public Task InitializeAsync() { return(Task.WhenAll(ResourceReaper.GetAndStartNewAsync(this.SessionId), this.volume.CreateAsync())); }
public async Task InitializeAsync() { this.resourceReaper = await ResourceReaper.GetAndStartNewAsync() .ConfigureAwait(false); }
private bool IsTest(ResourceReaper resourceReaper) { return(resourceReaper.SessionId.Equals(this.sessionId)); }
/// <summary> /// Runs the docker image build command to build this image /// </summary> /// <inheritdoc /> public override async Task <string> Resolve(CancellationToken ct = default) { if (ct.IsCancellationRequested) { return(null); } if (DeleteOnExit) { ResourceReaper.RegisterImageForCleanup(ImageName, DockerClient); } _logger.LogDebug("Begin building image: {}", ImageName); var tempTarPath = Path.Combine(Path.GetTempPath(), ImageName.Replace('/', '_') + ".tar"); try { using (var tempFile = new FileStream(tempTarPath, FileMode.Create)) using (var tarArchive = TarArchive.CreateOutputTarArchive(tempFile)) { if (!string.IsNullOrWhiteSpace(BasePath)) { // the algorithm here is carefully crafted to minimise the use of // Path.GetFullPath. Path.GetFullPath is used very sparingly and // completely avoided in loops. The reason is because Path.GetFullPath // is a very expensive call and can reduce CPU time by at least 1 order // of magnitude if avoided var fullBasePath = Path.GetFullPath(OS.NormalizePath(BasePath)); var ignoreFullPaths = GetIgnores(fullBasePath); // sending a full path will result in entries with full path var allFullPaths = GetAllFilesInDirectory(fullBasePath); // a thread pool that is starved can decrease the performance of // this method dramatically. Using `AsParallel()` will circumvent such issues. // as a result, methods and classes used by this needs to be thread safe. var validFullPaths = allFullPaths .AsParallel() .Where(f => !IsFileIgnored(ignoreFullPaths, f)); foreach (var fullPath in validFullPaths) { // we can safely perform a substring without expanding the paths // using Path.GetFullPath because we know fullBasePath has already been // expanded and the paths in validFullPaths are derived from fullBasePath var relativePath = fullPath.Substring(fullBasePath.Length); // if fullBasePath does not end with directory separator, // relativePath will start with directory separator and that should not be the case if (relativePath.StartsWith(Path.DirectorySeparatorChar.ToString())) { relativePath = relativePath.Substring(1); } await new MountableFile(fullPath) .TransferTo(tarArchive, relativePath, ct) .ConfigureAwait(false); } _logger.LogDebug("Transferred base path [{}] into tar archive", BasePath); } foreach (var entry in Transferables) { var destinationPath = entry.Key; var transferable = entry.Value; await transferable .TransferTo(tarArchive, destinationPath, ct) .ConfigureAwait(false); _logger.LogDebug("Transferred [{}] into tar archive", destinationPath); } tarArchive.Close(); } if (ct.IsCancellationRequested) { return(null); } var buildImageParameters = new ImageBuildParameters { Dockerfile = DockerfilePath, Labels = DeleteOnExit ? ResourceReaper.Labels : null, Tags = new List <string> { ImageName } }; using (var tempFile = new FileStream(tempTarPath, FileMode.Open)) { var output = await DockerClient.Images.BuildImageFromDockerfileAsync(tempFile, buildImageParameters, ct); using (var reader = new StreamReader(output)) { while (!reader.EndOfStream) { _logger.LogTrace(reader.ReadLine()); } } } } finally { File.Delete(tempTarPath); } _logger.LogInformation("Dockerfile image built: {}", ImageName); // we should not catch exceptions thrown by inspect because the image is // expected to be available since we've just built it var image = await DockerClient.Images.InspectImageAsync(ImageName, ct); ImageId = image.ID; return(ImageId); }