From fec24e834137afe2dc751a38707d0e399c10f8fb Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Fri, 16 Sep 2022 11:09:55 +0000 Subject: [PATCH] Check service exit code if there is no healtcheck configured --- .../ContainerOperationProvider.cs | 7 ++- .../L0/Worker/ContainerOperationProviderL0.cs | 61 +++++++++++++++++-- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/Runner.Worker/ContainerOperationProvider.cs b/src/Runner.Worker/ContainerOperationProvider.cs index 45017133c69..d532f9d87bf 100644 --- a/src/Runner.Worker/ContainerOperationProvider.cs +++ b/src/Runner.Worker/ContainerOperationProvider.cs @@ -435,8 +435,13 @@ private async Task ContainerHealthcheck(IExecutionContext executionConte string serviceHealth = (await _dockerManager.DockerInspect(context: executionContext, dockerObject: container.ContainerId, options: healthCheck)).FirstOrDefault(); if (string.IsNullOrEmpty(serviceHealth)) { + string exitCode = "--format=\"{{print .State.ExitCode}}\""; + string serviceExitCode = (await _dockerManager.DockerInspect(context: executionContext, dockerObject: container.ContainerId, options: exitCode)).FirstOrDefault(); + + // Container has no healthcheck but didn't exit with an error code + if ("0".Equals(serviceExitCode)) return "healthy"; // Container has no HEALTHCHECK - return String.Empty; + else return "unhealthy"; } var retryCount = 0; while (string.Equals(serviceHealth, "starting", StringComparison.OrdinalIgnoreCase)) diff --git a/src/Test/L0/Worker/ContainerOperationProviderL0.cs b/src/Test/L0/Worker/ContainerOperationProviderL0.cs index bfc09f343ac..8d4c2bb66e4 100644 --- a/src/Test/L0/Worker/ContainerOperationProviderL0.cs +++ b/src/Test/L0/Worker/ContainerOperationProviderL0.cs @@ -24,7 +24,9 @@ public sealed class ContainerOperationProviderL0 private Mock pagingLogger; private List healthyDockerStatus = new List { "healthy" }; private List unhealthyDockerStatus = new List { "unhealthy" }; + private List emptyDockerStatus = new List { "" }; private List dockerLogs = new List { "log1", "log2", "log3" }; + string healthCheck = "--format=\"{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}\""; List containers = new List(); @@ -35,7 +37,7 @@ public async void RunServiceContainersHealthcheck_UnhealthyServiceContainer_Asse { //Arrange Setup(); - _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), It.IsAny())).Returns(Task.FromResult(unhealthyDockerStatus)); + _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), healthCheck)).Returns(Task.FromResult(unhealthyDockerStatus)); //Act try @@ -47,6 +49,7 @@ public async void RunServiceContainersHealthcheck_UnhealthyServiceContainer_Asse //Assert Assert.Equal(TaskResult.Failed, _ec.Object.Result ?? TaskResult.Failed); + _dockerManager.Verify(x => x.DockerInspect(_ec.Object, It.IsAny(), It.IsAny()), Times.Once()); } } @@ -57,27 +60,77 @@ public async void RunServiceContainersHealthcheck_UnhealthyServiceContainer_Asse { //Arrange Setup(); - _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), It.IsAny())).Returns(Task.FromResult(unhealthyDockerStatus)); + _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), healthCheck)).Returns(Task.FromResult(unhealthyDockerStatus)); //Act and Assert await Assert.ThrowsAsync(() => containerOperationProvider.RunContainersHealthcheck(_ec.Object, containers)); + _dockerManager.Verify(x => x.DockerInspect(_ec.Object, It.IsAny(), It.IsAny()), 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(), 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(), It.IsAny()), Times.Once()); } [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public async void RunServiceContainersHealthcheck_healthyServiceContainer_AssertSucceededTask() + public async void RunServiceContainersHealthcheck_ServiceContainerWithoutHealthcheckAndWithOkExitStatus_AssertSucceededTask() { + + string exitCode = "--format=\"{{print .State.ExitCode}}\""; //Arrange Setup(); - _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), It.IsAny())).Returns(Task.FromResult(healthyDockerStatus)); + _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), healthCheck)).Returns(Task.FromResult(emptyDockerStatus)); + _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), exitCode)).Returns(Task.FromResult(new List { "0" })); //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(), It.IsAny()), 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(), healthCheck)).Returns(Task.FromResult(emptyDockerStatus)); + _dockerManager.Setup(x => x.DockerInspect(_ec.Object, It.IsAny(), exitCode)).Returns(Task.FromResult(new List { "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(), It.IsAny()), Times.Exactly(2)); + } }