From a240d03a70c070150d3c755a8bb97fcc17173240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igr=20Alex=C3=A1nder=20Fern=C3=A1ndez=20Sa=C3=BAco?= Date: Tue, 31 Mar 2020 17:48:11 -0400 Subject: [PATCH 1/6] DockerImagePuller checks if the images is already installed before pull it --- .../DockerImagePuller.cs | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs index e88dfdce7..4e85231cf 100644 --- a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs +++ b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Tye.Hosting.Model; @@ -66,16 +67,39 @@ private async Task PullContainerAsync(string image) { await Task.Yield(); + string name = image; + string version = "latest"; + var idx = image.LastIndexOf(":"); + if (image.IndexOf("/") < idx) + { + name = image.Substring(0, idx); + version = image.Substring(idx + 1); + } + + string output = string.Empty; + await ProcessUtil.RunAsync( + "docker", + "images", + outputDataReceived: data => output += data + '\n', + throwOnError: false); + + var matchCollection = Regex.Matches(output, @"([^\s]+)\s+([^\s]+).+"); + if (matchCollection.Any(match => match.Groups[1].Value == name && match.Groups[2].Value == version)) + { + _logger.LogInformation("Docker image {image} already installed", image); + return; + } + var command = $"pull {image}"; _logger.LogInformation("Running docker command {command}", command); var result = await ProcessUtil.RunAsync( - "docker", - command, - outputDataReceived: data => _logger.LogInformation("{Image}: " + data, image), - errorDataReceived: data => _logger.LogInformation("{Image}: " + data, image), - throwOnError: false); + "docker", + command, + outputDataReceived: data => _logger.LogInformation("{Image}: " + data, image), + errorDataReceived: data => _logger.LogInformation("{Image}: " + data, image), + throwOnError: false); if (result.ExitCode != 0) { From b7f615d19f4092fa08e447a4be698ec0f8ca1a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igr=20Alex=C3=A1nder=20Fern=C3=A1ndez=20Sa=C3=BAco?= Date: Tue, 31 Mar 2020 20:43:06 -0400 Subject: [PATCH 2/6] Use --filter and --format options to filter and format the output docker images command --- src/Microsoft.Tye.Hosting/DockerImagePuller.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs index 4e85231cf..45c61e379 100644 --- a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs +++ b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs @@ -76,15 +76,15 @@ private async Task PullContainerAsync(string image) version = image.Substring(idx + 1); } + bool installed = false; string output = string.Empty; - await ProcessUtil.RunAsync( - "docker", - "images", - outputDataReceived: data => output += data + '\n', - throwOnError: false); + var processResult = await ProcessUtil.RunAsync( + "docker", + $"images --filter \"reference={name}:{version}\" --format \"{{{{.ID}}}}\"", + outputDataReceived: data => installed = true, + throwOnError: false); - var matchCollection = Regex.Matches(output, @"([^\s]+)\s+([^\s]+).+"); - if (matchCollection.Any(match => match.Groups[1].Value == name && match.Groups[2].Value == version)) + if (installed) { _logger.LogInformation("Docker image {image} already installed", image); return; From a18bfe9a728bd6502fd416a1ae133803ec53096d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igr=20Alex=C3=A1nder=20Fern=C3=A1ndez=20Sa=C3=BAco?= Date: Tue, 31 Mar 2020 20:44:33 -0400 Subject: [PATCH 3/6] Optimize usings --- src/Microsoft.Tye.Hosting/DockerImagePuller.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs index 45c61e379..f90c59f4c 100644 --- a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs +++ b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Tye.Hosting.Model; From e03b39e5c7998c714cefabfbfc8b6416f468b9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igr=20Alex=C3=A1nder=20Fern=C3=A1ndez=20Sa=C3=BAco?= Date: Tue, 31 Mar 2020 20:46:53 -0400 Subject: [PATCH 4/6] Remove unused variable --- src/Microsoft.Tye.Hosting/DockerImagePuller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs index f90c59f4c..02a06d375 100644 --- a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs +++ b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs @@ -75,7 +75,7 @@ private async Task PullContainerAsync(string image) bool installed = false; string output = string.Empty; - var processResult = await ProcessUtil.RunAsync( + await ProcessUtil.RunAsync( "docker", $"images --filter \"reference={name}:{version}\" --format \"{{{{.ID}}}}\"", outputDataReceived: data => installed = true, From af18a778b571542aebbf5c23d19dd16745070413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igr=20Alex=C3=A1nder=20Fern=C3=A1ndez=20Sa=C3=BAco?= Date: Tue, 31 Mar 2020 23:01:42 -0400 Subject: [PATCH 5/6] Improve PullContainerAsync implementation and also throws CommandException if docker images command failed --- .../DockerImagePuller.cs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs index 02a06d375..f78dea2c5 100644 --- a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs +++ b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs @@ -64,23 +64,18 @@ private async Task PullContainerAsync(string image) { await Task.Yield(); - string name = image; - string version = "latest"; - var idx = image.LastIndexOf(":"); - if (image.IndexOf("/") < idx) - { - name = image.Substring(0, idx); - version = image.Substring(idx + 1); - } - bool installed = false; - string output = string.Empty; - await ProcessUtil.RunAsync( + var result = await ProcessUtil.RunAsync( "docker", - $"images --filter \"reference={name}:{version}\" --format \"{{{{.ID}}}}\"", + $"images --filter \"reference={image}\" --format \"{{{{.ID}}}}\"", outputDataReceived: data => installed = true, throwOnError: false); + if (result.ExitCode != 0) + { + throw new CommandException("Docker images command failed"); + } + if (installed) { _logger.LogInformation("Docker image {image} already installed", image); @@ -91,7 +86,7 @@ await ProcessUtil.RunAsync( _logger.LogInformation("Running docker command {command}", command); - var result = await ProcessUtil.RunAsync( + result = await ProcessUtil.RunAsync( "docker", command, outputDataReceived: data => _logger.LogInformation("{Image}: " + data, image), From 26a1cecf8ee299802223448fb4cee5c7bb41196c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igr=20Alex=C3=A1nder=20Fern=C3=A1ndez=20Sa=C3=BAco?= Date: Wed, 1 Apr 2020 11:30:03 -0400 Subject: [PATCH 6/6] Improve the approach to determine if it's installed and print the output of this command images in case of failure --- src/Microsoft.Tye.Hosting/DockerImagePuller.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs index f78dea2c5..3e6612603 100644 --- a/src/Microsoft.Tye.Hosting/DockerImagePuller.cs +++ b/src/Microsoft.Tye.Hosting/DockerImagePuller.cs @@ -64,19 +64,18 @@ private async Task PullContainerAsync(string image) { await Task.Yield(); - bool installed = false; var result = await ProcessUtil.RunAsync( "docker", $"images --filter \"reference={image}\" --format \"{{{{.ID}}}}\"", - outputDataReceived: data => installed = true, throwOnError: false); if (result.ExitCode != 0) { + _logger.LogInformation("{Image}: " + result.StandardError, image); throw new CommandException("Docker images command failed"); } - if (installed) + if (!string.IsNullOrWhiteSpace(result.StandardOutput)) { _logger.LogInformation("Docker image {image} already installed", image); return;