| File: Tasks\ParseContainerProperties.cs | Web Access |
| Project: src\sdk\src\Containers\Microsoft.NET.Build.Containers\Microsoft.NET.Build.Containers.csproj (Microsoft.NET.Build.Containers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Build.Framework; using Microsoft.NET.Build.Containers.Resources; namespace Microsoft.NET.Build.Containers.Tasks; public sealed class ParseContainerProperties : Microsoft.Build.Utilities.Task { /// <summary> /// The full base image name. mcr.microsoft.com/dotnet/runtime:6.0, for example. /// </summary> [Required] public string FullyQualifiedBaseImageName { get; set; } /// <summary> /// The registry to push the new container to. This will be null if the container is to be pushed to a local registry. /// </summary> public string ContainerRegistry { get; set; } /// <summary> /// The name of the container to be created. /// </summary> [Required] public string ContainerRepository { get; set; } /// <summary> /// The tag for the container to be created. /// </summary> public string ContainerImageTag { get; set; } /// <summary> /// The tags for the container to be created. /// </summary> public string[] ContainerImageTags { get; set; } /// <summary> /// Container environment variables to set. /// </summary> public ITaskItem[] ContainerEnvironmentVariables { get; set; } [Output] public string ParsedContainerRegistry { get; private set; } [Output] public string ParsedContainerImage { get; private set; } [Output] public string ParsedContainerTag { get; private set; } [Output] public string ParsedContainerDigest { get; private set; } [Output] public string NewContainerRegistry { get; private set; } [Output] public string NewContainerRepository { get; private set; } [Output] public string[] NewContainerTags { get; private set; } [Output] public ITaskItem[] NewContainerEnvironmentVariables { get; private set; } public ParseContainerProperties() { FullyQualifiedBaseImageName = ""; ContainerRegistry = ""; ContainerRepository = ""; ContainerImageTag = ""; ContainerImageTags = Array.Empty<string>(); ContainerEnvironmentVariables = Array.Empty<ITaskItem>(); ParsedContainerRegistry = ""; ParsedContainerImage = ""; ParsedContainerTag = ""; ParsedContainerDigest = ""; NewContainerRegistry = ""; NewContainerRepository = ""; NewContainerTags = Array.Empty<string>(); NewContainerEnvironmentVariables = Array.Empty<ITaskItem>(); TaskResources = Resource.Manager; } public override bool Execute() { string[] validTags; if (!string.IsNullOrEmpty(ContainerImageTag) && ContainerImageTags.Length >= 1) { Log.LogErrorWithCodeFromResources(nameof(Strings.AmbiguousTags), nameof(ContainerImageTag), nameof(ContainerImageTags)); return !Log.HasLoggedErrors; } if (!string.IsNullOrEmpty(ContainerImageTag)) { if (ContainerHelpers.IsValidImageTag(ContainerImageTag)) { validTags = new[] { ContainerImageTag }; } else { validTags = Array.Empty<string>(); Log.LogErrorWithCodeFromResources(nameof(Strings.InvalidTag), nameof(ContainerImageTag), ContainerImageTag); } } else if (ContainerImageTags.Length != 0) { (validTags, var invalidTags) = TryValidateTags(ContainerImageTags); if (invalidTags.Any()) { Log.LogErrorWithCodeFromResources(nameof(Strings.InvalidTags), nameof(ContainerImageTags), String.Join(",", invalidTags)); return !Log.HasLoggedErrors; } } else { validTags = Array.Empty<string>(); } if (!string.IsNullOrEmpty(ContainerRegistry) && !ContainerHelpers.IsValidRegistry(ContainerRegistry)) { Log.LogErrorWithCodeFromResources(nameof(Strings.CouldntRecognizeRegistry), ContainerRegistry); return !Log.HasLoggedErrors; } ValidateEnvironmentVariables(); if (FullyQualifiedBaseImageName.Contains(' ') && BuildEngine != null) { Log.LogWarningWithCodeFromResources(nameof(Strings.BaseImageNameWithSpaces), nameof(FullyQualifiedBaseImageName)); } FullyQualifiedBaseImageName = FullyQualifiedBaseImageName.Replace(' ', '-'); if (!ContainerHelpers.TryParseFullyQualifiedContainerName(FullyQualifiedBaseImageName, out string? outputReg, out string? outputImage, out string? outputTag, out string? outputDigest, out bool isRegistrySpecified)) { Log.LogErrorWithCodeFromResources(nameof(Strings.BaseImageNameParsingFailed), nameof(FullyQualifiedBaseImageName), FullyQualifiedBaseImageName); return !Log.HasLoggedErrors; } if (!isRegistrySpecified) { Log.LogWarningWithCodeFromResources(nameof(Strings.BaseImageNameRegistryFallback), nameof(FullyQualifiedBaseImageName), ContainerHelpers.DockerRegistryAlias); } var (normalizedRepository, normalizationWarning, normalizationError) = ContainerHelpers.NormalizeRepository(ContainerRepository); if (normalizedRepository is not null) { NewContainerRepository = normalizedRepository; } if (normalizationWarning is (string warningMessageKey, object[] warningParams)) { Log.LogMessageFromResources(warningMessageKey, warningParams); } if (normalizationError is (string errorMessageKey, object[] errorParams)) { Log.LogErrorWithCodeFromResources(errorMessageKey, errorParams); return !Log.HasLoggedErrors; } ParsedContainerRegistry = outputReg ?? ""; ParsedContainerImage = outputImage ?? ""; ParsedContainerTag = outputTag ?? ""; ParsedContainerDigest = outputDigest ?? ""; NewContainerRegistry = ContainerRegistry; NewContainerTags = validTags; if (BuildEngine != null) { Log.LogMessage(MessageImportance.Low, "Parsed the following properties. Note: Spaces are replaced with dashes."); Log.LogMessage(MessageImportance.Low, "Host: {0}", ParsedContainerRegistry); Log.LogMessage(MessageImportance.Low, "Image: {0}", ParsedContainerImage); Log.LogMessage(MessageImportance.Low, "Tag: {0}", ParsedContainerTag); Log.LogMessage(MessageImportance.Low, "Digest: {0}", ParsedContainerDigest); Log.LogMessage(MessageImportance.Low, "Image Name: {0}", NewContainerRepository); Log.LogMessage(MessageImportance.Low, "Image Tags: {0}", string.Join(", ", NewContainerTags)); } return !Log.HasLoggedErrors; } private void ValidateEnvironmentVariables() { var filteredEnvVars = ContainerEnvironmentVariables.Where((x) => ContainerHelpers.IsValidEnvironmentVariable(x.ItemSpec)).ToArray<ITaskItem>(); var badEnvVars = ContainerEnvironmentVariables.Where((x) => !ContainerHelpers.IsValidEnvironmentVariable(x.ItemSpec)); foreach (var badEnvVar in badEnvVars) { if (BuildEngine != null) { Log.LogWarningWithCodeFromResources(nameof(Strings.InvalidEnvVar), nameof(ContainerEnvironmentVariables), badEnvVar.ItemSpec); } } NewContainerEnvironmentVariables = new ITaskItem[filteredEnvVars.Length]; for (int i = 0; i < filteredEnvVars.Length; i++) { NewContainerEnvironmentVariables[i] = filteredEnvVars[i]; } } private static (string[] validTags, string[] invalidTags) TryValidateTags(string[] inputTags) { var v = new List<string>(); var i = new List<string>(); foreach (var tag in inputTags) { if (ContainerHelpers.IsValidImageTag(tag)) { v.Add(tag); } else { i.Add(tag); } } return (v.ToArray(), i.ToArray()); } }