2022-08-30 12:17:35 +02:00
|
|
|
using GitHub.Runner.Worker;
|
|
|
|
|
using GitHub.Runner.Worker.Container;
|
|
|
|
|
using Xunit;
|
2022-08-31 10:05:44 +00:00
|
|
|
using Moq;
|
|
|
|
|
using GitHub.Runner.Worker.Container.ContainerHooks;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
2022-09-14 08:10:03 +00:00
|
|
|
using GitHub.DistributedTask.WebApi;
|
|
|
|
|
using System;
|
2022-08-30 12:17:35 +02:00
|
|
|
|
|
|
|
|
namespace GitHub.Runner.Common.Tests.Worker
|
|
|
|
|
{
|
2022-08-31 10:05:44 +00:00
|
|
|
|
2022-08-30 12:17:35 +02:00
|
|
|
public sealed class ContainerOperationProviderL0
|
|
|
|
|
{
|
2022-08-31 10:05:44 +00:00
|
|
|
|
|
|
|
|
private TestHostContext _hc;
|
|
|
|
|
private Mock<IExecutionContext> _ec;
|
|
|
|
|
private Mock<IDockerCommandManager> _dockerManager;
|
|
|
|
|
private Mock<IContainerHookManager> _containerHookManager;
|
|
|
|
|
private ContainerOperationProvider containerOperationProvider;
|
2022-08-31 13:55:18 +00:00
|
|
|
private Mock<IJobServerQueue> serverQueue;
|
|
|
|
|
private Mock<IPagingLogger> pagingLogger;
|
2022-08-31 10:05:44 +00:00
|
|
|
private List<string> healthyDockerStatus = new List<string> { "healthy" };
|
2022-09-14 08:10:03 +00:00
|
|
|
private List<string> unhealthyDockerStatus = new List<string> { "unhealthy" };
|
2022-09-16 11:09:55 +00:00
|
|
|
private List<string> emptyDockerStatus = new List<string> { "" };
|
2022-08-31 10:05:44 +00:00
|
|
|
private List<string> dockerLogs = new List<string> { "log1", "log2", "log3" };
|
2022-09-16 11:09:55 +00:00
|
|
|
string healthCheck = "--format=\"{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}\"";
|
2022-08-30 12:17:35 +02:00
|
|
|
|
2022-09-14 08:10:03 +00:00
|
|
|
List<ContainerInfo> containers = new List<ContainerInfo>();
|
2022-08-31 13:55:18 +00:00
|
|
|
|
2022-09-14 08:10:03 +00:00
|
|
|
[Fact]
|
|
|
|
|
[Trait("Level", "L0")]
|
|
|
|
|
[Trait("Category", "Worker")]
|
|
|
|
|
public async void RunServiceContainersHealthcheck_UnhealthyServiceContainer_AssertFailedTask()
|
|
|
|
|
{
|
|
|
|
|
//Arrange
|
|
|
|
|
Setup();
|
2022-09-16 11:09:55 +00:00
|
|
|
_dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), healthCheck)).Returns(Task.FromResult(unhealthyDockerStatus));
|
2022-08-31 13:55:18 +00:00
|
|
|
|
|
|
|
|
//Act
|
2022-09-14 08:10:03 +00:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await containerOperationProvider.RunContainersHealthcheck(_ec.Object, containers);
|
|
|
|
|
}
|
2022-09-16 09:23:44 +02:00
|
|
|
catch (InvalidOperationException)
|
2022-09-16 07:53:12 +00:00
|
|
|
{
|
|
|
|
|
|
2022-09-16 09:22:46 +02:00
|
|
|
//Assert
|
|
|
|
|
Assert.Equal(TaskResult.Failed, _ec.Object.Result ?? TaskResult.Failed);
|
2022-09-16 11:09:55 +00:00
|
|
|
_dockerManager.Verify(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), It.IsAny<string>()), Times.Once());
|
2022-09-15 19:17:22 +00:00
|
|
|
}
|
2022-08-30 12:17:35 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-16 07:53:12 +00:00
|
|
|
[Fact]
|
|
|
|
|
[Trait("Level", "L0")]
|
|
|
|
|
[Trait("Category", "Worker")]
|
|
|
|
|
public async void RunServiceContainersHealthcheck_UnhealthyServiceContainer_AssertExceptionThrown()
|
|
|
|
|
{
|
|
|
|
|
//Arrange
|
|
|
|
|
Setup();
|
2022-09-16 11:09:55 +00:00
|
|
|
_dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), healthCheck)).Returns(Task.FromResult(unhealthyDockerStatus));
|
2022-09-16 07:53:12 +00:00
|
|
|
|
|
|
|
|
//Act and Assert
|
|
|
|
|
await Assert.ThrowsAsync<InvalidOperationException>(() => containerOperationProvider.RunContainersHealthcheck(_ec.Object, containers));
|
2022-09-16 11:09:55 +00:00
|
|
|
_dockerManager.Verify(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), It.IsAny<string>()), Times.Once());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
[Trait("Level", "L0")]
|
|
|
|
|
[Trait("Category", "Worker")]
|
|
|
|
|
public async void RunServiceContainersHealthcheck_HealthyServiceContainer_AssertSucceededTask()
|
|
|
|
|
{
|
|
|
|
|
//Arrange
|
|
|
|
|
Setup();
|
|
|
|
|
_dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), healthCheck)).Returns(Task.FromResult(healthyDockerStatus));
|
|
|
|
|
|
|
|
|
|
//Act
|
|
|
|
|
await containerOperationProvider.RunContainersHealthcheck(_ec.Object, containers);
|
|
|
|
|
|
|
|
|
|
//Assert
|
|
|
|
|
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
|
|
|
|
_dockerManager.Verify(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), It.IsAny<string>()), Times.Once());
|
2022-09-16 07:53:12 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-14 08:10:03 +00:00
|
|
|
[Fact]
|
|
|
|
|
[Trait("Level", "L0")]
|
|
|
|
|
[Trait("Category", "Worker")]
|
2022-09-16 11:09:55 +00:00
|
|
|
public async void RunServiceContainersHealthcheck_ServiceContainerWithoutHealthcheckAndWithOkExitStatus_AssertSucceededTask()
|
2022-09-14 08:10:03 +00:00
|
|
|
{
|
2022-09-16 11:09:55 +00:00
|
|
|
|
|
|
|
|
string exitCode = "--format=\"{{print .State.ExitCode}}\"";
|
2022-09-14 08:10:03 +00:00
|
|
|
//Arrange
|
|
|
|
|
Setup();
|
2022-09-16 11:09:55 +00:00
|
|
|
_dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), healthCheck)).Returns(Task.FromResult(emptyDockerStatus));
|
|
|
|
|
_dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), exitCode)).Returns(Task.FromResult(new List<string> { "0" }));
|
2022-09-14 08:10:03 +00:00
|
|
|
|
|
|
|
|
//Act
|
2022-09-16 07:53:12 +00:00
|
|
|
await containerOperationProvider.RunContainersHealthcheck(_ec.Object, containers);
|
2022-08-31 10:05:44 +00:00
|
|
|
|
2022-09-14 08:10:03 +00:00
|
|
|
//Assert
|
|
|
|
|
Assert.Equal(TaskResult.Succeeded, _ec.Object.Result ?? TaskResult.Succeeded);
|
2022-09-16 11:09:55 +00:00
|
|
|
_dockerManager.Verify(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), It.IsAny<string>()), Times.Exactly(2));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
[Trait("Level", "L0")]
|
|
|
|
|
[Trait("Category", "Worker")]
|
|
|
|
|
public async void RunServiceContainersHealthcheck_ServiceContainerWithoutHealthcheckAndWithErrorExitStatus_AssertSucceededTask()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
string exitCode = "--format=\"{{print .State.ExitCode}}\"";
|
|
|
|
|
//Arrange
|
|
|
|
|
Setup();
|
|
|
|
|
_dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), healthCheck)).Returns(Task.FromResult(emptyDockerStatus));
|
|
|
|
|
_dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), exitCode)).Returns(Task.FromResult(new List<string> { "127" }));
|
|
|
|
|
|
|
|
|
|
//Act
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await containerOperationProvider.RunContainersHealthcheck(_ec.Object, containers);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (InvalidOperationException)
|
|
|
|
|
{
|
|
|
|
|
//Assert
|
|
|
|
|
Assert.Equal(TaskResult.Failed, _ec.Object.Result ?? TaskResult.Failed);
|
|
|
|
|
_dockerManager.Verify(x => x.DockerInspect(_ec.Object, It.IsAny<string>(), It.IsAny<string>()), Times.Exactly(2));
|
|
|
|
|
}
|
2022-09-14 08:10:03 +00:00
|
|
|
|
|
|
|
|
}
|
2022-09-16 09:23:32 +02:00
|
|
|
|
2022-08-31 10:05:44 +00:00
|
|
|
private void Setup([CallerMemberName] string testName = "")
|
|
|
|
|
{
|
2022-09-14 08:10:03 +00:00
|
|
|
containers.Add(new ContainerInfo() { ContainerImage = "ubuntu:16.04" });
|
2022-09-16 09:23:17 +02:00
|
|
|
_hc = new TestHostContext(this, testName);
|
2022-08-31 10:05:44 +00:00
|
|
|
_ec = new Mock<IExecutionContext>();
|
2022-08-31 13:55:18 +00:00
|
|
|
serverQueue = new Mock<IJobServerQueue>();
|
|
|
|
|
pagingLogger = new Mock<IPagingLogger>();
|
2022-08-31 10:05:44 +00:00
|
|
|
|
|
|
|
|
_dockerManager = new Mock<IDockerCommandManager>();
|
|
|
|
|
_containerHookManager = new Mock<IContainerHookManager>();
|
|
|
|
|
containerOperationProvider = new ContainerOperationProvider();
|
|
|
|
|
|
2022-08-31 13:55:18 +00:00
|
|
|
_hc.SetSingleton<IDockerCommandManager>(_dockerManager.Object);
|
|
|
|
|
_hc.SetSingleton<IJobServerQueue>(serverQueue.Object);
|
|
|
|
|
_hc.SetSingleton<IPagingLogger>(pagingLogger.Object);
|
|
|
|
|
|
2022-08-31 10:05:44 +00:00
|
|
|
_hc.SetSingleton<IDockerCommandManager>(_dockerManager.Object);
|
|
|
|
|
_hc.SetSingleton<IContainerHookManager>(_containerHookManager.Object);
|
|
|
|
|
|
|
|
|
|
_ec.Setup(x => x.Global).Returns(new GlobalContext());
|
|
|
|
|
|
|
|
|
|
containerOperationProvider.Initialize(_hc);
|
|
|
|
|
}
|
2022-08-30 12:17:35 +02:00
|
|
|
}
|
|
|
|
|
}
|